Loading app/build.gradle +16 −0 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,7 @@ plugins { id 'org.jlleitschuh.gradle.ktlint' version '10.2.0' id 'org.jlleitschuh.gradle.ktlint' version '10.2.0' id 'androidx.navigation.safeargs.kotlin' id 'androidx.navigation.safeargs.kotlin' id 'dagger.hilt.android.plugin' id 'dagger.hilt.android.plugin' id 'kotlin-allopen' } } def versionMajor = 2 def versionMajor = 2 Loading Loading @@ -92,6 +93,11 @@ kapt { correctErrorTypes true correctErrorTypes true } } allOpen { // allows mocking for classes w/o directly opening them for release builds annotation 'foundation.e.apps.OpenClass' } dependencies { dependencies { api "com.gitlab.AuroraOSS:gplayapi:0e224071f3" api "com.gitlab.AuroraOSS:gplayapi:0e224071f3" Loading @@ -109,6 +115,15 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' // Optional -- Robolectric environment testImplementation "androidx.test:core:1.4.0" // Optional -- Mockito framework testImplementation "org.mockito:mockito-core:4.6.1" // Optional -- mockito-kotlin testImplementation "org.mockito.kotlin:mockito-kotlin:3.2.0" testImplementation 'org.mockito:mockito-inline:2.13.0' // Coil and PhotoView // Coil and PhotoView implementation "io.coil-kt:coil:1.4.0" implementation "io.coil-kt:coil:1.4.0" Loading Loading @@ -161,6 +176,7 @@ dependencies { def coroutines_version = "1.6.0" def coroutines_version = "1.6.0" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" // Room // Room def roomVersion = "2.4.1" def roomVersion = "2.4.1" Loading app/src/debug/java/foundation/e/apps/OpenForTesting.kt 0 → 100644 +32 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2022 ECORP * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps /** * This annotation allows us to open some classes for mocking purposes while they are final in * release builds. */ @Target(AnnotationTarget.ANNOTATION_CLASS) annotation class OpenClass /** * Annotate a class with [OpenForTesting] if you want it to be extendable in debug builds. */ @OpenClass @Target(AnnotationTarget.CLASS) annotation class OpenForTesting app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +15 −0 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package foundation.e.apps package foundation.e.apps import android.content.Context import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.graphics.Bitmap import android.os.Build import android.os.Build import android.os.SystemClock import android.os.SystemClock Loading Loading @@ -56,6 +57,7 @@ import foundation.e.apps.utils.enums.isUnFiltered import foundation.e.apps.utils.modules.CommonUtilsModule.NETWORK_CODE_SUCCESS import foundation.e.apps.utils.modules.CommonUtilsModule.NETWORK_CODE_SUCCESS import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.PWAManagerModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext Loading @@ -71,6 +73,7 @@ class MainActivityViewModel @Inject constructor( private val fusedAPIRepository: FusedAPIRepository, private val fusedAPIRepository: FusedAPIRepository, private val fusedManagerRepository: FusedManagerRepository, private val fusedManagerRepository: FusedManagerRepository, private val pkgManagerModule: PkgManagerModule, private val pkgManagerModule: PkgManagerModule, private val pwaManagerModule: PWAManagerModule, private val ecloudRepository: EcloudRepository, private val ecloudRepository: EcloudRepository, private val blockedAppRepository: BlockedAppRepository, private val blockedAppRepository: BlockedAppRepository, private val aC2DMTask: AC2DMTask, private val aC2DMTask: AC2DMTask, Loading Loading @@ -122,6 +125,10 @@ class MainActivityViewModel @Inject constructor( private var isGoogleLoginRunning = false private var isGoogleLoginRunning = false } } fun getUser(): User { return User.valueOf(userType.value ?: User.UNAVAILABLE.name) } private fun setFirstTokenFetchTime() { private fun setFirstTokenFetchTime() { if (firstAuthDataFetchTime == 0L) { if (firstAuthDataFetchTime == 0L) { firstAuthDataFetchTime = SystemClock.uptimeMillis() firstAuthDataFetchTime = SystemClock.uptimeMillis() Loading Loading @@ -631,4 +638,12 @@ class MainActivityViewModel @Inject constructor( fun getAppNameByPackageName(packageName: String): String { fun getAppNameByPackageName(packageName: String): String { return pkgManagerModule.getAppNameFromPackageName(packageName) return pkgManagerModule.getAppNameFromPackageName(packageName) } } fun getLaunchIntentForPackageName(packageName: String): Intent? { return pkgManagerModule.getLaunchIntent(packageName) } fun launchPwa(fusedApp: FusedApp) { pwaManagerModule.launchPwa(fusedApp) } } } app/src/main/java/foundation/e/apps/api/cleanapk/CleanAPKRepository.kt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ package foundation.e.apps.api.cleanapk package foundation.e.apps.api.cleanapk import foundation.e.apps.OpenForTesting import foundation.e.apps.api.cleanapk.data.app.Application import foundation.e.apps.api.cleanapk.data.app.Application import foundation.e.apps.api.cleanapk.data.categories.Categories import foundation.e.apps.api.cleanapk.data.categories.Categories import foundation.e.apps.api.cleanapk.data.download.Download import foundation.e.apps.api.cleanapk.data.download.Download Loading @@ -26,6 +27,7 @@ import foundation.e.apps.api.cleanapk.data.search.Search import retrofit2.Response import retrofit2.Response import javax.inject.Inject import javax.inject.Inject @OpenForTesting class CleanAPKRepository @Inject constructor( class CleanAPKRepository @Inject constructor( private val cleanAPKInterface: CleanAPKInterface, private val cleanAPKInterface: CleanAPKInterface, private val cleanApkAppDetailApi: CleanApkAppDetailApi private val cleanApkAppDetailApi: CleanApkAppDetailApi Loading app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +71 −0 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,7 @@ import foundation.e.apps.api.fused.data.FusedHome import foundation.e.apps.api.fused.data.Ratings import foundation.e.apps.api.fused.data.Ratings import foundation.e.apps.api.fused.utils.CategoryUtils import foundation.e.apps.api.fused.utils.CategoryUtils import foundation.e.apps.api.gplay.GPlayAPIRepository import foundation.e.apps.api.gplay.GPlayAPIRepository import foundation.e.apps.home.model.HomeChildFusedAppDiffUtil import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.AppTag import foundation.e.apps.utils.enums.AppTag Loading Loading @@ -1260,4 +1261,74 @@ class FusedAPIImpl @Inject constructor( } } return list return list } } /** * @return true, if any change is found, otherwise false */ fun isHomeDataUpdated( newHomeData: List<FusedHome>, oldHomeData: List<FusedHome> ): Boolean { if (newHomeData.size != oldHomeData.size) { return true } oldHomeData.forEach { val fusedHome = newHomeData[oldHomeData.indexOf(it)] if (!it.title.contentEquals(fusedHome.title) || !areFusedAppsUpdated(it, fusedHome)) { return true } } return false } private fun areFusedAppsUpdated( oldFusedHome: FusedHome, newFusedHome: FusedHome, ): Boolean { val fusedAppDiffUtil = HomeChildFusedAppDiffUtil() oldFusedHome.list.forEach { oldFusedApp -> val indexOfOldFusedApp = oldFusedHome.list.indexOf(oldFusedApp) val fusedApp = newFusedHome.list[indexOfOldFusedApp] if (!fusedAppDiffUtil.areContentsTheSame(oldFusedApp, fusedApp)) { return false } } return true } /** * @return returns true if there is changes in data, otherwise false */ fun isAnyFusedAppUpdated( newFusedApps: List<FusedApp>, oldFusedApps: List<FusedApp> ): Boolean { val fusedAppDiffUtil = HomeChildFusedAppDiffUtil() if (newFusedApps.size != oldFusedApps.size) { return true } newFusedApps.forEach { val indexOfNewFusedApp = newFusedApps.indexOf(it) if (!fusedAppDiffUtil.areContentsTheSame(it, oldFusedApps[indexOfNewFusedApp])) { return true } } return false } fun isAnyAppInstallStatusChanged(currentList: List<FusedApp>): Boolean { currentList.forEach { if (it.status == Status.INSTALLATION_ISSUE) { return@forEach } val currentAppStatus = pkgManagerModule.getPackageStatus(it.package_name, it.latest_version_code) if (it.status != currentAppStatus) { return true } } return false } } } Loading
app/build.gradle +16 −0 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,7 @@ plugins { id 'org.jlleitschuh.gradle.ktlint' version '10.2.0' id 'org.jlleitschuh.gradle.ktlint' version '10.2.0' id 'androidx.navigation.safeargs.kotlin' id 'androidx.navigation.safeargs.kotlin' id 'dagger.hilt.android.plugin' id 'dagger.hilt.android.plugin' id 'kotlin-allopen' } } def versionMajor = 2 def versionMajor = 2 Loading Loading @@ -92,6 +93,11 @@ kapt { correctErrorTypes true correctErrorTypes true } } allOpen { // allows mocking for classes w/o directly opening them for release builds annotation 'foundation.e.apps.OpenClass' } dependencies { dependencies { api "com.gitlab.AuroraOSS:gplayapi:0e224071f3" api "com.gitlab.AuroraOSS:gplayapi:0e224071f3" Loading @@ -109,6 +115,15 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' // Optional -- Robolectric environment testImplementation "androidx.test:core:1.4.0" // Optional -- Mockito framework testImplementation "org.mockito:mockito-core:4.6.1" // Optional -- mockito-kotlin testImplementation "org.mockito.kotlin:mockito-kotlin:3.2.0" testImplementation 'org.mockito:mockito-inline:2.13.0' // Coil and PhotoView // Coil and PhotoView implementation "io.coil-kt:coil:1.4.0" implementation "io.coil-kt:coil:1.4.0" Loading Loading @@ -161,6 +176,7 @@ dependencies { def coroutines_version = "1.6.0" def coroutines_version = "1.6.0" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" // Room // Room def roomVersion = "2.4.1" def roomVersion = "2.4.1" Loading
app/src/debug/java/foundation/e/apps/OpenForTesting.kt 0 → 100644 +32 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2022 ECORP * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps /** * This annotation allows us to open some classes for mocking purposes while they are final in * release builds. */ @Target(AnnotationTarget.ANNOTATION_CLASS) annotation class OpenClass /** * Annotate a class with [OpenForTesting] if you want it to be extendable in debug builds. */ @OpenClass @Target(AnnotationTarget.CLASS) annotation class OpenForTesting
app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +15 −0 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package foundation.e.apps package foundation.e.apps import android.content.Context import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.graphics.Bitmap import android.os.Build import android.os.Build import android.os.SystemClock import android.os.SystemClock Loading Loading @@ -56,6 +57,7 @@ import foundation.e.apps.utils.enums.isUnFiltered import foundation.e.apps.utils.modules.CommonUtilsModule.NETWORK_CODE_SUCCESS import foundation.e.apps.utils.modules.CommonUtilsModule.NETWORK_CODE_SUCCESS import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.PWAManagerModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext Loading @@ -71,6 +73,7 @@ class MainActivityViewModel @Inject constructor( private val fusedAPIRepository: FusedAPIRepository, private val fusedAPIRepository: FusedAPIRepository, private val fusedManagerRepository: FusedManagerRepository, private val fusedManagerRepository: FusedManagerRepository, private val pkgManagerModule: PkgManagerModule, private val pkgManagerModule: PkgManagerModule, private val pwaManagerModule: PWAManagerModule, private val ecloudRepository: EcloudRepository, private val ecloudRepository: EcloudRepository, private val blockedAppRepository: BlockedAppRepository, private val blockedAppRepository: BlockedAppRepository, private val aC2DMTask: AC2DMTask, private val aC2DMTask: AC2DMTask, Loading Loading @@ -122,6 +125,10 @@ class MainActivityViewModel @Inject constructor( private var isGoogleLoginRunning = false private var isGoogleLoginRunning = false } } fun getUser(): User { return User.valueOf(userType.value ?: User.UNAVAILABLE.name) } private fun setFirstTokenFetchTime() { private fun setFirstTokenFetchTime() { if (firstAuthDataFetchTime == 0L) { if (firstAuthDataFetchTime == 0L) { firstAuthDataFetchTime = SystemClock.uptimeMillis() firstAuthDataFetchTime = SystemClock.uptimeMillis() Loading Loading @@ -631,4 +638,12 @@ class MainActivityViewModel @Inject constructor( fun getAppNameByPackageName(packageName: String): String { fun getAppNameByPackageName(packageName: String): String { return pkgManagerModule.getAppNameFromPackageName(packageName) return pkgManagerModule.getAppNameFromPackageName(packageName) } } fun getLaunchIntentForPackageName(packageName: String): Intent? { return pkgManagerModule.getLaunchIntent(packageName) } fun launchPwa(fusedApp: FusedApp) { pwaManagerModule.launchPwa(fusedApp) } } }
app/src/main/java/foundation/e/apps/api/cleanapk/CleanAPKRepository.kt +2 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ package foundation.e.apps.api.cleanapk package foundation.e.apps.api.cleanapk import foundation.e.apps.OpenForTesting import foundation.e.apps.api.cleanapk.data.app.Application import foundation.e.apps.api.cleanapk.data.app.Application import foundation.e.apps.api.cleanapk.data.categories.Categories import foundation.e.apps.api.cleanapk.data.categories.Categories import foundation.e.apps.api.cleanapk.data.download.Download import foundation.e.apps.api.cleanapk.data.download.Download Loading @@ -26,6 +27,7 @@ import foundation.e.apps.api.cleanapk.data.search.Search import retrofit2.Response import retrofit2.Response import javax.inject.Inject import javax.inject.Inject @OpenForTesting class CleanAPKRepository @Inject constructor( class CleanAPKRepository @Inject constructor( private val cleanAPKInterface: CleanAPKInterface, private val cleanAPKInterface: CleanAPKInterface, private val cleanApkAppDetailApi: CleanApkAppDetailApi private val cleanApkAppDetailApi: CleanApkAppDetailApi Loading
app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +71 −0 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,7 @@ import foundation.e.apps.api.fused.data.FusedHome import foundation.e.apps.api.fused.data.Ratings import foundation.e.apps.api.fused.data.Ratings import foundation.e.apps.api.fused.utils.CategoryUtils import foundation.e.apps.api.fused.utils.CategoryUtils import foundation.e.apps.api.gplay.GPlayAPIRepository import foundation.e.apps.api.gplay.GPlayAPIRepository import foundation.e.apps.home.model.HomeChildFusedAppDiffUtil import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.AppTag import foundation.e.apps.utils.enums.AppTag Loading Loading @@ -1260,4 +1261,74 @@ class FusedAPIImpl @Inject constructor( } } return list return list } } /** * @return true, if any change is found, otherwise false */ fun isHomeDataUpdated( newHomeData: List<FusedHome>, oldHomeData: List<FusedHome> ): Boolean { if (newHomeData.size != oldHomeData.size) { return true } oldHomeData.forEach { val fusedHome = newHomeData[oldHomeData.indexOf(it)] if (!it.title.contentEquals(fusedHome.title) || !areFusedAppsUpdated(it, fusedHome)) { return true } } return false } private fun areFusedAppsUpdated( oldFusedHome: FusedHome, newFusedHome: FusedHome, ): Boolean { val fusedAppDiffUtil = HomeChildFusedAppDiffUtil() oldFusedHome.list.forEach { oldFusedApp -> val indexOfOldFusedApp = oldFusedHome.list.indexOf(oldFusedApp) val fusedApp = newFusedHome.list[indexOfOldFusedApp] if (!fusedAppDiffUtil.areContentsTheSame(oldFusedApp, fusedApp)) { return false } } return true } /** * @return returns true if there is changes in data, otherwise false */ fun isAnyFusedAppUpdated( newFusedApps: List<FusedApp>, oldFusedApps: List<FusedApp> ): Boolean { val fusedAppDiffUtil = HomeChildFusedAppDiffUtil() if (newFusedApps.size != oldFusedApps.size) { return true } newFusedApps.forEach { val indexOfNewFusedApp = newFusedApps.indexOf(it) if (!fusedAppDiffUtil.areContentsTheSame(it, oldFusedApps[indexOfNewFusedApp])) { return true } } return false } fun isAnyAppInstallStatusChanged(currentList: List<FusedApp>): Boolean { currentList.forEach { if (it.status == Status.INSTALLATION_ISSUE) { return@forEach } val currentAppStatus = pkgManagerModule.getPackageStatus(it.package_name, it.latest_version_code) if (it.status != currentAppStatus) { return true } } return false } } }