Loading app/src/main/java/foundation/e/apps/data/blockedApps/ContentRatingsRepository.kt +18 −8 Original line number Diff line number Diff line Loading @@ -62,23 +62,33 @@ class ContentRatingsRepository @Inject constructor( private fun parseContentRatingData() { _contentRatingGroups = try { val outputPath = "$cacheDir/warning_list/" FileManager.moveFile("$cacheDir/", CONTENT_RATINGS_FILE_NAME, outputPath) FileManager.moveFile( "$cacheDir/", CONTENT_RATINGS_FILE_NAME, outputPath ) val downloadedFile = File(outputPath + CONTENT_RATINGS_FILE_NAME) val contentRatingJson = String(downloadedFile.inputStream().readBytes()) Timber.d("ContentRatings file contents: $contentRatingJson") val contentRatingsListTypeGroup = object : TypeToken<List<ContentRatingGroup>>() {}.type val contentRatingGroups: List<ContentRatingGroup> = gson.fromJson(contentRatingJson, contentRatingsListTypeGroup) contentRatingGroups.map { it.ratings = it.ratings.map { rating -> rating.lowercase()} it } parseJsonOfContentRatingGroup(contentRatingJson) } catch (exception: JsonSyntaxException) { handleException(exception) } } private fun parseJsonOfContentRatingGroup(contentRatingJson: String): List<ContentRatingGroup> { val contentRatingsListTypeGroup = object : TypeToken<List<ContentRatingGroup>>() {}.type val contentRatingGroups: List<ContentRatingGroup> = gson.fromJson(contentRatingJson, contentRatingsListTypeGroup) return contentRatingGroups.map { it.ratings = it.ratings.map { rating -> rating.lowercase() } it } } private fun handleException(exception: Exception): MutableList<ContentRatingGroup> { Timber.e(exception.localizedMessage ?: "", exception) return mutableListOf() Loading app/src/main/java/foundation/e/apps/domain/CheckAppAgeLimitUseCase.kt→app/src/main/java/foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt +38 −21 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ package foundation.e.apps.domain import com.aurora.gplayapi.data.models.AuthData import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.blockedApps.Ages import foundation.e.apps.data.blockedApps.ContentRatingGroup import foundation.e.apps.data.blockedApps.ContentRatingsRepository import foundation.e.apps.data.blockedApps.ParentalControlRepository import foundation.e.apps.data.enums.ResultStatus Loading @@ -30,7 +32,7 @@ import foundation.e.apps.data.preference.DataStoreManager import timber.log.Timber import javax.inject.Inject class CheckAppAgeLimitUseCase @Inject constructor( class ValidateAppAgeLimitUseCase @Inject constructor( private val applicationRepository: ApplicationRepository, private val dataStoreManager: DataStoreManager, private val contentRatingRepository: ContentRatingsRepository, Loading @@ -38,10 +40,12 @@ class CheckAppAgeLimitUseCase @Inject constructor( private val playStoreRepository: PlayStoreRepository ) { suspend operator fun invoke(appInstall: AppInstall): Boolean { suspend operator fun invoke(appInstall: AppInstall): Pair<Boolean, ResultStatus> { val authData = dataStoreManager.getAuthData() verifyContentRatingExists(appInstall, authData) if (!verifyContentRatingExists(appInstall, authData)) { return Pair(false, ResultStatus.UNKNOWN) } val selectedAgeGroup = parentalControlRepository.getSelectedAgeGroup() val allowedContentRating = contentRatingRepository.contentRatingGroups.find { Loading @@ -53,34 +57,47 @@ class CheckAppAgeLimitUseCase @Inject constructor( "Content rating: ${appInstall.contentRating.id} \n" + "Allowed content rating: $allowedContentRating" ) return selectedAgeGroup != null && appInstall.contentRating.id.isNotEmpty() && allowedContentRating?.ratings?.contains(appInstall.contentRating.id) == false val isAppAgeLimitedValidated = isParentalControlDisabled(selectedAgeGroup) || isAppAgeRatingValid(appInstall, allowedContentRating) return Pair(isAppAgeLimitedValidated, ResultStatus.OK) } private fun isAppAgeRatingValid( appInstall: AppInstall, allowedContentRating: ContentRatingGroup? ) = (appInstall.contentRating.id.isNotEmpty() && allowedContentRating?.ratings?.contains(appInstall.contentRating.id) == true) private fun isParentalControlDisabled(selectedAgeGroup: Ages?) = selectedAgeGroup == null private suspend fun verifyContentRatingExists( appInstall: AppInstall, authData: AuthData ) { ): Boolean { if (appInstall.contentRating.title.isEmpty()) { applicationRepository.getApplicationDetails( appInstall.id, appInstall.packageName, authData, appInstall.origin applicationRepository .getApplicationDetails( appInstall.id, appInstall.packageName, authData, appInstall.origin ).let { (appDetails, resultStatus) -> if (resultStatus == ResultStatus.OK) { appInstall.contentRating = appDetails.contentRating } else { return false } // todo: handle unhappy path and return from this method } } if (appInstall.contentRating.id.isEmpty()) { appInstall.contentRating = playStoreRepository.getContentRatingWithId( appInstall.contentRating = playStoreRepository.getContentRatingWithId( appInstall.packageName, appInstall.contentRating ) } return appInstall.contentRating.title.isNotEmpty() && appInstall.contentRating.id.isNotEmpty() } } app/src/main/java/foundation/e/apps/install/workmanager/AppInstallProcessor.kt +10 −5 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.install.models.AppInstall import foundation.e.apps.data.playstore.utils.GplayHttpRequestException import foundation.e.apps.data.preference.DataStoreManager import foundation.e.apps.domain.CheckAppAgeLimitUseCase import foundation.e.apps.domain.ValidateAppAgeLimitUseCase import foundation.e.apps.install.AppInstallComponents import foundation.e.apps.install.download.DownloadManagerUtils import foundation.e.apps.install.notification.StorageNotificationManager Loading @@ -53,7 +53,7 @@ class AppInstallProcessor @Inject constructor( @ApplicationContext private val context: Context, private val appInstallComponents: AppInstallComponents, private val applicationRepository: ApplicationRepository, private val checkAppAgeLimitUseCase: CheckAppAgeLimitUseCase, private val validateAppAgeLimitUseCase: ValidateAppAgeLimitUseCase, private val dataStoreManager: DataStoreManager, private val storageNotificationManager: StorageNotificationManager, ) { Loading Loading @@ -131,9 +131,14 @@ class AppInstallProcessor @Inject constructor( return } if (checkAppAgeLimitUseCase.invoke(appInstall)) { val (isAgeLimitValidated, resultStatus) = validateAppAgeLimitUseCase.invoke(appInstall) if (!isAgeLimitValidated) { if (resultStatus == ResultStatus.OK) { Timber.i("Content rating is not allowed for: ${appInstall.name}") EventBus.invokeEvent(AppEvent.AgeLimitRestrictionEvent()) } else { //TODO trigger an error event } appInstallComponents.appManagerWrapper.cancelDownload(appInstall) return } Loading Loading
app/src/main/java/foundation/e/apps/data/blockedApps/ContentRatingsRepository.kt +18 −8 Original line number Diff line number Diff line Loading @@ -62,23 +62,33 @@ class ContentRatingsRepository @Inject constructor( private fun parseContentRatingData() { _contentRatingGroups = try { val outputPath = "$cacheDir/warning_list/" FileManager.moveFile("$cacheDir/", CONTENT_RATINGS_FILE_NAME, outputPath) FileManager.moveFile( "$cacheDir/", CONTENT_RATINGS_FILE_NAME, outputPath ) val downloadedFile = File(outputPath + CONTENT_RATINGS_FILE_NAME) val contentRatingJson = String(downloadedFile.inputStream().readBytes()) Timber.d("ContentRatings file contents: $contentRatingJson") val contentRatingsListTypeGroup = object : TypeToken<List<ContentRatingGroup>>() {}.type val contentRatingGroups: List<ContentRatingGroup> = gson.fromJson(contentRatingJson, contentRatingsListTypeGroup) contentRatingGroups.map { it.ratings = it.ratings.map { rating -> rating.lowercase()} it } parseJsonOfContentRatingGroup(contentRatingJson) } catch (exception: JsonSyntaxException) { handleException(exception) } } private fun parseJsonOfContentRatingGroup(contentRatingJson: String): List<ContentRatingGroup> { val contentRatingsListTypeGroup = object : TypeToken<List<ContentRatingGroup>>() {}.type val contentRatingGroups: List<ContentRatingGroup> = gson.fromJson(contentRatingJson, contentRatingsListTypeGroup) return contentRatingGroups.map { it.ratings = it.ratings.map { rating -> rating.lowercase() } it } } private fun handleException(exception: Exception): MutableList<ContentRatingGroup> { Timber.e(exception.localizedMessage ?: "", exception) return mutableListOf() Loading
app/src/main/java/foundation/e/apps/domain/CheckAppAgeLimitUseCase.kt→app/src/main/java/foundation/e/apps/domain/ValidateAppAgeLimitUseCase.kt +38 −21 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ package foundation.e.apps.domain import com.aurora.gplayapi.data.models.AuthData import foundation.e.apps.data.application.ApplicationRepository import foundation.e.apps.data.blockedApps.Ages import foundation.e.apps.data.blockedApps.ContentRatingGroup import foundation.e.apps.data.blockedApps.ContentRatingsRepository import foundation.e.apps.data.blockedApps.ParentalControlRepository import foundation.e.apps.data.enums.ResultStatus Loading @@ -30,7 +32,7 @@ import foundation.e.apps.data.preference.DataStoreManager import timber.log.Timber import javax.inject.Inject class CheckAppAgeLimitUseCase @Inject constructor( class ValidateAppAgeLimitUseCase @Inject constructor( private val applicationRepository: ApplicationRepository, private val dataStoreManager: DataStoreManager, private val contentRatingRepository: ContentRatingsRepository, Loading @@ -38,10 +40,12 @@ class CheckAppAgeLimitUseCase @Inject constructor( private val playStoreRepository: PlayStoreRepository ) { suspend operator fun invoke(appInstall: AppInstall): Boolean { suspend operator fun invoke(appInstall: AppInstall): Pair<Boolean, ResultStatus> { val authData = dataStoreManager.getAuthData() verifyContentRatingExists(appInstall, authData) if (!verifyContentRatingExists(appInstall, authData)) { return Pair(false, ResultStatus.UNKNOWN) } val selectedAgeGroup = parentalControlRepository.getSelectedAgeGroup() val allowedContentRating = contentRatingRepository.contentRatingGroups.find { Loading @@ -53,34 +57,47 @@ class CheckAppAgeLimitUseCase @Inject constructor( "Content rating: ${appInstall.contentRating.id} \n" + "Allowed content rating: $allowedContentRating" ) return selectedAgeGroup != null && appInstall.contentRating.id.isNotEmpty() && allowedContentRating?.ratings?.contains(appInstall.contentRating.id) == false val isAppAgeLimitedValidated = isParentalControlDisabled(selectedAgeGroup) || isAppAgeRatingValid(appInstall, allowedContentRating) return Pair(isAppAgeLimitedValidated, ResultStatus.OK) } private fun isAppAgeRatingValid( appInstall: AppInstall, allowedContentRating: ContentRatingGroup? ) = (appInstall.contentRating.id.isNotEmpty() && allowedContentRating?.ratings?.contains(appInstall.contentRating.id) == true) private fun isParentalControlDisabled(selectedAgeGroup: Ages?) = selectedAgeGroup == null private suspend fun verifyContentRatingExists( appInstall: AppInstall, authData: AuthData ) { ): Boolean { if (appInstall.contentRating.title.isEmpty()) { applicationRepository.getApplicationDetails( appInstall.id, appInstall.packageName, authData, appInstall.origin applicationRepository .getApplicationDetails( appInstall.id, appInstall.packageName, authData, appInstall.origin ).let { (appDetails, resultStatus) -> if (resultStatus == ResultStatus.OK) { appInstall.contentRating = appDetails.contentRating } else { return false } // todo: handle unhappy path and return from this method } } if (appInstall.contentRating.id.isEmpty()) { appInstall.contentRating = playStoreRepository.getContentRatingWithId( appInstall.contentRating = playStoreRepository.getContentRatingWithId( appInstall.packageName, appInstall.contentRating ) } return appInstall.contentRating.title.isNotEmpty() && appInstall.contentRating.id.isNotEmpty() } }
app/src/main/java/foundation/e/apps/install/workmanager/AppInstallProcessor.kt +10 −5 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import foundation.e.apps.data.application.data.Application import foundation.e.apps.data.install.models.AppInstall import foundation.e.apps.data.playstore.utils.GplayHttpRequestException import foundation.e.apps.data.preference.DataStoreManager import foundation.e.apps.domain.CheckAppAgeLimitUseCase import foundation.e.apps.domain.ValidateAppAgeLimitUseCase import foundation.e.apps.install.AppInstallComponents import foundation.e.apps.install.download.DownloadManagerUtils import foundation.e.apps.install.notification.StorageNotificationManager Loading @@ -53,7 +53,7 @@ class AppInstallProcessor @Inject constructor( @ApplicationContext private val context: Context, private val appInstallComponents: AppInstallComponents, private val applicationRepository: ApplicationRepository, private val checkAppAgeLimitUseCase: CheckAppAgeLimitUseCase, private val validateAppAgeLimitUseCase: ValidateAppAgeLimitUseCase, private val dataStoreManager: DataStoreManager, private val storageNotificationManager: StorageNotificationManager, ) { Loading Loading @@ -131,9 +131,14 @@ class AppInstallProcessor @Inject constructor( return } if (checkAppAgeLimitUseCase.invoke(appInstall)) { val (isAgeLimitValidated, resultStatus) = validateAppAgeLimitUseCase.invoke(appInstall) if (!isAgeLimitValidated) { if (resultStatus == ResultStatus.OK) { Timber.i("Content rating is not allowed for: ${appInstall.name}") EventBus.invokeEvent(AppEvent.AgeLimitRestrictionEvent()) } else { //TODO trigger an error event } appInstallComponents.appManagerWrapper.cancelDownload(appInstall) return } Loading