fix(notification): Prevent duplicate notifications during backup and restore processes (#933)

Avoid calling show() before returning builder for ForegroundInfo
This commit is contained in:
Cuong-Tran 2025-05-27 12:35:57 +07:00 committed by GitHub
parent 46c3f1ef2f
commit 068dc188ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 92 additions and 38 deletions

View file

@ -52,7 +52,7 @@ class BackupNotifier(private val context: Context) {
setAutoCancel(false)
}
private fun NotificationCompat.Builder.show(id: Int) {
internal fun NotificationCompat.Builder.show(id: Int) {
context.notify(id, build())
}
@ -63,7 +63,11 @@ class BackupNotifier(private val context: Context) {
setProgress(0, 0, true)
}
builder.show(Notifications.ID_BACKUP_PROGRESS)
// KMK -->
// Avoid calling show() before returning builder for ForegroundInfo.
// Calling show() here can cause duplicate notifications, as setForegroundSafely will display the notification using the returned builder.
// builder.show(Notifications.ID_BACKUP_PROGRESS)
// KMK <--
return builder
}
@ -129,7 +133,11 @@ class BackupNotifier(private val context: Context) {
)
}
builder.show(Notifications.ID_RESTORE_PROGRESS)
// KMK -->
// Avoid calling show() before returning builder for ForegroundInfo.
// Calling show() here can cause duplicate notifications, as setForegroundSafely will display the notification using the returned builder.
// builder.show(Notifications.ID_RESTORE_PROGRESS)
// KMK <--
return builder
}

View file

@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.data.backup.restore.restorers.FeedRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.MangaRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.PreferenceRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.SavedSearchRestorer
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
@ -139,12 +140,17 @@ class BackupRestorer(
categoriesRestorer(backupCategories)
restoreProgress += 1
notifier.showRestoreProgress(
context.stringResource(MR.strings.categories),
restoreProgress,
restoreAmount,
isSync,
)
with(notifier) {
showRestoreProgress(
context.stringResource(MR.strings.categories),
restoreProgress,
restoreAmount,
isSync,
)
// KMK -->
.show(Notifications.ID_RESTORE_PROGRESS)
// KMK <--
}
}
// SY -->
@ -161,12 +167,17 @@ class BackupRestorer(
// KMK <--
restoreProgress += 1
notifier.showRestoreProgress(
context.stringResource(KMR.strings.saved_searches_feeds),
restoreProgress,
restoreAmount,
isSync,
)
with(notifier) {
showRestoreProgress(
context.stringResource(KMR.strings.saved_searches_feeds),
restoreProgress,
restoreAmount,
isSync,
)
// KMK -->
.show(Notifications.ID_RESTORE_PROGRESS)
// KMK <--
}
}
// SY <--
@ -186,7 +197,12 @@ class BackupRestorer(
}
restoreProgress += 1
notifier.showRestoreProgress(it.title, restoreProgress, restoreAmount, isSync)
with(notifier) {
showRestoreProgress(it.title, restoreProgress, restoreAmount, isSync)
// KMK -->
.show(Notifications.ID_RESTORE_PROGRESS)
// KMK <--
}
}
}
@ -201,12 +217,17 @@ class BackupRestorer(
)
restoreProgress += 1
notifier.showRestoreProgress(
context.stringResource(MR.strings.app_settings),
restoreProgress,
restoreAmount,
isSync,
)
with(notifier) {
showRestoreProgress(
context.stringResource(MR.strings.app_settings),
restoreProgress,
restoreAmount,
isSync,
)
// KMK -->
.show(Notifications.ID_RESTORE_PROGRESS)
// KMK <--
}
}
private fun CoroutineScope.restoreSourcePreferences(preferences: List<BackupSourcePreferences>) = launch {
@ -214,12 +235,17 @@ class BackupRestorer(
preferenceRestorer.restoreSource(preferences)
restoreProgress += 1
notifier.showRestoreProgress(
context.stringResource(MR.strings.source_settings),
restoreProgress,
restoreAmount,
isSync,
)
with(notifier) {
showRestoreProgress(
context.stringResource(MR.strings.source_settings),
restoreProgress,
restoreAmount,
isSync,
)
// KMK -->
.show(Notifications.ID_RESTORE_PROGRESS)
// KMK <--
}
}
private fun CoroutineScope.restoreExtensionRepos(
@ -236,12 +262,17 @@ class BackupRestorer(
}
restoreProgress += 1
notifier.showRestoreProgress(
context.stringResource(MR.strings.extensionRepo_settings),
restoreProgress,
restoreAmount,
isSync,
)
with(notifier) {
showRestoreProgress(
context.stringResource(MR.strings.extensionRepo_settings),
restoreProgress,
restoreAmount,
isSync,
)
// KMK -->
.show(Notifications.ID_RESTORE_PROGRESS)
// KMK <--
}
}
}

View file

@ -74,7 +74,11 @@ class SyncNotifier(private val context: Context) {
)
}
builder.show(Notifications.ID_SYNC_PROGRESS)
// KMK -->
// Avoid calling show() before returning builder for ForegroundInfo.
// Calling show() here can cause duplicate notifications, as setForegroundSafely will display the notification using the returned builder.
// builder.show(Notifications.ID_SYNC_PROGRESS)
// KMK <--
return builder
}

View file

@ -124,7 +124,12 @@ class AppUpdateDownloadJob(private val context: Context, workerParams: WorkerPar
*/
private suspend fun downloadApk(title: String, url: String) = coroutineScope {
// Show notification download starting.
notifier.onDownloadStarted(title)
with(notifier) {
onDownloadStarted(title)
// KMK -->
.show()
// KMK <--
}
val progressListener = object : ProgressListener {
// KMK -->

View file

@ -32,7 +32,7 @@ internal class AppUpdateNotifier(private val context: Context) {
*
* @param id id of the notification channel.
*/
private fun NotificationCompat.Builder.show(id: Int = Notifications.ID_APP_UPDATER) {
internal fun NotificationCompat.Builder.show(id: Int = Notifications.ID_APP_UPDATER) {
context.notify(id, build())
}
@ -102,7 +102,13 @@ internal class AppUpdateNotifier(private val context: Context) {
NotificationReceiver.cancelDownloadAppUpdatePendingBroadcast(context),
)
}
notificationBuilder.show()
// KMK -->
// Avoid calling show() before returning builder for ForegroundInfo.
// Calling show() here can cause duplicate notifications, as setForegroundSafely will display the notification using the returned builder.
// notificationBuilder.show()
// KMK <--
return notificationBuilder
}