Loading app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt +1 −1 Original line number Diff line number Diff line Loading @@ -228,7 +228,7 @@ val appModule = module { viewModelOf(::InternetPrivacyViewModel) viewModelOf(::DashboardViewModel) single { WeeklyReportViewFactory() } single { WeeklyReportViewFactory(context = androidContext()) } single { NotificationsPresenter( Loading app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersAndAppsListsUseCase.kt +1 −1 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ class TrackersAndAppsListsUseCase( private suspend fun getCountByEntityMaps(period: Period): CountByEntitiesMaps { val periodStart: Instant = period.getPeriodStart() val trackersAndAppsIds = statsDatabase.getDistinctTrackerAndApp(periodStart) val trackersAndAppsIds = statsDatabase.getDistinctTrackerAndApp(periodStart, Instant.now()) val trackersAndApps = mapIdsToEntities(trackersAndAppsIds) return foldToCountByEntityMaps(trackersAndApps) } Loading app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersScreenUseCase.kt +13 −3 Original line number Diff line number Diff line Loading @@ -18,14 +18,20 @@ package foundation.e.advancedprivacy.domain.usecases import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository import foundation.e.advancedprivacy.features.trackers.Period import foundation.e.advancedprivacy.features.trackers.TrackerTab import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.withContext class TrackersScreenUseCase( private val localStateRepository: LocalStateRepository, private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO ) { private val _goToTab = MutableSharedFlow<Pair<Int, Int>>() val goToTab: SharedFlow<Pair<Int, Int>> = _goToTab suspend fun getLastPosition(): Int = withContext(backgroundDispatcher) { localStateRepository.getTrackersScreenLastPosition() Loading @@ -43,8 +49,12 @@ class TrackersScreenUseCase( localStateRepository.trackersScreenTabStartPosition = -1 } suspend fun preselectTab(periodPosition: Int, tabPosition: Int) = withContext(backgroundDispatcher) { localStateRepository.setTrackersScreenLastPosition(periodPosition) localStateRepository.trackersScreenTabStartPosition = tabPosition suspend fun preselectTab(period: Period, tab: TrackerTab) = withContext(backgroundDispatcher) { localStateRepository.setTrackersScreenLastPosition(period.ordinal) localStateRepository.trackersScreenTabStartPosition = tab.ordinal } suspend fun selectTab(period: Period, tab: TrackerTab) { _goToTab.emit(period.ordinal to tab.ordinal) } } app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt +51 −28 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import foundation.e.advancedprivacy.data.repositories.WeeklyReportLocalRepositor import foundation.e.advancedprivacy.domain.entities.weeklyreport.DisplayableReport import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReport import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReportScore import foundation.e.advancedprivacy.trackers.data.StatsDatabase import foundation.e.advancedprivacy.trackers.data.TrackersRepository import java.time.Duration import java.time.Instant Loading @@ -40,6 +41,7 @@ class WeeklyReportUseCase( private val trackersRepository: TrackersRepository, private val appListRepository: AppListRepository, private val weeklyReportRepository: WeeklyReportLocalRepository, private val statsDatabase: StatsDatabase, private val scope: CoroutineScope ) { private val _currentReport = MutableStateFlow<DisplayableReport?>(null) Loading @@ -55,7 +57,7 @@ class WeeklyReportUseCase( } } private suspend fun updateCurrent() { suspend fun updateCurrent() { val weeklyReport = weeklyReportRepository.getLastWeeklyReport() ?: return val now = Instant.now() val endOfDisplay = weeklyReport.timestamp + displayDuration Loading Loading @@ -97,7 +99,7 @@ class WeeklyReportUseCase( result.reversed() } private fun buildCandidates(endOfWeek: Instant, history: List<WeeklyReport>): List<WeeklyReportScore> { private suspend fun buildCandidates(endOfWeek: Instant, history: List<WeeklyReport>): List<WeeklyReportScore> { val candidates = mutableListOf<WeeklyReport>() addCallPerAppCandidates(candidates, endOfWeek) addNewTrackerCandidates(candidates, endOfWeek) Loading Loading @@ -143,38 +145,55 @@ class WeeklyReportUseCase( ) } private fun addNewTrackerCandidates(candidates: MutableList<WeeklyReport>, endOfWeek: Instant) { val anyApp2 = appListRepository.displayableApps.value.first().id private suspend fun addNewTrackerCandidates(candidates: MutableList<WeeklyReport>, endOfWeek: Instant) { val startOfWeek = endOfWeek.minus(7, ChronoUnit.DAYS) val startOfYear = endOfWeek.minus(365, ChronoUnit.DAYS) val trackerAppsHistoric = statsDatabase.getDistinctTrackerAndApp(startOfYear, startOfWeek) val trackerAppsOfWeek = statsDatabase.getDistinctTrackerAndApp(startOfWeek, endOfWeek) val historicTrackers = trackerAppsHistoric.map { it.first }.toSet() val newTrackersDetected = trackerAppsOfWeek.filter { it.first !in historicTrackers } val appsIntroducingNewTracker = newTrackersDetected.mapNotNull { appListRepository.getAppById(it.second) }.toSet() // TODO dummy apps ?&& displayableApp != appListRepository appsIntroducingNewTracker.forEach { app -> candidates.add( WeeklyReport( endOfWeek, WeeklyReport.StatType.NEW_TRACKER, WeeklyReport.LabelId.NEW_TRACKER_1, anyApp2, app.id, emptyList() ) ) } val newTrackersCount = newTrackersDetected.map { it.first }.toSet().size if (newTrackersCount > 0) { candidates.add( WeeklyReport( endOfWeek, WeeklyReport.StatType.NEW_TRACKER, WeeklyReport.LabelId.NEW_TRACKER_2, "", listOf(Random.nextInt(4).toString()) listOf(newTrackersCount.toString()) ) ) } if (appsIntroducingNewTracker.isNotEmpty()) { candidates.add( WeeklyReport( endOfWeek, WeeklyReport.StatType.NEW_TRACKER, WeeklyReport.LabelId.NEW_TRACKER_3, "", listOf(Random.nextInt(4).toString()) listOf(appsIntroducingNewTracker.size.toString()) ) ) } } private fun addCallAndLeaksCandidates(candidates: MutableList<WeeklyReport>, endOfWeek: Instant) { val blockedRate = Random.nextInt(100).toString() Loading Loading @@ -268,6 +287,10 @@ class WeeklyReportUseCase( ) } private fun getStartOfWeek(endOfWeek: Instant): Instant { return endOfWeek.minus(7, ChronoUnit.DAYS) } private fun WeeklyReport.toDisplayableReport(): DisplayableReport? { val weeklyReport = this return when (weeklyReport.labelId) { Loading app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardViewModel.kt +2 −2 Original line number Diff line number Diff line Loading @@ -130,12 +130,12 @@ class DashboardViewModel( } fun onClickViewAllApps() = viewModelScope.launch { trackersScreenUseCase.preselectTab(Period.MONTH.ordinal, TrackerTab.APPS.ordinal) trackersScreenUseCase.preselectTab(Period.MONTH, TrackerTab.APPS) _navigate.emit(DashboardFragmentDirections.gotoTrackersFragment()) } fun onClickViewAllTrackers() = viewModelScope.launch { trackersScreenUseCase.preselectTab(Period.MONTH.ordinal, TrackerTab.TRACKERS.ordinal) trackersScreenUseCase.preselectTab(Period.MONTH, TrackerTab.TRACKERS) _navigate.emit(DashboardFragmentDirections.gotoTrackersFragment()) } private suspend fun fetchStatistics() = withContext(Dispatchers.IO) { Loading Loading
app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt +1 −1 Original line number Diff line number Diff line Loading @@ -228,7 +228,7 @@ val appModule = module { viewModelOf(::InternetPrivacyViewModel) viewModelOf(::DashboardViewModel) single { WeeklyReportViewFactory() } single { WeeklyReportViewFactory(context = androidContext()) } single { NotificationsPresenter( Loading
app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersAndAppsListsUseCase.kt +1 −1 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ class TrackersAndAppsListsUseCase( private suspend fun getCountByEntityMaps(period: Period): CountByEntitiesMaps { val periodStart: Instant = period.getPeriodStart() val trackersAndAppsIds = statsDatabase.getDistinctTrackerAndApp(periodStart) val trackersAndAppsIds = statsDatabase.getDistinctTrackerAndApp(periodStart, Instant.now()) val trackersAndApps = mapIdsToEntities(trackersAndAppsIds) return foldToCountByEntityMaps(trackersAndApps) } Loading
app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersScreenUseCase.kt +13 −3 Original line number Diff line number Diff line Loading @@ -18,14 +18,20 @@ package foundation.e.advancedprivacy.domain.usecases import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository import foundation.e.advancedprivacy.features.trackers.Period import foundation.e.advancedprivacy.features.trackers.TrackerTab import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.withContext class TrackersScreenUseCase( private val localStateRepository: LocalStateRepository, private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO ) { private val _goToTab = MutableSharedFlow<Pair<Int, Int>>() val goToTab: SharedFlow<Pair<Int, Int>> = _goToTab suspend fun getLastPosition(): Int = withContext(backgroundDispatcher) { localStateRepository.getTrackersScreenLastPosition() Loading @@ -43,8 +49,12 @@ class TrackersScreenUseCase( localStateRepository.trackersScreenTabStartPosition = -1 } suspend fun preselectTab(periodPosition: Int, tabPosition: Int) = withContext(backgroundDispatcher) { localStateRepository.setTrackersScreenLastPosition(periodPosition) localStateRepository.trackersScreenTabStartPosition = tabPosition suspend fun preselectTab(period: Period, tab: TrackerTab) = withContext(backgroundDispatcher) { localStateRepository.setTrackersScreenLastPosition(period.ordinal) localStateRepository.trackersScreenTabStartPosition = tab.ordinal } suspend fun selectTab(period: Period, tab: TrackerTab) { _goToTab.emit(period.ordinal to tab.ordinal) } }
app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt +51 −28 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import foundation.e.advancedprivacy.data.repositories.WeeklyReportLocalRepositor import foundation.e.advancedprivacy.domain.entities.weeklyreport.DisplayableReport import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReport import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReportScore import foundation.e.advancedprivacy.trackers.data.StatsDatabase import foundation.e.advancedprivacy.trackers.data.TrackersRepository import java.time.Duration import java.time.Instant Loading @@ -40,6 +41,7 @@ class WeeklyReportUseCase( private val trackersRepository: TrackersRepository, private val appListRepository: AppListRepository, private val weeklyReportRepository: WeeklyReportLocalRepository, private val statsDatabase: StatsDatabase, private val scope: CoroutineScope ) { private val _currentReport = MutableStateFlow<DisplayableReport?>(null) Loading @@ -55,7 +57,7 @@ class WeeklyReportUseCase( } } private suspend fun updateCurrent() { suspend fun updateCurrent() { val weeklyReport = weeklyReportRepository.getLastWeeklyReport() ?: return val now = Instant.now() val endOfDisplay = weeklyReport.timestamp + displayDuration Loading Loading @@ -97,7 +99,7 @@ class WeeklyReportUseCase( result.reversed() } private fun buildCandidates(endOfWeek: Instant, history: List<WeeklyReport>): List<WeeklyReportScore> { private suspend fun buildCandidates(endOfWeek: Instant, history: List<WeeklyReport>): List<WeeklyReportScore> { val candidates = mutableListOf<WeeklyReport>() addCallPerAppCandidates(candidates, endOfWeek) addNewTrackerCandidates(candidates, endOfWeek) Loading Loading @@ -143,38 +145,55 @@ class WeeklyReportUseCase( ) } private fun addNewTrackerCandidates(candidates: MutableList<WeeklyReport>, endOfWeek: Instant) { val anyApp2 = appListRepository.displayableApps.value.first().id private suspend fun addNewTrackerCandidates(candidates: MutableList<WeeklyReport>, endOfWeek: Instant) { val startOfWeek = endOfWeek.minus(7, ChronoUnit.DAYS) val startOfYear = endOfWeek.minus(365, ChronoUnit.DAYS) val trackerAppsHistoric = statsDatabase.getDistinctTrackerAndApp(startOfYear, startOfWeek) val trackerAppsOfWeek = statsDatabase.getDistinctTrackerAndApp(startOfWeek, endOfWeek) val historicTrackers = trackerAppsHistoric.map { it.first }.toSet() val newTrackersDetected = trackerAppsOfWeek.filter { it.first !in historicTrackers } val appsIntroducingNewTracker = newTrackersDetected.mapNotNull { appListRepository.getAppById(it.second) }.toSet() // TODO dummy apps ?&& displayableApp != appListRepository appsIntroducingNewTracker.forEach { app -> candidates.add( WeeklyReport( endOfWeek, WeeklyReport.StatType.NEW_TRACKER, WeeklyReport.LabelId.NEW_TRACKER_1, anyApp2, app.id, emptyList() ) ) } val newTrackersCount = newTrackersDetected.map { it.first }.toSet().size if (newTrackersCount > 0) { candidates.add( WeeklyReport( endOfWeek, WeeklyReport.StatType.NEW_TRACKER, WeeklyReport.LabelId.NEW_TRACKER_2, "", listOf(Random.nextInt(4).toString()) listOf(newTrackersCount.toString()) ) ) } if (appsIntroducingNewTracker.isNotEmpty()) { candidates.add( WeeklyReport( endOfWeek, WeeklyReport.StatType.NEW_TRACKER, WeeklyReport.LabelId.NEW_TRACKER_3, "", listOf(Random.nextInt(4).toString()) listOf(appsIntroducingNewTracker.size.toString()) ) ) } } private fun addCallAndLeaksCandidates(candidates: MutableList<WeeklyReport>, endOfWeek: Instant) { val blockedRate = Random.nextInt(100).toString() Loading Loading @@ -268,6 +287,10 @@ class WeeklyReportUseCase( ) } private fun getStartOfWeek(endOfWeek: Instant): Instant { return endOfWeek.minus(7, ChronoUnit.DAYS) } private fun WeeklyReport.toDisplayableReport(): DisplayableReport? { val weeklyReport = this return when (weeklyReport.labelId) { Loading
app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardViewModel.kt +2 −2 Original line number Diff line number Diff line Loading @@ -130,12 +130,12 @@ class DashboardViewModel( } fun onClickViewAllApps() = viewModelScope.launch { trackersScreenUseCase.preselectTab(Period.MONTH.ordinal, TrackerTab.APPS.ordinal) trackersScreenUseCase.preselectTab(Period.MONTH, TrackerTab.APPS) _navigate.emit(DashboardFragmentDirections.gotoTrackersFragment()) } fun onClickViewAllTrackers() = viewModelScope.launch { trackersScreenUseCase.preselectTab(Period.MONTH.ordinal, TrackerTab.TRACKERS.ordinal) trackersScreenUseCase.preselectTab(Period.MONTH, TrackerTab.TRACKERS) _navigate.emit(DashboardFragmentDirections.gotoTrackersFragment()) } private suspend fun fetchStatistics() = withContext(Dispatchers.IO) { Loading