Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5739e2be authored by Hasib Prince's avatar Hasib Prince
Browse files

Merge branch '1709-remove_code_smell' into 'main'

1709 remove code smell

See merge request !396
parents 5fb40257 93493e8d
Loading
Loading
Loading
Loading
Loading
+0 −17
Original line number Diff line number Diff line
@@ -2,13 +2,6 @@
<SmellBaseline>
  <ManuallySuppressedIssues></ManuallySuppressedIssues>
  <CurrentIssues>
    <ID>ComplexCondition:AppPurchaseFragment.kt$AppPurchaseFragment.&lt;no name provided&gt;$url.contains("https://play.google.com/store/apps/details") &amp;&amp; url.contains("raii") &amp;&amp; url.contains("raboi") &amp;&amp; url.contains("rasi") &amp;&amp; url.contains("rapt")</ID>
    <ID>CyclomaticComplexMethod:ApplicationApiImpl.kt$ApplicationApiImpl$private suspend fun generateCleanAPKHome(home: CleanApkHome, appType: String): List&lt;Home&gt;</ID>
    <ID>CyclomaticComplexMethod:ApplicationDiffUtil.kt$ApplicationDiffUtil$override fun areContentsTheSame(oldItem: Application, newItem: Application): Boolean</ID>
    <ID>CyclomaticComplexMethod:CategoryUtils.kt$CategoryUtils$fun provideAppsCategoryIconResource(categoryId: String): Int</ID>
    <ID>CyclomaticComplexMethod:DownloadProgressLD.kt$DownloadProgressLD$override fun observe(owner: LifecycleOwner, observer: Observer&lt;in DownloadProgress&gt;)</ID>
    <ID>CyclomaticComplexMethod:HomeChildFusedAppDiffUtil.kt$HomeChildFusedAppDiffUtil$override fun areContentsTheSame(oldItem: Application, newItem: Application): Boolean</ID>
    <ID>CyclomaticComplexMethod:MainActivity.kt$MainActivity$override fun onCreate(savedInstanceState: Bundle?)</ID>
    <ID>EmptyCatchBlock:NativeDeviceInfoProviderModule.kt$NativeDeviceInfoProviderModule${ }</ID>
    <ID>EmptyFunctionBlock:CleanApkAuthenticator.kt$CleanApkAuthenticator${}</ID>
    <ID>ImplicitDefaultLocale:ApplicationFragment.kt$ApplicationFragment$String.format("%d%%", progressPercentage)</ID>
@@ -21,11 +14,6 @@
    <ID>InvalidPackageDeclaration:Trackers.kt$package foundation.e.apps.data.exodus</ID>
    <ID>LargeClass:ApplicationApiImpl.kt$ApplicationApiImpl : ApplicationApi</ID>
    <ID>LargeClass:ApplicationFragment.kt$ApplicationFragment : TimeoutFragment</ID>
    <ID>LongMethod:ApplicationApiImpl.kt$ApplicationApiImpl$private suspend fun generateCleanAPKHome(home: CleanApkHome, appType: String): List&lt;Home&gt;</ID>
    <ID>LongMethod:ApplicationFragment.kt$ApplicationFragment$private fun observeDownloadStatus(view: View)</ID>
    <ID>LongMethod:CategoryUtils.kt$CategoryUtils$fun provideAppsCategoryIconResource(categoryId: String): Int</ID>
    <ID>LongMethod:MainActivity.kt$MainActivity$override fun onCreate(savedInstanceState: Bundle?)</ID>
    <ID>LongMethod:NativeDeviceInfoProviderModule.kt$NativeDeviceInfoProviderModule$@Singleton @Provides fun provideNativeDeviceProperties( @ApplicationContext context: Context, ): Properties</ID>
    <ID>LongParameterList:ApplicationApiImpl.kt$ApplicationApiImpl$( private val pkgManagerModule: PkgManagerModule, private val pwaManagerModule: PWAManagerModule, private val preferenceManagerModule: PreferenceManagerModule, @Named("gplayRepository") private val gplayRepository: PlayStoreRepository, @Named("cleanApkAppsRepository") private val cleanApkAppsRepository: CleanApkRepository, @Named("cleanApkPWARepository") private val cleanApkPWARepository: CleanApkRepository, @ApplicationContext private val context: Context )</ID>
    <ID>LongParameterList:ApplicationDialogFragment.kt$ApplicationDialogFragment$( drawable: Int = -1, title: String, message: String, positiveButtonText: String = "", positiveButtonAction: (() -&gt; Unit)? = null, cancelButtonText: String = "", cancelButtonAction: (() -&gt; Unit)? = null, cancellable: Boolean = true, onDismissListener: (() -&gt; Unit)? = null, )</ID>
    <ID>LongParameterList:ApplicationListRVAdapter.kt$ApplicationListRVAdapter$( private val applicationInstaller: ApplicationInstaller, private val privacyInfoViewModel: PrivacyInfoViewModel, private val appInfoFetchViewModel: AppInfoFetchViewModel, private val mainActivityViewModel: MainActivityViewModel, private val currentDestinationId: Int, private var lifecycleOwner: LifecycleOwner?, private var paidAppHandler: ((Application) -&gt; Unit)? = null )</ID>
@@ -115,11 +103,6 @@
    <ID>MaxLineLength:UpdatesViewModel.kt$UpdatesViewModel$return updatesList.value?.first?.any { it.status == Status.UPDATABLE || it.status == Status.INSTALLATION_ISSUE } == true</ID>
    <ID>MaxLineLength:UpdatesWorker.kt$UpdatesWorker$applicationContext.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED</ID>
    <ID>MayBeConst:EcloudApiInterface.kt$EcloudApiInterface.Companion$val BASE_URL = "https://eu.gtoken.ecloud.global/"</ID>
    <ID>NestedBlockDepth:ApplicationApiImpl.kt$ApplicationApiImpl$private suspend fun generateCleanAPKHome(home: CleanApkHome, appType: String): List&lt;Home&gt;</ID>
    <ID>NestedBlockDepth:DownloadManager.kt$DownloadManager$fun checkDownloadProgress( downloadId: Long, filePath: String = "", downloadCompleted: ((Boolean, String) -&gt; Unit)? )</ID>
    <ID>NestedBlockDepth:PWAManagerModule.kt$PWAManagerModule$fun getPwaStatus(application: Application): Status</ID>
    <ID>NestedBlockDepth:PkgManagerBR.kt$PkgManagerBR$override fun onReceive(context: Context?, intent: Intent?)</ID>
    <ID>NestedBlockDepth:SettingsFragment.kt$SettingsFragment$override fun onViewCreated(view: View, savedInstanceState: Bundle?)</ID>
    <ID>PrintStackTrace:CommonUtilsModule.kt$CommonUtilsModule$e</ID>
    <ID>PrintStackTrace:EcloudRepository.kt$EcloudRepository$e</ID>
    <ID>PrintStackTrace:InstallWorkManager.kt$InstallWorkManager$e</ID>
+152 −99
Original line number Diff line number Diff line
@@ -78,20 +78,50 @@ class MainActivity : AppCompatActivity() {
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val bottomNavigationView = binding.bottomNavigationView
        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment
        val navController = navHostFragment.navController
        bottomNavigationView.setupWithNavController(navController)
        setupBottomNavItemSelectedListener(bottomNavigationView, navHostFragment, navController)
        val (bottomNavigationView, navController) = setupBootomNav()

        var hasInternet = true

        viewModel = ViewModelProvider(this)[MainActivityViewModel::class.java]
        signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java]
        loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
        setupViewModels()

        setupNavigations(navController)

        if (intent.hasExtra(UpdatesNotifier.UPDATES_NOTIFICATION_CLICK_EXTRA)) {
            bottomNavigationView.selectedItemId = R.id.updatesFragment
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            viewModel.createNotificationChannels()
        }

        viewModel.setupConnectivityManager(this.applicationContext)

        hasInternet = observeInternetConnections(hasInternet)

        observeAuthObjects(navController)

        setupDestinationChangedListener(navController, hasInternet, bottomNavigationView)

        observePurchaseAppPage()

        observeErrorMessage()

        // navOptions and activityNavController for TOS and SignIn Fragments
        observeErrorMessageString()

        observeIsAppPurchased()

        observePurchaseDeclined()

        if (viewModel.internetConnection.value != true) {
            showNoInternet()
        }

        viewModel.updateAppWarningList()

        observeEvents()
    }

    private fun setupNavigations(navController: NavController) {
        val navOptions = NavOptions.Builder()
            .setPopUpTo(R.id.navigation_resource, true)
            .build()
@@ -104,79 +134,63 @@ class MainActivity : AppCompatActivity() {
                loginViewModel.startLoginFlow()
            }
        }
    }

        viewModel.setupConnectivityManager(this.applicationContext)

        viewModel.internetConnection.observe(this) { isInternetAvailable ->
            hasInternet = isInternetAvailable
            if (isInternetAvailable) {
                binding.noInternet.visibility = View.GONE
                binding.fragment.visibility = View.VISIBLE
    private fun observeEvents() {
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    observeInvalidAuth()
                }

                launch {
                    observeTooManyRequests()
                }

        loginViewModel.authObjects.distinctUntilChanged().observe(this) {
            when {
                it == null -> return@observe
                it.isEmpty() -> {
                    // No auth type defined means user has not logged in yet
                    // Pop back stack to prevent showing TOSFragment on pressing back button.
                    navController.popBackStack()
                    navController.navigate(R.id.signInFragment)
                launch {
                    observeSignatureMissMatchError()
                }

                else -> {}
                launch {
                    observerErrorEvent()
                }

            it.find { it is AuthObject.GPlayAuth }?.result?.run {
                if (isSuccess()) {
                    viewModel.gPlayAuthData = data as AuthData
                } else if (exception is GPlayValidationException) {
                    val email = otherPayload.toString()
                    viewModel.uploadFaultyTokenToEcloud(
                        email,
                        SystemInfoProvider.getAppBuildInfo()
                    )
                } else if (exception != null) {
                    Timber.e(exception, "Login failed! message: ${exception?.localizedMessage}")
                launch {
                    observeAppPurchaseFragment()
                }

                launch {
                    observeNoInternetEvent()
                }
            }

        navController.addOnDestinationChangedListener { _, destination, _ ->
            if (!hasInternet) {
                showNoInternet()
        }
            when (destination.id) {
                R.id.applicationFragment,
                R.id.applicationListFragment,
                R.id.screenshotFragment,
                R.id.descriptionFragment,
                R.id.TOSFragment,
                R.id.googleSignInFragment,
                R.id.signInFragment -> {
                    bottomNavigationView.visibility = View.GONE
    }

                else -> {
                    bottomNavigationView.visibility = View.VISIBLE
    private fun observePurchaseDeclined() {
        viewModel.purchaseDeclined.observe(this) {
            if (it.isNotEmpty()) {
                lifecycleScope.launch {
                    viewModel.updateUnavailableForPurchaseDeclined(it)
                }
            }
        }

        if (intent.hasExtra(UpdatesNotifier.UPDATES_NOTIFICATION_CLICK_EXTRA)) {
            bottomNavigationView.selectedItemId = R.id.updatesFragment
    }

        // Create notification channel on post-nougat devices
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            viewModel.createNotificationChannels()
    private fun observeIsAppPurchased() {
        viewModel.isAppPurchased.observe(this) {
            if (it.isNotEmpty()) {
                startInstallationOfPurchasedApp(viewModel, it)
            }
        }
    }

        viewModel.purchaseAppLiveData.observe(this) {
            goToAppPurchaseFragment(it)
    private fun observeErrorMessageString() {
        viewModel.errorMessageStringResource.observe(this) {
            showSnackbarMessage(getString(it))
        }
    }

    private fun observeErrorMessage() {
        viewModel.errorMessage.observe(this) {
            when (it) {
                is ApiException.AppNotPurchased -> showSnackbarMessage(getString(R.string.message_app_available_later))
@@ -185,58 +199,97 @@ class MainActivity : AppCompatActivity() {
                )
            }
        }

        viewModel.errorMessageStringResource.observe(this) {
            showSnackbarMessage(getString(it))
    }

        viewModel.isAppPurchased.observe(this) {
            if (it.isNotEmpty()) {
                startInstallationOfPurchasedApp(viewModel, it)
    private fun observePurchaseAppPage() {
        viewModel.purchaseAppLiveData.observe(this) {
            goToAppPurchaseFragment(it)
        }
    }

        viewModel.purchaseDeclined.observe(this) {
            if (it.isNotEmpty()) {
                lifecycleScope.launch {
                    viewModel.updateUnavailableForPurchaseDeclined(it)
    private fun observeInternetConnections(hasInternet: Boolean): Boolean {
        var mutableHasInternet = hasInternet
        viewModel.internetConnection.observe(this) { isInternetAvailable ->
            mutableHasInternet = isInternetAvailable
            if (isInternetAvailable) {
                binding.noInternet.visibility = View.GONE
                binding.fragment.visibility = View.VISIBLE
            }
        }
        return mutableHasInternet
    }

        if (viewModel.internetConnection.value != true) {
    private fun setupDestinationChangedListener(
        navController: NavController,
        hasInternet: Boolean,
        bottomNavigationView: BottomNavigationView
    ) {
        navController.addOnDestinationChangedListener { _, destination, _ ->
            if (!hasInternet) {
                showNoInternet()
            }

        viewModel.updateAppWarningList()

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    observeInvalidAuth()
            when (destination.id) {
                R.id.applicationFragment,
                R.id.applicationListFragment,
                R.id.screenshotFragment,
                R.id.descriptionFragment,
                R.id.TOSFragment,
                R.id.googleSignInFragment,
                R.id.signInFragment -> {
                    bottomNavigationView.visibility = View.GONE
                }

                launch {
                    observeTooManyRequests()
                else -> {
                    bottomNavigationView.visibility = View.VISIBLE
                }
            }
        }

                launch {
                    observeSignatureMissMatchError()
    }

                launch {
                    observerErrorEvent()
    private fun observeAuthObjects(navController: NavController) {
        loginViewModel.authObjects.distinctUntilChanged().observe(this) {
            when {
                it == null -> return@observe
                it.isEmpty() -> {
                    // No auth type defined means user has not logged in yet
                    // Pop back stack to prevent showing TOSFragment on pressing back button.
                    navController.popBackStack()
                    navController.navigate(R.id.signInFragment)
                }

                launch {
                    observeAppPurchaseFragment()
                else -> {}
            }

                launch {
                    observeNoInternetEvent()
            it.find { it is AuthObject.GPlayAuth }?.result?.run {
                if (isSuccess()) {
                    viewModel.gPlayAuthData = data as AuthData
                } else if (exception is GPlayValidationException) {
                    val email = otherPayload.toString()
                    viewModel.uploadFaultyTokenToEcloud(
                        email,
                        SystemInfoProvider.getAppBuildInfo()
                    )
                } else if (exception != null) {
                    Timber.e(exception, "Login failed! message: ${exception?.localizedMessage}")
                }
            }
        }
    }

    private fun setupViewModels() {
        viewModel = ViewModelProvider(this)[MainActivityViewModel::class.java]
        signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java]
        loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
    }

    private fun setupBootomNav(): Pair<BottomNavigationView, NavController> {
        val bottomNavigationView = binding.bottomNavigationView
        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment
        val navController = navHostFragment.navController
        bottomNavigationView.setupWithNavController(navController)
        setupBottomNavItemSelectedListener(bottomNavigationView, navHostFragment, navController)
        return Pair(bottomNavigationView, navController)
    }

    private suspend fun observeNoInternetEvent() {
+32 −24
Original line number Diff line number Diff line
@@ -123,9 +123,22 @@ class DownloadManager @Inject constructor(
        downloadCompleted: ((Boolean, String) -> Unit)?
    ) {
        try {
            downloadManager.query(downloadManagerQuery.setFilterById(downloadId))
                .use { cursor ->
            downloadManager.query(downloadManagerQuery.setFilterById(downloadId)).use { cursor ->
                if (cursor.moveToFirst()) {
                    handleDownloadStatus(cursor, downloadId, filePath, downloadCompleted)
                }
            }
        } catch (e: Exception) {
            Timber.e(e)
        }
    }

    private fun handleDownloadStatus(
        cursor: Cursor,
        downloadId: Long,
        filePath: String,
        downloadCompleted: ((Boolean, String) -> Unit)?
    ) {
        var status =
            cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
        val totalSizeBytes =
@@ -147,11 +160,6 @@ class DownloadManager @Inject constructor(
            downloadCompleted?.invoke(true, filePath)
        }
    }
                }
        } catch (e: Exception) {
            Timber.e(e)
        }
    }

    private fun tickerFlow(
        downloadId: Long,
+41 −70
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ import foundation.e.apps.data.playstore.PlayStoreRepository
import foundation.e.apps.data.preference.PreferenceManagerModule
import foundation.e.apps.install.pkg.PWAManagerModule
import foundation.e.apps.install.pkg.PkgManagerModule
import foundation.e.apps.ui.home.model.HomeChildFusedAppDiffUtil
import foundation.e.apps.ui.applicationlist.ApplicationDiffUtil
import foundation.e.apps.utils.eventBus.AppEvent
import foundation.e.apps.utils.eventBus.EventBus
import kotlinx.coroutines.Deferred
@@ -1072,106 +1072,77 @@ class ApplicationApiImpl @Inject constructor(
    private suspend fun generateCleanAPKHome(home: CleanApkHome, appType: String): List<Home> {
        val list = mutableListOf<Home>()
        val headings = if (appType == APP_TYPE_OPEN) {
            mapOf(
                "top_updated_apps" to context.getString(R.string.top_updated_apps),
                "top_updated_games" to context.getString(R.string.top_updated_games),
                "popular_apps_in_last_24_hours" to context.getString(R.string.popular_apps_in_last_24_hours),
                "popular_games_in_last_24_hours" to context.getString(R.string.popular_games_in_last_24_hours),
                "discover" to context.getString(R.string.discover)
            )
            getOpenSourceHomeCategories()
        } else {
            mapOf(
                "popular_apps" to context.getString(R.string.popular_apps),
                "popular_games" to context.getString(R.string.popular_games),
                "discover" to context.getString(R.string.discover_pwa)
            )
            getPWAHomeCategories()
        }
        headings.forEach { (key, value) ->
            when (key) {
                "top_updated_apps" -> {
                    if (home.top_updated_apps.isNotEmpty()) {
                        home.top_updated_apps.forEach {
                            it.updateStatus()
                            it.updateType()
                            it.updateFilterLevel(null)
                        }
                        list.add(Home(value, home.top_updated_apps))
                    }
                    prepareApps(home.top_updated_apps, list, value)
                }

                "top_updated_games" -> {
                    if (home.top_updated_games.isNotEmpty()) {
                        home.top_updated_games.forEach {
                            it.updateStatus()
                            it.updateType()
                            it.updateFilterLevel(null)
                        }
                        list.add(Home(value, home.top_updated_games))
                    }
                    prepareApps(home.top_updated_games, list, value)
                }

                "popular_apps" -> {
                    if (home.popular_apps.isNotEmpty()) {
                        home.popular_apps.forEach {
                            it.updateStatus()
                            it.updateType()
                            it.updateFilterLevel(null)
                        }
                        list.add(Home(value, home.popular_apps))
                    }
                    prepareApps(home.popular_apps, list, value)
                }

                "popular_games" -> {
                    if (home.popular_games.isNotEmpty()) {
                        home.popular_games.forEach {
                            it.updateStatus()
                            it.updateType()
                            it.updateFilterLevel(null)
                        }
                        list.add(Home(value, home.popular_games))
                    }
                    prepareApps(home.popular_games, list, value)
                }

                "popular_apps_in_last_24_hours" -> {
                    if (home.popular_apps_in_last_24_hours.isNotEmpty()) {
                        home.popular_apps_in_last_24_hours.forEach {
                            it.updateStatus()
                            it.updateType()
                            it.updateFilterLevel(null)
                        }
                        list.add(Home(value, home.popular_apps_in_last_24_hours))
                    }
                    prepareApps(home.popular_apps_in_last_24_hours, list, value)
                }

                "popular_games_in_last_24_hours" -> {
                    if (home.popular_games_in_last_24_hours.isNotEmpty()) {
                        home.popular_games_in_last_24_hours.forEach {
                            it.updateStatus()
                            it.updateType()
                            it.updateFilterLevel(null)
                        }
                        list.add(Home(value, home.popular_games_in_last_24_hours))
                    }
                    prepareApps(home.popular_games_in_last_24_hours, list, value)
                }

                "discover" -> {
                    if (home.discover.isNotEmpty()) {
                        home.discover.forEach {
                            it.updateStatus()
                            it.updateType()
                            it.updateFilterLevel(null)
                        }
                        list.add(Home(value, home.discover))
                    }
                    prepareApps(home.discover, list, value)
                }
            }
        }

        return list.map {
            it.source = appType
            it
        }
    }

    private suspend fun prepareApps(
        appList: List<Application>,
        list: MutableList<Home>,
        value: String
    ) {
        if (appList.isNotEmpty()) {
            appList.forEach {
                it.updateStatus()
                it.updateType()
                it.updateFilterLevel(null)
            }
            list.add(Home(value, appList))
        }
    }

    private fun getPWAHomeCategories() = mapOf(
        "popular_apps" to context.getString(R.string.popular_apps),
        "popular_games" to context.getString(R.string.popular_games),
        "discover" to context.getString(R.string.discover_pwa)
    )

    private fun getOpenSourceHomeCategories() = mapOf(
        "top_updated_apps" to context.getString(R.string.top_updated_apps),
        "top_updated_games" to context.getString(R.string.top_updated_games),
        "popular_apps_in_last_24_hours" to context.getString(R.string.popular_apps_in_last_24_hours),
        "popular_games_in_last_24_hours" to context.getString(R.string.popular_games_in_last_24_hours),
        "discover" to context.getString(R.string.discover)
    )

    private suspend fun fetchGPlayHome(authData: AuthData): List<Home> {
        val list = mutableListOf<Home>()
        val gplayHomeData = gplayRepository.getHomeScreenData() as Map<String, List<App>>
@@ -1293,7 +1264,7 @@ class ApplicationApiImpl @Inject constructor(
        newApplications: List<Application>,
        oldApplications: List<Application>
    ): Boolean {
        val fusedAppDiffUtil = HomeChildFusedAppDiffUtil()
        val fusedAppDiffUtil = ApplicationDiffUtil()
        if (newApplications.size != oldApplications.size) {
            return true
        }
+81 −154

File changed.

Preview size limit exceeded, changes collapsed.

Loading