From 2e0a5f7b9cef13ac354a6229c798c720b8a3960d Mon Sep 17 00:00:00 2001 From: zarzet Date: Sun, 30 Aug 2026 18:58:19 +0700 Subject: [PATCH] fix(downloads): hide unknown byte totals in notifications --- .../src/main/kotlin/com/zarz/spotiflac/DownloadService.kt | 8 ++++++-- .../kotlin/com/zarz/spotiflac/NativeWorkerPolicyTest.kt | 8 ++++++++ lib/providers/download_queue_provider_progress.dart | 7 +++++-- lib/services/platform_bridge.dart | 4 ++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/kotlin/com/zarz/spotiflac/DownloadService.kt b/android/app/src/main/kotlin/com/zarz/spotiflac/DownloadService.kt index a9477f50..a780d632 100644 --- a/android/app/src/main/kotlin/com/zarz/spotiflac/DownloadService.kt +++ b/android/app/src/main/kotlin/com/zarz/spotiflac/DownloadService.kt @@ -89,10 +89,14 @@ class DownloadService : Service() { internal const val NATIVE_REPLAYGAIN_JOURNAL_FILE = "native_replaygain_journal.json" internal const val NATIVE_WORKER_CONTRACT_VERSION = NativeDownloadFinalizer.NATIVE_WORKER_CONTRACT_VERSION internal const val NOTIFICATION_PERCENT_TOTAL = 10_000L + private const val LEGACY_NOTIFICATION_PERCENT_TOTAL = 100L internal val NATIVE_WORKER_STATE_FILE_LOCK = Any() internal val NATIVE_REPLAYGAIN_JOURNAL_FILE_LOCK = Any() private var isRunning = false + + internal fun isPercentOnlyNotificationTotal(total: Long): Boolean = + total == NOTIFICATION_PERCENT_TOTAL || total == LEGACY_NOTIFICATION_PERCENT_TOTAL fun isServiceRunning(): Boolean = isRunning @@ -1818,7 +1822,7 @@ class DownloadService : Service() { val visibleProgress = when { total <= 0L -> "indeterminate" - total == NOTIFICATION_PERCENT_TOTAL -> + isPercentOnlyNotificationTotal(total) -> "percent:${(progress * 100 / total).toInt()}" else -> { // buildNotification renders one decimal place for MB and an @@ -1909,7 +1913,7 @@ class DownloadService : Service() { "Preparing download..." } else if (currentArtistName.isNotEmpty() && queueCount <= 1) { currentArtistName - } else if (total == NOTIFICATION_PERCENT_TOTAL) { + } else if (isPercentOnlyNotificationTotal(total)) { val progressPercent = (progress * 100 / total).toInt() "$progressPercent%" } else if (total > 0) { diff --git a/android/app/src/test/kotlin/com/zarz/spotiflac/NativeWorkerPolicyTest.kt b/android/app/src/test/kotlin/com/zarz/spotiflac/NativeWorkerPolicyTest.kt index a0470a12..5c278c65 100644 --- a/android/app/src/test/kotlin/com/zarz/spotiflac/NativeWorkerPolicyTest.kt +++ b/android/app/src/test/kotlin/com/zarz/spotiflac/NativeWorkerPolicyTest.kt @@ -6,6 +6,14 @@ import org.junit.Assert.assertTrue import org.junit.Test class NativeWorkerPolicyTest { + @Test + fun percentOnlyNotificationTotalsDoNotRenderAsBytes() { + assertTrue(DownloadService.isPercentOnlyNotificationTotal(10_000L)) + assertTrue(DownloadService.isPercentOnlyNotificationTotal(100L)) + assertFalse(DownloadService.isPercentOnlyNotificationTotal(72L * 1024L * 1024L)) + assertFalse(DownloadService.isPercentOnlyNotificationTotal(0L)) + } + @Test fun rateLimitRetriesExactlyOnce() { assertTrue( diff --git a/lib/providers/download_queue_provider_progress.dart b/lib/providers/download_queue_provider_progress.dart index 30a5793e..6bb4907f 100644 --- a/lib/providers/download_queue_provider_progress.dart +++ b/lib/providers/download_queue_provider_progress.dart @@ -373,8 +373,11 @@ extension _DownloadQueueProgress on DownloadQueueNotifier { notifProgress = 0; notifTotal = 0; } else if (bytesTotal <= 0) { - notifProgress = (progressPercent * 100).toInt(); - notifTotal = 100; + notifTotal = PlatformBridge.notificationPercentTotal; + notifProgress = (progressPercent * notifTotal) + .round() + .clamp(0, notifTotal) + .toInt(); } final serviceStatus = notifTotal <= 0 ? 'preparing' : 'downloading'; diff --git a/lib/services/platform_bridge.dart b/lib/services/platform_bridge.dart index 88b2b359..c2cc6faf 100644 --- a/lib/services/platform_bridge.dart +++ b/lib/services/platform_bridge.dart @@ -145,6 +145,10 @@ class _BridgeInFlight { } class PlatformBridge { + /// Sentinel shared with Android's foreground service for progress reports + /// that contain a percentage but no byte counts. + static const int notificationPercentTotal = 10000; + static const _channel = MethodChannel('com.zarz.spotiflac/backend'); static const _jsonResultFileKey = '__json_file'; static const _backgroundJsonDecodeThresholdBytes = 128 * 1024;