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

Commit 681accd2 authored by Guillaume Jacquart's avatar Guillaume Jacquart
Browse files

Merge branch '3233-weeklyreport_infinite_loop' into 'main'

fix:3233: weeklyreport infinite loop on sunday

See merge request !196
parents 0c7d9c04 581659ba
Loading
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import foundation.e.advancedprivacy.domain.usecases.TrackersStateUseCase
import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase
import foundation.e.advancedprivacy.domain.usecases.VpnSupervisorUseCase
import foundation.e.advancedprivacy.domain.usecases.WeeklyReportUseCase
import foundation.e.advancedprivacy.externalinterfaces.workers.WeeklyReportWorker
import foundation.e.advancedprivacy.trackers.data.TrackersRepository
import foundation.e.advancedprivacy.trackers.services.UpdateTrackersWorker
import foundation.e.lib.telemetry.Telemetry
@@ -39,12 +38,15 @@ import kotlinx.coroutines.withContext
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
import org.koin.java.KoinJavaComponent.get
import timber.log.Timber

class AdvancedPrivacyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Telemetry.init(BuildConfig.SENTRY_DSN, this, true)

        Timber.plant(Timber.DebugTree())

        startKoin {
            androidContext(this@AdvancedPrivacyApplication)
            modules(appModule)
@@ -59,7 +61,6 @@ class AdvancedPrivacyApplication : Application() {
        get<TrackersRepository>(TrackersRepository::class.java).initTrackersFile()

        UpdateTrackersWorker.periodicUpdate(this@AdvancedPrivacyApplication)
        WeeklyReportWorker.scheduleNext(this@AdvancedPrivacyApplication)

        WarningDialog.startListening(
            get(ShowFeaturesWarningUseCase::class.java),
+3 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase
import foundation.e.advancedprivacy.domain.usecases.WeeklyReportUseCase
import foundation.e.advancedprivacy.dummy.CityDataSource
import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule
import foundation.e.advancedprivacy.externalinterfaces.workers.WeeklyReportWorkerScheduler
import foundation.e.advancedprivacy.features.dashboard.DashboardViewModel
import foundation.e.advancedprivacy.features.internetprivacy.InternetPrivacyViewModel
import foundation.e.advancedprivacy.features.location.FakeLocationViewModel
@@ -138,6 +139,8 @@ val appModule = module {
    single { CityDataSource }
    single { ResourcesRepository(androidContext()) }

    single { WeeklyReportWorkerScheduler(androidContext()) }

    singleOf(::FakeLocationStateUseCase)

    single {
+4 −0
Original line number Diff line number Diff line
@@ -64,4 +64,8 @@ class WeeklyReportLocalRepository(
            }.getOrNull()
        } ?: emptyList()
    }

    suspend fun clearAllReports() {
        return store.removeKey(weeklyReportsKey)
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package foundation.e.advancedprivacy.domain.entities.weeklyreport

import foundation.e.advancedprivacy.core.utils.InstantSerializer
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId
import kotlinx.serialization.Serializable

@Serializable
@@ -30,6 +32,10 @@ data class WeeklyReport(
    val primaryValue: String,
    val secondaryValues: List<String>
) {
    fun getDate(): LocalDate {
        return timestamp.atZone(ZoneId.systemDefault()).toLocalDate()
    }

    @Serializable
    enum class StatType {
        CALLS_PER_APP,
+15 −16
Original line number Diff line number Diff line
@@ -22,18 +22,19 @@ 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.externalinterfaces.workers.WeeklyReportWorkerScheduler
import foundation.e.advancedprivacy.trackers.data.StatsDatabase
import foundation.e.advancedprivacy.trackers.data.TrackersRepository
import java.time.Duration
import java.time.DayOfWeek
import java.time.DayOfWeek.SUNDAY
import java.time.Instant
import java.time.LocalDate
import java.time.temporal.ChronoUnit
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.random.Random
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
@@ -43,44 +44,42 @@ class WeeklyReportUseCase(
    private val trackersRepository: TrackersRepository,
    private val appListRepository: AppListRepository,
    private val weeklyReportRepository: WeeklyReportLocalRepository,
    private val weeklyReportWorkerScheduler: WeeklyReportWorkerScheduler,
    private val statsDatabase: StatsDatabase,
    private val scope: CoroutineScope
) {
    companion object {
        val REPORT_DAY_OF_WEEK: DayOfWeek = SUNDAY
        const val REPORT_HOUR: Long = 11L
    }
    private val _currentReport = MutableStateFlow<DisplayableReport?>(null)
    val currentReport: StateFlow<DisplayableReport?> = _currentReport

    private val displayDuration: Duration = Duration.ofDays(1)

    private var stopDisplayJob: Job? = null

    fun listen() {
        scope.launch {
            updateCurrent()
            val currentReport = currentReport.value?.report
            weeklyReportWorkerScheduler.scheduleNext(currentReport)
            weeklyReportWorkerScheduler.scheduleDismiss(currentReport)
        }
    }

    suspend fun updateCurrent() {
        val weeklyReport = weeklyReportRepository.getLastWeeklyReport() ?: return
        val now = Instant.now()
        val endOfDisplay = weeklyReport.timestamp + displayDuration
        if (now < endOfDisplay) {
        if (LocalDate.now() == weeklyReport.getDate()) {
            _currentReport.value = weeklyReport.toDisplayableReport()
            stopDisplayJob = scope.launch {
                delay(endOfDisplay.toEpochMilli() - now.toEpochMilli())
                _currentReport.value = null
                stopDisplayJob = null
            }
        } else {
            _currentReport.value = null
        }
    }

    suspend fun updateWeeklyReport() = withContext(Dispatchers.IO) {
    suspend fun updateWeeklyReport(): WeeklyReport = withContext(Dispatchers.IO) {
        val history = weeklyReportRepository.getLast99Reports()
        val weeklyReport = buildCandidates(Instant.now(), history).first().weeklyReport
        weeklyReportRepository.setLastWeeklyReport(weeklyReport)

        updateCurrent()
        weeklyReport
    }

    suspend fun debugGenerateReportsSinceWeeksAgo(weeksAgo: Int): List<Pair<DisplayableReport?, List<WeeklyReportScore>>> =
Loading