Skip to content

feat(widget): add adaptive card & circular desktop widgets - #1006

Closed
SteveZMTstudios wants to merge 12 commits into
FoedusProgramme:betafrom
SteveZMTstudios:feat/desktop-widgets
Closed

SteveZMTstudios wants to merge 12 commits into
FoedusProgramme:betafrom
SteveZMTstudios:feat/desktop-widgets

Conversation

@SteveZMTstudios

Copy link
Copy Markdown
Contributor

Summary

Card widget — a new responsive home-screen widget family for quick playback control. One provider delivers pill (1×1), circle (2×2 w/ progress ring), card (4×1), medium (4×2) and large (4×4 / wide 5×4) layouts, plus favorite & shuffle actions on wide slots.
Widget favorite action connects through a dedicated playback-service helper so the current item's heart rating and widget state stay in sync across lyric/session updates.
Widget resources use Material You system colors on Android 12+ with stable theme-token fallbacks for pre-12 and night mode; default + zh-rCN strings added for all new settings and the widget picker label.

Screenshots, CI tests and more, see #1003

@SteveZMTstudios

Copy link
Copy Markdown
Contributor Author

@SteveZMTstudios
SteveZMTstudios force-pushed the feat/desktop-widgets branch 2 times, most recently from f5c9b4d to e7d7146 Compare August 22, 2026 18:44
@SteveZMTstudios

Copy link
Copy Markdown
Contributor Author

@nift4 nift4 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note I didn't have time to go through all of the code yet, this is only partial comments

Comment thread app/src/main/java/org/akanework/gramophone/logic/GramophonePlaybackService.kt Outdated
Comment thread app/src/main/java/org/akanework/gramophone/logic/GramophonePlaybackService.kt Outdated
Comment thread app/src/main/java/org/akanework/gramophone/logic/GramophonePlaybackService.kt Outdated
) {
val uri = state.artworkUri ?: return
CoroutineScope(Dispatchers.IO).launch {
val request = ImageRequest.Builder(context)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if there's a more optimal way to do it, did you test letting image view load the cover itself? (I guess a placeholder can be achieved by stacking two imageview in a framelayout, but IDK if that is a great idea)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My initial attempt involved handling album art loading directly with RemoteViews/ImageViews, but I encountered noticeable UI flickering issues: Whenever controls were updated (e.g., scrolling lyrics from a lyrics control, progress updates, or play/pause switching), reapplying RemoteViews caused the launcher's ImageView to reload/redraw the URI from scratch, resulting in very noticeable and distracting flickering of the album art.

Stacking two ImageViews within a FrameLayout was completely unnecessary, not only adding unnecessary layout overhead but also failing to prevent the top album art view from flickering during subsequent RemoteViews updates, as they refreshed together.

By loading the album art once in the background using Coil and caching it in memory (cachedArtworkBitmap), subsequent control updates (progress bar jumps, playback status changes) could immediately reuse the existing Bitmap, completely eliminating flickering and making updates visually smoother.

Comment thread app/src/main/java/org/akanework/gramophone/logic/GramophonePlaybackService.kt Outdated
@nift4

nift4 commented Aug 31, 2026

Copy link
Copy Markdown
Member

There's still unused methods fyi, and a conflict because your other PR was merged

@nift4

nift4 commented Sep 2, 2026

Copy link
Copy Markdown
Member

I'm confused, do you perhaps have different code locally? because in this branch there's still unused functions like createErrorNotificationChannel or initCustomCommands

@SteveZMTstudios

SteveZMTstudios commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor Author

I apologize, I (and my computer) have been handling too many things simultaneously lately, and I made a mistake while sorting the code. I have fixed it and will carefully review the subsequent steps.

do you perhaps have different code locally?

And yes, I always bring up the code collection in the feature/stevezmt branch change, which is #1003, to test their coupling.

@nift4

nift4 commented Sep 9, 2026

Copy link
Copy Markdown
Member

Sorry for the delay, currently occupied with something else, will review soon.

@nift4

nift4 commented Sep 15, 2026

Copy link
Copy Markdown
Member

Thanks for your patience, and sorry for the delay. I tried the widgets on my phone now.

My thoughts from testing:

Overall, I really like the concept of the different widgets. But, I think each type of widget at least needs one provider (so one does pill/circle and another does the card ones). Otherwise I think users would simply not notice that there is different types.

Also, I was wondering about the favorite and shuffle button. I think I would prefer there to either be both shuffle and repeat, or none of them. So maybe, in card layout, there could be repeat in place of current favorite, and favorite is moved to be at end of the name text view instead?

Also, I noticed a minor issue where the favorite button is a different color (more grey) than the other buttons.

Lastly, after closing the app, the widget became empty - it should preferably show the last played song instead, that will be played after pressing the play button (the latter part with restarting playback is already working, widget just doesn't show it).

Comment thread app/src/main/java/org/akanework/gramophone/ui/CardWidgetProvider.kt Outdated
Comment thread app/src/main/java/org/akanework/gramophone/ui/CardWidgetProvider.kt Outdated
@SteveZMTstudios

Copy link
Copy Markdown
Contributor Author

I will make time to handle this as soon as possible. Thank you for sharing your experience and feedback.

Note: corrected file copyright header to SteveZMTstudios (author mistakenly copied Akane Foundation header from template during creation, now corrected).
…to ui/widget

Note: corrected file copyright header to SteveZMTstudios (author mistakenly copied Akane Foundation header from template during creation, now corrected).
Note: corrected file copyright header to SteveZMTstudios (author mistakenly copied Akane Foundation header from template during creation, now corrected).
…void reflection crash

- Remove unsupported reflection setInt(setGravity) on TextViews in large layout preventing VIEW_MODE_ERROR crash
- Update responsive breakpoint mapping:
  * Circle: (40, 40) -> pillSingle, (100, 40) -> pill, (100, 95) -> circle (2x1 selects pill, 2x2 selects circle)
  * Card: (120, 50) -> card, (180, 75) -> medium, (180, 130) -> large, (250, 130) -> largeWide (3x1 selects medium, 3x2 selects large)
- Expose repeat and shuffle buttons on medium layout (selected by default 3x1 slot)
- Constrain card_widget cover maxWidth and button widths with minWidth on text column to prevent title column collapse
- Isolate CardWidgetStore SharedPreferences into GramophoneCardWidget to avoid polluting LastPlayedManager
- Move savePlaybackSnapshot before nulling instanceForWidgetAndLyricsOnly in GramophonePlaybackService.onDestroy
- Extract BaseWidgetProvider to decouple shared provider lifecycle, actions, and artwork caching
…r clipping

- Support 6 widget themes in Appearance settings (wallpaper/album art palette with follow-system, dark, and light modes)
- Resolve dynamic colors via CardWidgetColorResolver with LRU caching
- Add preview images for card and circle widgets in widget picker
- Fix double rounded corner issue on large 4x4 covers by relying on view clipToOutline and removing CardWidgetBitmapUtils
- Optimize responsive layout variants and prevent pill collapse
- Add DesktopWidgetTest and WidgetLayoutProbeTest suites
@SteveZMTstudios

Copy link
Copy Markdown
Contributor Author
Screenshot_2026-09-19-18-34-14-32_b783bf344239542886fee7b48fa4b892

@nift4

nift4 commented Sep 21, 2026

Copy link
Copy Markdown
Member

Your screenshot looks nice, but can you remove the favorite button from the 2x1 card (only)? It makes the title unreadable.

@SteveZMTstudios

SteveZMTstudios commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Your screenshot looks nice, but can you remove the favorite button from the 2x1 card (only)? It makes the title unreadable.

thats 3x1 actually, my screen is 5x6, and 2x1 with cards makes ugly and its feature almost dumplicate with pill widgets.

btw in the previous round of changes, I revisited the color extraction scheme; it now supports extracting colors from the cover art rather than the system theme color, and allows for independent theme configuration for the widget.

It's now looks like.

Screenshot_2026-09-21-22-07-50-45_b783bf344239542886fee7b48fa4b892

- Hidden the favorite button in compact layouts to ensure the title displays correctly.
SteveZMTstudios added a commit to SteveZMTstudios/Gramophone that referenced this pull request Sep 22, 2026
…ktop-widgets

feat(widget): add adaptive card & circular desktop widgets
@nift4

nift4 commented Oct 8, 2026

Copy link
Copy Markdown
Member

I'm working on merging your changes into the compose-rewrite branch. We are rewriting the app in compose, this PR is still applicable so I'm merging it there. I will fix the remaining stuff if I find any myself. GitHub does not support merging PR to different branch without retargeting and I do not have permission to retarget, so I will close this PR. Rest assured the code will be merged manually though.

@nift4 nift4 closed this Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants