From 12a48168021ab3ddcb1bc8f2ccf10629402a1f2a Mon Sep 17 00:00:00 2001 From: jacquarg Date: Tue, 15 Apr 2025 09:05:18 +0200 Subject: [PATCH 1/3] fix:3233: weeklyreport infinite loop on sunday and fix 3240 weeklyreport not dismissed after 24h --- .../AdvancedPrivacyApplication.kt | 5 +- .../e/advancedprivacy/KoinModule.kt | 3 + .../domain/usecases/WeeklyReportUseCase.kt | 24 +++--- .../workers/WeeklyReportWorker.kt | 75 ++++++++++++++----- 4 files changed, 74 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt b/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt index 7b7353b8..5b298b7e 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt @@ -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::class.java).initTrackersFile() UpdateTrackersWorker.periodicUpdate(this@AdvancedPrivacyApplication) - WeeklyReportWorker.scheduleNext(this@AdvancedPrivacyApplication) WarningDialog.startListening( get(ShowFeaturesWarningUseCase::class.java), diff --git a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt index 20f78870..e87242da 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt @@ -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 { diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt index 26f16e57..d7176b46 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt @@ -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.externalinterfaces.workers.WeeklyReportWorkerScheduler import foundation.e.advancedprivacy.trackers.data.StatsDatabase import foundation.e.advancedprivacy.trackers.data.TrackersRepository import java.time.Duration @@ -32,8 +33,6 @@ 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 +42,43 @@ 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 DISPLAY_DURATION: Duration = Duration.ofDays(1) + } private val _currentReport = MutableStateFlow(null) val currentReport: StateFlow = _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 + val endOfDisplay = weeklyReport.timestamp + DISPLAY_DURATION if (now < endOfDisplay) { _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>> = diff --git a/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt b/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt index a3a7e2c2..5a6df0c8 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt @@ -23,7 +23,10 @@ import androidx.work.ExistingWorkPolicy import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import androidx.work.WorkerParameters +import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReport import foundation.e.advancedprivacy.domain.usecases.WeeklyReportUseCase +import java.time.Instant +import java.time.ZoneId import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.time.temporal.WeekFields @@ -34,31 +37,67 @@ import timber.log.Timber class WeeklyReportWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) { override suspend fun doWork(): Result { Timber.d("WeeklyReportWorker starts computing this week report") + val weeklyReportWorkerScheduler: WeeklyReportWorkerScheduler = get(WeeklyReportWorkerScheduler::class.java) val weeklyReportUseCase: WeeklyReportUseCase = get(WeeklyReportUseCase::class.java) - weeklyReportUseCase.updateWeeklyReport() - scheduleNext(applicationContext) + val newReport = weeklyReportUseCase.updateWeeklyReport() + weeklyReportWorkerScheduler.scheduleNext(newReport) + weeklyReportWorkerScheduler.scheduleDismiss(newReport) return Result.success() } +} + +class WeeklyReportDismissWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) { + override suspend fun doWork(): Result { + Timber.d("WeeklyReportDismissWorker will dismiss any displayed WeeklyReport") + val weeklyReportUseCase: WeeklyReportUseCase = get(WeeklyReportUseCase::class.java) + weeklyReportUseCase.updateCurrent() + return Result.success() + } +} - companion object { - fun scheduleNext(appContext: Context) { - var next = ZonedDateTime.now() - next = next.with(WeekFields.of(appContext.resources.configuration.locales[0]).dayOfWeek(), 7) - next = next.truncatedTo(ChronoUnit.DAYS) - next = next.plus(11, ChronoUnit.HOURS) +class WeeklyReportWorkerScheduler(private val appContext: Context) { + fun scheduleNext(lastReport: WeeklyReport?) { + val now = ZonedDateTime.now() + var next = now + next = next.with(WeekFields.of(appContext.resources.configuration.locales[0]).dayOfWeek(), 7) + next = next.truncatedTo(ChronoUnit.DAYS) - val delay = next.toEpochSecond() - ZonedDateTime.now().toEpochSecond() - Timber.d("Schedule Weeklyreport for $next, in $delay seconds") + if (next.toLocalDate() == lastReport?.timestamp?.atZone(ZoneId.systemDefault())?.toLocalDate() && now.hour >= 11) { + next = next.plus(7, ChronoUnit.DAYS) + } + + next = next.plus(11, ChronoUnit.HOURS) - val request = OneTimeWorkRequestBuilder() - .setInitialDelay(delay, TimeUnit.SECONDS) - .build() + val delay = next.toEpochSecond() - ZonedDateTime.now().toEpochSecond() + Timber.d("Schedule Weeklyreport for $next, in $delay seconds") - WorkManager.getInstance(appContext).enqueueUniqueWork( - WeeklyReportWorker::class.qualifiedName ?: "", - ExistingWorkPolicy.REPLACE, - request - ) + val request = OneTimeWorkRequestBuilder() + .setInitialDelay(delay, TimeUnit.SECONDS) + .build() + + WorkManager.getInstance(appContext).enqueueUniqueWork( + WeeklyReportWorker::class.qualifiedName ?: "", + ExistingWorkPolicy.REPLACE, + request + ) + } + + fun scheduleDismiss(currentReport: WeeklyReport?) { + val next = currentReport?.timestamp?.plus(WeeklyReportUseCase.DISPLAY_DURATION) ?: return + val delay = next.toEpochMilli() - Instant.now().toEpochMilli() + if (delay < 0) { + return } + + Timber.d("Schedule Dismiss of WeeklyReport of ${currentReport.timestamp} at $next, in $delay milliseconds") + val request = OneTimeWorkRequestBuilder() + .setInitialDelay(delay, TimeUnit.MILLISECONDS) + .build() + + WorkManager.getInstance(appContext).enqueueUniqueWork( + WeeklyReportDismissWorker::class.qualifiedName ?: "", + ExistingWorkPolicy.REPLACE, + request + ) } } -- GitLab From fb82df9a4210b20a46c0fc7efe139b57008ace4a Mon Sep 17 00:00:00 2001 From: jacquarg Date: Tue, 15 Apr 2025 17:37:25 +0200 Subject: [PATCH 2/3] fix:3233: dismiss report at end of day --- .../entities/weeklyreport/WeeklyReport.kt | 6 +++++ .../domain/usecases/WeeklyReportUseCase.kt | 9 +++---- .../workers/WeeklyReportWorker.kt | 26 ++++++++++++------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/entities/weeklyreport/WeeklyReport.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/entities/weeklyreport/WeeklyReport.kt index 7e93b8e7..3fc97bcd 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/entities/weeklyreport/WeeklyReport.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/entities/weeklyreport/WeeklyReport.kt @@ -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 ) { + fun getDate(): LocalDate { + return timestamp.atZone(ZoneId.systemDefault()).toLocalDate() + } + @Serializable enum class StatType { CALLS_PER_APP, diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt index d7176b46..16f62c29 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt @@ -25,8 +25,8 @@ import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReportSco 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.Instant +import java.time.LocalDate import java.time.temporal.ChronoUnit import kotlin.collections.component1 import kotlin.collections.component2 @@ -47,7 +47,8 @@ class WeeklyReportUseCase( private val scope: CoroutineScope ) { companion object { - val DISPLAY_DURATION: Duration = Duration.ofDays(1) + const val REPORT_DAY_OF_WEEK: Long = 7L + const val REPORT_HOUR: Long = 11L } private val _currentReport = MutableStateFlow(null) val currentReport: StateFlow = _currentReport @@ -63,9 +64,7 @@ class WeeklyReportUseCase( suspend fun updateCurrent() { val weeklyReport = weeklyReportRepository.getLastWeeklyReport() ?: return - val now = Instant.now() - val endOfDisplay = weeklyReport.timestamp + DISPLAY_DURATION - if (now < endOfDisplay) { + if (LocalDate.now() == weeklyReport.getDate()) { _currentReport.value = weeklyReport.toDisplayableReport() } else { _currentReport.value = null diff --git a/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt b/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt index 5a6df0c8..66f83225 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt @@ -25,7 +25,6 @@ import androidx.work.WorkManager import androidx.work.WorkerParameters import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReport import foundation.e.advancedprivacy.domain.usecases.WeeklyReportUseCase -import java.time.Instant import java.time.ZoneId import java.time.ZonedDateTime import java.time.temporal.ChronoUnit @@ -59,16 +58,18 @@ class WeeklyReportWorkerScheduler(private val appContext: Context) { fun scheduleNext(lastReport: WeeklyReport?) { val now = ZonedDateTime.now() var next = now - next = next.with(WeekFields.of(appContext.resources.configuration.locales[0]).dayOfWeek(), 7) + next = next.with(WeekFields.of(appContext.resources.configuration.locales[0]).dayOfWeek(), WeeklyReportUseCase.REPORT_DAY_OF_WEEK) next = next.truncatedTo(ChronoUnit.DAYS) - if (next.toLocalDate() == lastReport?.timestamp?.atZone(ZoneId.systemDefault())?.toLocalDate() && now.hour >= 11) { + // Report has already been created today, + // next report will be scheduled for next week + if (next.toLocalDate() == lastReport?.timestamp && now.hour >= WeeklyReportUseCase.REPORT_HOUR) { next = next.plus(7, ChronoUnit.DAYS) } - next = next.plus(11, ChronoUnit.HOURS) + next = next.plus(WeeklyReportUseCase.REPORT_HOUR, ChronoUnit.HOURS) - val delay = next.toEpochSecond() - ZonedDateTime.now().toEpochSecond() + val delay = next.toEpochSecond() - now.toEpochSecond() Timber.d("Schedule Weeklyreport for $next, in $delay seconds") val request = OneTimeWorkRequestBuilder() @@ -83,15 +84,22 @@ class WeeklyReportWorkerScheduler(private val appContext: Context) { } fun scheduleDismiss(currentReport: WeeklyReport?) { - val next = currentReport?.timestamp?.plus(WeeklyReportUseCase.DISPLAY_DURATION) ?: return - val delay = next.toEpochMilli() - Instant.now().toEpochMilli() + if (currentReport == null) { + return + } + + val dismiss = ZonedDateTime.ofInstant(currentReport.timestamp, ZoneId.systemDefault()) + .plus(1, ChronoUnit.DAYS) + .truncatedTo(ChronoUnit.DAYS) + + val delay = dismiss.toEpochSecond() - ZonedDateTime.now().toEpochSecond() if (delay < 0) { return } - Timber.d("Schedule Dismiss of WeeklyReport of ${currentReport.timestamp} at $next, in $delay milliseconds") + Timber.d("Schedule Dismiss of WeeklyReport of ${currentReport.timestamp} at $dismiss, in $delay seconds") val request = OneTimeWorkRequestBuilder() - .setInitialDelay(delay, TimeUnit.MILLISECONDS) + .setInitialDelay(delay, TimeUnit.SECONDS) .build() WorkManager.getInstance(appContext).enqueueUniqueWork( -- GitLab From 581659ba9bf82bd404f956a5c1d24e165c5e9e3c Mon Sep 17 00:00:00 2001 From: jacquarg Date: Wed, 16 Apr 2025 08:19:03 +0200 Subject: [PATCH 3/3] fix:3241: Display weekly report on Sundays --- .../WeeklyReportLocalRepository.kt | 4 +++ .../domain/usecases/WeeklyReportUseCase.kt | 4 ++- .../workers/WeeklyReportWorker.kt | 14 ++++++---- .../debug/DebugWeeklyReportFragment.kt | 6 ++++ .../layout/debug_weekly_report_fragment.xml | 28 ++++++++++++++----- app/src/main/res/values/debug_strings.xml | 1 + 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/foundation/e/advancedprivacy/data/repositories/WeeklyReportLocalRepository.kt b/app/src/main/java/foundation/e/advancedprivacy/data/repositories/WeeklyReportLocalRepository.kt index 220a655c..fd760089 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/data/repositories/WeeklyReportLocalRepository.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/data/repositories/WeeklyReportLocalRepository.kt @@ -64,4 +64,8 @@ class WeeklyReportLocalRepository( }.getOrNull() } ?: emptyList() } + + suspend fun clearAllReports() { + return store.removeKey(weeklyReportsKey) + } } diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt index 16f62c29..735095e6 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/WeeklyReportUseCase.kt @@ -25,6 +25,8 @@ import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReportSco import foundation.e.advancedprivacy.externalinterfaces.workers.WeeklyReportWorkerScheduler import foundation.e.advancedprivacy.trackers.data.StatsDatabase import foundation.e.advancedprivacy.trackers.data.TrackersRepository +import java.time.DayOfWeek +import java.time.DayOfWeek.SUNDAY import java.time.Instant import java.time.LocalDate import java.time.temporal.ChronoUnit @@ -47,7 +49,7 @@ class WeeklyReportUseCase( private val scope: CoroutineScope ) { companion object { - const val REPORT_DAY_OF_WEEK: Long = 7L + val REPORT_DAY_OF_WEEK: DayOfWeek = SUNDAY const val REPORT_HOUR: Long = 11L } private val _currentReport = MutableStateFlow(null) diff --git a/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt b/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt index 66f83225..80d8fe49 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/externalinterfaces/workers/WeeklyReportWorker.kt @@ -25,10 +25,11 @@ import androidx.work.WorkManager import androidx.work.WorkerParameters import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReport import foundation.e.advancedprivacy.domain.usecases.WeeklyReportUseCase +import java.time.LocalDate import java.time.ZoneId import java.time.ZonedDateTime import java.time.temporal.ChronoUnit -import java.time.temporal.WeekFields +import java.time.temporal.TemporalAdjusters.nextOrSame import java.util.concurrent.TimeUnit import org.koin.java.KoinJavaComponent.get import timber.log.Timber @@ -57,16 +58,17 @@ class WeeklyReportDismissWorker(appContext: Context, workerParams: WorkerParamet class WeeklyReportWorkerScheduler(private val appContext: Context) { fun scheduleNext(lastReport: WeeklyReport?) { val now = ZonedDateTime.now() - var next = now - next = next.with(WeekFields.of(appContext.resources.configuration.locales[0]).dayOfWeek(), WeeklyReportUseCase.REPORT_DAY_OF_WEEK) - next = next.truncatedTo(ChronoUnit.DAYS) + var nextDate: LocalDate = now.toLocalDate() + + nextDate.with(nextOrSame(WeeklyReportUseCase.REPORT_DAY_OF_WEEK)) // Report has already been created today, // next report will be scheduled for next week - if (next.toLocalDate() == lastReport?.timestamp && now.hour >= WeeklyReportUseCase.REPORT_HOUR) { - next = next.plus(7, ChronoUnit.DAYS) + if (nextDate == lastReport?.getDate() && now.hour >= WeeklyReportUseCase.REPORT_HOUR) { + nextDate = nextDate.plus(7, ChronoUnit.DAYS) } + var next = nextDate.atStartOfDay(ZoneId.systemDefault()) next = next.plus(WeeklyReportUseCase.REPORT_HOUR, ChronoUnit.HOURS) val delay = next.toEpochSecond() - now.toEpochSecond() diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/debug/DebugWeeklyReportFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/debug/DebugWeeklyReportFragment.kt index 2544e845..57453f3b 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/debug/DebugWeeklyReportFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/debug/DebugWeeklyReportFragment.kt @@ -147,6 +147,12 @@ class DebugWeeklyReportFragment : Fragment(R.layout.debug_weekly_report_fragment } } + binding.debugClearAllReport.setOnClickListener { + lifecycleScope.launch(Dispatchers.IO) { + weeklyReportRepository.clearAllReports() + } + } + binding.debugGenerateOldReport.setOnClickListener { lifecycleScope.launch { val count = binding.debugWeeksAgo.text.toString().toInt() diff --git a/app/src/main/res/layout/debug_weekly_report_fragment.xml b/app/src/main/res/layout/debug_weekly_report_fragment.xml index e0f1297b..713163ae 100644 --- a/app/src/main/res/layout/debug_weekly_report_fragment.xml +++ b/app/src/main/res/layout/debug_weekly_report_fragment.xml @@ -25,13 +25,27 @@ android:layout_width="match_parent" android:orientation="vertical" > - + + + + AdvancedPrivacy debug tools Weekly Report debug tools Update report + Clear all reports Generate report of week ago: Share Details -- GitLab