From 183744c41e01bd3c2af35e055fe6d88c07d13a1c Mon Sep 17 00:00:00 2001 From: zarzet Date: Sun, 26 Jul 2026 19:21:58 +0700 Subject: [PATCH] feat(android): home-screen download queue widget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A RemoteViews widget (no new dependencies) shows the active track, artist, queue count, and a coarse progress bar, with tap-to-open. DownloadService pushes updates only on discrete events — track or status changes and 25% progress steps, never per byte — matching the battery discipline; the last state persists so launcher refreshes render after process death. Colors use Material You system tokens on API 31+ with static light/dark fallbacks below. --- android/app/src/main/AndroidManifest.xml | 11 ++ .../spotiflac/DownloadQueueWidgetProvider.kt | 108 ++++++++++++++++++ .../com/zarz/spotiflac/DownloadService.kt | 50 +++++++- .../main/res/drawable/widget_download_bg.xml | 6 + .../main/res/layout/widget_download_queue.xml | 52 +++++++++ .../src/main/res/values-night-v31/colors.xml | 7 ++ .../app/src/main/res/values-night/colors.xml | 6 + .../app/src/main/res/values-v31/colors.xml | 7 ++ android/app/src/main/res/values/colors.xml | 4 + .../res/xml/widget_download_queue_info.xml | 8 ++ 10 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 android/app/src/main/kotlin/com/zarz/spotiflac/DownloadQueueWidgetProvider.kt create mode 100644 android/app/src/main/res/drawable/widget_download_bg.xml create mode 100644 android/app/src/main/res/layout/widget_download_queue.xml create mode 100644 android/app/src/main/res/values-night-v31/colors.xml create mode 100644 android/app/src/main/res/values-night/colors.xml create mode 100644 android/app/src/main/res/values-v31/colors.xml create mode 100644 android/app/src/main/res/xml/widget_download_queue_info.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9987354e..d799627e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -118,6 +118,17 @@ android:exported="false" android:foregroundServiceType="dataSync" /> + + + + + + + 0) { + ((progress * 100) / total).toInt().coerceIn(0, 100) + } else { + -1 + } + val bucket = if (percent < 0) -1 else percent / 25 + val signature = "$currentTrackName|$currentStatus|$queueCount|$bucket" + if (signature == widgetSignature) return + widgetSignature = signature + + val subtitle = when (currentStatus) { + "verification_required" -> "Verification required" + "rate_limited" -> "Rate limited, retrying..." + "waiting_wifi" -> "Waiting for Wi-Fi..." + "finalizing" -> "Finalizing..." + else -> buildString { + append(currentArtistName) + if (queueCount > 1) { + if (isNotEmpty()) append(" • ") + append("$queueCount in queue") + } + } + } + try { + DownloadQueueWidgetProvider.push( + this, + running = true, + title = currentTrackName.ifEmpty { "Downloading..." }, + subtitle = subtitle, + percent = percent, + ) + } catch (e: Exception) { + android.util.Log.w("DownloadService", "Widget update failed: ${e.message}") + } } private fun buildNotification(progress: Long, total: Long): Notification { diff --git a/android/app/src/main/res/drawable/widget_download_bg.xml b/android/app/src/main/res/drawable/widget_download_bg.xml new file mode 100644 index 00000000..ab808957 --- /dev/null +++ b/android/app/src/main/res/drawable/widget_download_bg.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/android/app/src/main/res/layout/widget_download_queue.xml b/android/app/src/main/res/layout/widget_download_queue.xml new file mode 100644 index 00000000..0b5e95de --- /dev/null +++ b/android/app/src/main/res/layout/widget_download_queue.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values-night-v31/colors.xml b/android/app/src/main/res/values-night-v31/colors.xml new file mode 100644 index 00000000..4524607e --- /dev/null +++ b/android/app/src/main/res/values-night-v31/colors.xml @@ -0,0 +1,7 @@ + + + @android:color/system_neutral1_900 + @android:color/system_neutral1_50 + @android:color/system_neutral2_200 + @android:color/system_accent1_200 + diff --git a/android/app/src/main/res/values-night/colors.xml b/android/app/src/main/res/values-night/colors.xml new file mode 100644 index 00000000..cd97213c --- /dev/null +++ b/android/app/src/main/res/values-night/colors.xml @@ -0,0 +1,6 @@ + + + #1C1B1F + #E6E1E5 + #CAC4D0 + diff --git a/android/app/src/main/res/values-v31/colors.xml b/android/app/src/main/res/values-v31/colors.xml new file mode 100644 index 00000000..769fafd2 --- /dev/null +++ b/android/app/src/main/res/values-v31/colors.xml @@ -0,0 +1,7 @@ + + + @android:color/system_neutral1_10 + @android:color/system_neutral1_900 + @android:color/system_neutral2_700 + @android:color/system_accent1_600 + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index beab31f7..74e1334d 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -1,4 +1,8 @@ #000000 + #F3F3F3 + #1C1B1F + #49454F + #1DB954 \ No newline at end of file diff --git a/android/app/src/main/res/xml/widget_download_queue_info.xml b/android/app/src/main/res/xml/widget_download_queue_info.xml new file mode 100644 index 00000000..b4310db8 --- /dev/null +++ b/android/app/src/main/res/xml/widget_download_queue_info.xml @@ -0,0 +1,8 @@ + +