## Description
Prefer using thumb image types for movies when adding to Watch Next
android OS channel. The primary/poster image will be used if there is no
thumb.
### Related issues
Fixes#1425Fixes#1403
### Testing
Emulator, verified a movie was showing its primary image, then ran this
PR
## Screenshots
N/A
## AI or LLM usage
None
## Description
- Fix crash on license info page for release builds (#1437)
- Fix configuring which ratings to show by default (#1407)
- When re-ordering nav drawer items, ensure the one that was just moved
is always visible (#886 )
- Fix app losing focus when switching between list layout types (#1428)
- If the version doesn't have any additional commits, don't show the git
hash info (ie `v0.6.4-0-gabc1234` shows as `v0.6.4`)
- Adds tests for Version comparisons & toString
### Related issues
See above
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Refactors all usages of `LiveData` into flows in keeping with best
practices. This also includes refactoring several `ViewModel`s to
combine multiple `LiveData` into a new single `StateFlow`.
There are no user facing changes
### Related issues
None
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Adds an option to display libraries in a list layout
The list can be regular showing 6-7 items or compact showing ~11 items.
Can also toggle showing the details on the left side. Movies, tv shows,
& albums have type-specific layouts and other types like videos, music
videos, etc use a generic one similar to movies.
Another change is that showing the backdrop is now a separate toggle
from showing details for both grid & list layouts.
Sorting, filtering, & jumping to a letter all work as expected!
### Related issues
Closes#1101
### Testing
Emulator mostly
## Screenshots
<details><summary>Click for screenshots</summary>
<p>
### TV shows list
<img width="1280" height="720" alt="series_list Large"
src="https://github.com/user-attachments/assets/f8f9b801-e537-4cdf-b992-f2f1259457fa"
/>
### TV shows compact list
<img width="1280" height="720" alt="series_list_compact Large"
src="https://github.com/user-attachments/assets/747e5929-90d7-4d59-a179-bc3210ac01b9"
/>
### Movie list
<img width="1280" height="720" alt="movie_list Large"
src="https://github.com/user-attachments/assets/ee3e1c6c-fb25-438a-a11e-522d30fbaabf"
/>
### Album list
<img width="1280" height="720" alt="music_list Large"
src="https://github.com/user-attachments/assets/9b1f59ec-c237-4ab2-9b51-6cb519f5327c"
/>
</p>
</details>
## AI or LLM usage
None
## Description
Shows a loading indicator and slightly dim the screen when playback is
buffering.
Showing the indicator is delayed in case the buffering doesn't take very
long.
Dev note: the changes to `MpvPlayer` need to be ported to
wholphin-extensions as well.
### Related issues
Closes#1411
### Testing
Emulator
## Screenshots
[buffering.webm](https://github.com/user-attachments/assets/dd848696-d6de-4f68-94e4-901bb5db1185)
## AI or LLM usage
None
## Description
Adds a setting to configure the app's language/locale. It is configured
per user. This settings has no impact on audio or subtitles language
choices.
Only languages Wholphin has translations for can be used. If you would
like to contribute new translations, check out
https://translate.codeberg.org/projects/wholphin/!
Dev notes: This doesn't exactly follow Android's recommendations because
the [guidelines are for
per-app](https://developer.android.com/guide/topics/resources/app-languages)
and not users within the app.
### Related issues
Closes#513Closes#669
### Testing
- Emulator API 34
- Nvidia shield API 30
- Fire TV OS 7 API 28
## Screenshots
<img width="1280" height="720" alt="language Large"
src="https://github.com/user-attachments/assets/bf1c0962-8a36-4012-aed9-eab564fc1114"
/>
## AI or LLM usage
None
## Description
There was an issue if when opening a page with theme music and quickly
changing pages, usually playback, the theme music might play on the new
page. This is because the call to stop the theme music could potentially
happen _before_ the song was loaded or had started playing.
This PR fixes this race condition by tracking the job that's fetching
the theme song and by adding a mutex to ensure the play function
completes before the stop function can begin.
### Related issues
Fixes#938
### Testing
Emulator w/ fake delay to increase the odds of the issue occurring
## Screenshots
N/A
## AI or LLM usage
None
## Description
Don't show future content (episodes, etc) on recently released rows in
recommended tabs or home page rows.
### Related issues
Closes#262
Replaces #1262
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
The original PR #1262 author used claude. Some of that code that was
retained in this PR was reviewed & tested.
---------
Co-authored-by: ADT95 <turner7@outlook.com>
## Description
This should fix the issue where suggestions would sometimes get stuck
loading. My best guess is that they were getting stuck because the app
thought it was still loading, even though the background job was just
waiting.
This should fix that by making each library kick off its own suggestions
job when needed.
### Related issues
Fixes#1065
### Testing
Emulator and nvidia shield
## Screenshots
N/A no ui changes
## AI or LLM usage
Used codex to help diagnosis the bug. Also added unit tests and more
debug logging for the suggestions system using ai. Wrote the fix myself.
---------
Co-authored-by: Damontecres <damontecres@gmail.com>
## Description
Fixes showing the discover search result row
Also adds a Search tab to the discover page. You can already search
discover results from the regular search page, so the new tab is just
for convenience.
### Related issues
Related to #709
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
- Fix always showing the user list on app cold start even with auto sign
in enabled
- Ignore unknown JSON keys when restoring view options or filters from
the database making them more backward compatible for devs switching
branches
- Don't show a view more card on collection detail page rows, it's not
necessary
### Related issues
First bug was introduced by #1367
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Adds the standard extras row to the album detail page if there are any
extras
I also tried to get Jellyfin to recognize artist extras, but it did not
work, so this just adds extras for albums
### Related issues
Closes#1409
### Testing
Emulator
## Screenshots
N/A, same extras row
## AI or LLM usage
None
## Description
Adds a "Show voice search button" toggle to the search page's view
options dialog, alongside the existing "Combined search results" toggle.
When disabled, the voice search button is hidden from the search row,
taking it out of the D-pad focus path.
The new field `show_voice_search_button` is added to `SearchPreferences`
(default `true`). The serializer applies the default for new installs,
and a new entry in `AppUpgradeHandler` sets it to `true` for users
upgrading from earlier versions so existing behaviour is preserved.
### Related issues
Discussion: https://github.com/damontecres/Wholphin/discussions/1419
### Testing
Tested on an Android TV (1080p) AVD running API 34:
- Toggle on (default): voice search button visible at the top of the
search row.
- Toggle off: button disappears; only the search text field remains.
- Toggle back on: button reappears.
- Upgrade handler verified by spoofing `version.current.name` to an
older value in SharedPreferences and force-restarting the app; after
`needUpgrade()` fired, the toggle was on as expected.
The upgrade-handler entry currently uses `0.6.4-8-g0` (based on current
`main` HEAD); happy to bump this if you'd prefer a different target
version on merge.
## Screenshots
<img width="1920" height="1080" alt="pr1-01-home"
src="https://github.com/user-attachments/assets/0d5cdad0-5547-44f3-b4a5-5d15f71dddc0"
/>
<img width="1920" height="1080" alt="pr1-02-toggled-off"
src="https://github.com/user-attachments/assets/1e574229-0838-487d-b943-83d394a8193d"
/>
## AI or LLM usage
I used Claude to scaffold the proto/serializer/upgrade-handler/dialog
changes, mirroring the existing `combined_search_results` pattern. I
reviewed each diff before committing and tested the toggle manually on
the emulator, including the upgrade-handler simulation.
---------
Co-authored-by: Damontecres <damontecres@gmail.com>
Fixes#1396.
The else branch of `when (nextState)` in PlaybackController added a 32dp
Spacer that left empty space below the controls when there were no
chapters or queue.
Possible follow-up: Pentaphon's idea of a "similar items" row in that
empty slot. Happy to put up a separate PR if useful.
## Testing
Verified on an Android TV (1080p) AVD running API 34 by playing a movie
with no chapters and no next-up item. With the fix, the bottom of the
control overlay sits the expected 8dp from the screen edge (the existing
parent padding). Also rebuilt without the fix and compared back-to-back
to confirm the Spacer was the cause.
The CHAPTERS and QUEUE branches were not modified.
## Screenshot
<img width="1920" height="1080" alt="case1-controls"
src="https://github.com/user-attachments/assets/18f50a87-a373-4f48-a9d4-f3c2a5cb2c00"
/>
## AI or LLM usage
I used Claude to help identify the file containing the bug and to
suggest the fix. I reviewed the diff before committing.
## Description
Adds a setting, Settings->Advanced->"Customize which ratings to
display", which allows for toggling parental, community, or critic
ratings to be displayed in the quick details.
This doesn't apply to discover yet.
### Related issues
Related to #1020
### Testing
Emulator
## Screenshots
### Just community rating
<img width="1280" height="720" alt="ratings Large"
src="https://github.com/user-attachments/assets/d6f9ad8a-6cc5-4680-9d2f-66d16a44b41e"
/>
## AI or LLM usage
None
## Description
This PR adds a new method of protecting a user profile when switching to
it: server login. When enabled, switching to the user requires
authenticating with the server again via Quick Connect or username &
password. This is basically the same as the official client.
### Related issues
Closes#321
Related to #1330 - might cause merge conflicts
Related to #1287 - definitely causes merge conflicts
### Testing
Emulator with various uses cases including auto sign-in, switching
between server login & PIN protection, and removing the protection
## Screenshots
N/A, the login looks identical as adding a new user
## AI or LLM usage
None
## Description
This PR has some UI/UX updates for live tv epg/guide.
- Show program images, if provided by the EPG source
- Show channel name under logo
- Show & set favorite channels
- Adjusts the header to match the rest of the app (font, padding, etc)
Additionally, navigation around the guide has been rewritten. It is more
efficient and feels a bit more smooth to scroll around.
### Related issues
Closes#529
### Testing
Emulator mostly
## Screenshots
<img width="1280" height="720" alt="epg_new Large"
src="https://github.com/user-attachments/assets/c53c01be-9209-4c59-82cb-47f268811d3e"
/>
## AI or LLM usage
None
## Description
Adds an option under Settings->Customize home page->Settings, "Continue
watching/Next up click behavior":
- When disabled (the default), clicking goes to the item's details page
- When enabled, clicking starts playback for the item from its resume
position
This only applies to the continue watching, next up, or combined rows.
All other rows go to the details page no matter what.
### Related issues
Closes#1007
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes a small UI glitch when the subtitle label is too long, it would
slightly increase the high of the labels. This is especially noticeable
on series details if some episodes have the long label and some don't
because the episode row will bounce up and down a few pixels.
Also moves the labels closer together and changes "Disabled" to "None"
when subtitles are turned off.
### Related issues
None
### Testing
Emulator & compose previews
## Screenshots
### Before
The subtitle label is slightly taller than the others
<img width="528" height="36" alt="image"
src="https://github.com/user-attachments/assets/32d322bc-11cc-4238-840c-03ae41b069d3"
/>
### After
The ellipse doesn't look great, but there's limited space and looks
better than being cut off.
<img width="510" height="37" alt="image"
src="https://github.com/user-attachments/assets/40af707c-3121-40c0-a978-60781d9704d6"
/>
## AI or LLM usage
None
## Description
Adds a card at the end of the rows on the home page and recommended tabs
to "View More" which goes to a grid of the items in the row.
The grid will endlessly scroll all of the available items except for a
few cases where the first 1000 are shown because the server does not
(yet) support pagination: genres, studios, people (added in v12), and
latest grouped tv shows.
Dev notes: This PR also rewrites the `RecommendedViewModel` and
consolidates the previous multiple view models into one.
### Related issues
Closes#1371Closes#1035
Similar to #1198
### Testing
Emulator
## Screenshots
N/A, see #1198
## AI or LLM usage
None
## Description
Improves how search results are displayed:
- Reorders search categories to Movies → TV Shows → Episodes →
Collections, surfacing the most commonly searched content types at the
top.
- Adds a new "Combined search results" preference in Advanced settings →
Search. When enabled, shows all results in a single list instead of
separate categories.
- When Seerr is active, adds Library/Discover tabs to switch between
local library results and Seerr discovery results.
- Hides empty result categories instead of showing "No results"
placeholders.
### Screenshots
<img width="1935" height="1100" alt="Screenshot_20260116_113656"
src="https://github.com/user-attachments/assets/1e29aa3a-3ba2-4f86-ab61-fed683490474"
/>
<img width="1934" height="1095" alt="image"
src="https://github.com/user-attachments/assets/8b93fa38-d4c9-4e72-a997-caa82b4949f0"
/>
<img width="1921" height="1094" alt="image"
src="https://github.com/user-attachments/assets/82aed1a5-810c-413f-a266-6d78490a1534"
/>
### AI/LLM usage
Code auditing and PR description drafting with Claude Code. Also used
Claude Code for the regex.
Fixed a bug with libass integration where the background thread
responsible for drawing the ASS subtitles (AssRenderThread) has been
shut down, but ExoPlayer is still actively running and trying to push
video time updates to it. Added fallback for software rendering on older
android versions that can have broken OpenGl implementation.This should
address much of issue #1049.
## Description
Essentially, debug logs showed repeated:
3145 3920 W MessageQueue: Handler (android.os.Handler) {4ba3c72} sending
message to a Handler on a dead thread
3145 3920 W MessageQueue: java.lang.IllegalStateException: Handler
(android.os.Handler) {4ba3c72} sending message to a Handler on a dead
thread
Essentially this was a lifecycle bug where the libass-android thread was
created, but was detaching from the window, shutting down when it does
so. It was still registered to ExoPlayer, but since there was no thread
to send to, it just repeatedly kept failing, never spinning back up to
display any subtitles. It seems just about any ui change can cause this
detachment, but in this case it seems it was right from the moment the
loading spinner shows up (making libass-android fail before video starts
playing).
Fixed by ensuring TextureView's visibility wasn't changed to invisible,
which ends up destroying the canvas that libass-android attaches itself
to. Hid the canvas using graphicsLayer (so the user can't see it, but
it's still alive and active). Also changed resizing logic to prevent
Android from seeing a 0x0 TextureView as "destroyed".
Since I discovered in testing how terribly my TV's OpenGl was handling
this, I added an additional fallback for Android versions < 9. Older
TV's can fallback to software rendering when using libass-android.
### Related issues
#### Issue #1049 :
**Fixes:**
- the issue where libass-android (when enabled) fails to load any
subtitles in ExoPlayer DirectPlay.
**Not Fixed from issue #1049 :**
- Issues around accented characters.
- Any issues surrounding MPV (I have no way of testing, MPV never worked
on any player for me)
- Fallback mode (libass-android disabled) where subtitles aren't
rendering properly
**Added:**
- While testing, discovered older Android versions have trouble with
reliable OpenGl rendering. Thus I added a fallback for older Android
versions to use libass-android in software rendering mode
(AssRenderType.OVERLAY_CANVAS)
### Testing
- Tested and confirmed flawlessly to work on Android 9 TCL Smart TV
(AssRenderType.OVERLAY_CANVAS)
- Tested on Android 14 Chromecast (AssRenderType.OVERLAY_OPEN_GL).
Slightly less perfect (font not always a match, less fancy shadows) but
most ASS/SSA effects work well. May be worth testing other AssRenderType
options to compare features and performance on other machines.
## AI or LLM usage
Google Gemini Pro in tracing down the cause and fine-tuning the fixes.
---------
Co-authored-by: Damontecres <damontecres@gmail.com>
## Description
1. Fixes when moving from nav drawer to home page content, focus would
sometimes move up a row
2. Fixes when moving up/down between rows, focus would sometimes move to
the later card (usually the last visible)
The second above is fixed by downgrading `tv-material` to
`1.0.1-alpha01`. Switching to
[`1.0.1-beta01`](https://developer.android.com/jetpack/androidx/releases/tv#tv-material-1.1.0-beta01)
or newer causes the bug. Not clear if its a bug in the library or
Wholphin though.
### Related issues
Fixes#1359
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Directly use "Wholphin" when searching for older APKs to clean up.
On debug builds, the `app_name` string is "Wholphin (Debug)" but the APK
file names is always "Wholphin.apk", so I think the debug build won't
clean them up.
### Related issues
Fixes#1368
### Testing
Testing downloading a few times without this change, applied the change,
and clean up worked
## Screenshots
N/A
## AI or LLM usage
None
## Description
This enhances the PIN entry system by allowing users to input digits
using the numbers 0-9. This is useful for those using a keyboard or
universal remote with a number pad.
### Testing
Tested on Nvidia Shield Pro and Onn 4k Pro
## Screenshots
<img width="3840" height="2160" alt="Screenshot_20260429_083041"
src="https://github.com/user-attachments/assets/9e603bda-f1d3-4268-a04c-b077297fdfac"
/>
---------
Co-authored-by: Damontecres <damontecres@gmail.com>
## Description
Show the public users (ie "Hide this user from login screens" is
unchecked) if the server has any. Previously, all users had to be
explicitly added by username or quick connect.
This PR also refactors the server & user pages to use modern state flows
and deletes some unused code.
### Related issues
Closes#600
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Instead of adding/removing the `SubtitleView` from composition
sometimes, instead toggle its visibility. This is technically slightly
more efficient. There's also a couple other minor tweaks that make the
subtitles style a little more efficient.
This should also help prevent crash caused by possible a race condition
in libass-android
(https://github.com/peerless2012/libass-android/issues/75).
### Related issues
I think this fixes#1322
### Testing
Emulator mostly
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes the delete button not showing on the movie detail page. Also fixes
some edge cases where button may not appear when toggling on the media
management setting.
Adds the delete button to album & artist pages. Previously, it was only
in the context menu.
### Related issues
Fixes#1343
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes an issue when changing subtitles during playback if you had
previously explicitly chosen subtitles for that item but not chosen an
audio track.
### Related issues
I don't think there is a specific issue for this
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Preload ~6 rows worth of images on library grid pages. So depending on
device CPU & memory, most cards do not show a placeholder image when
scrolling unless you press and hold up/down to scroll as fast as
possible.
There's a couple other minor optimizations on the grid code as well, but
nothing huge.
### Dev notes
This PR makes the `cacheWindow` for pre-rendering cards applicable to
their images. Previously, images would not be fetched until the card is
laid out within the window. This was to get the width/height to pass to
the server request. This PR instead calculates the card widths when the
grid itself is laid out and then passes this width into the cards'
composables.
### Related issues
Related to #1246
### Testing
Tested with emulator, shield, fire stick 4k max
## Screenshots
N/A
## AI or LLM usage
None
## Description
Adds a context menu option to choose the player backend or transcoding
to start playback. This allows for temporarily swapping to another
backend without having to updating the settings.
### Related issues
A couple comments have suggested this, but I don't think there's a
specific feature request
### Testing
Emulator
## Screenshots
<img width="1280" height="720" alt="play_with Large"
src="https://github.com/user-attachments/assets/2a75756f-5d7f-45f6-8ea6-a406f3d7f3e1"
/>
## AI or LLM usage
None
## Description
This PR refactors most of the context menu dialog code moving more of
the display into a Composable. This then allows for embedding the
confirm delete or choose version sub-dialogs. This will allow for easier
future expansion of the context menu.
Now instead of the page using a combination of `DiaglogPopup` &
`buildMoreFor` functions, pages create a `ContextMenu` object and pass
it to a composable.
There's no significant user facing changes.
### Related issues
None
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Shows the overlay (watched, progress bar) for extras appearing as single
items. Grouped extras individually show the overlay when clicking into.
If all of the grouped are played, the group is show with the watched
indicator.
Also very slightly optimizations the UI by offloading the
title/subtitle/imageUrl to object creation time instead of when they're
shown on screen.
### Related issues
Closes#1311
### Testing
Shield testing with different extras
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes an bug caused when the home page has an empty row before the last
row and there are non-empty rows later, an `IndexOutOfBoundsException`
would be thrown.
Also removes the loading indicator if an unknown error occurs during a
refresh.
### Related issues
Fixes#1314
### Testing
Emulator & shield
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes the play & shuffle buttons on music library tabs.
They previously attempted to play the audio via the video playback
method. This PR adds the ability to override the buttons and does so for
music libraries.
### Related issues
Fixes#1304
### Testing
Emulator, compared results against the web UI
## Screenshots
N/A
## AI or LLM usage
None
## Description
Moves the five skip segment settings to their own page. So there's now a
single "Skip behavior" that you click to bring up the settings for the
five. I doubt many people change these frequently, so moving them to a
new page de-clutters the settings page.
### Related issues
N/A
### Testing
Emulator
## Screenshots
### Advanced settings
<img width="1280" height="720" alt="single_setting Large"
src="https://github.com/user-attachments/assets/673555d5-109c-4c43-9073-f51572bb949d"
/>
### Skip segment specific settings
<img width="1280" height="720" alt="skip_settings Large"
src="https://github.com/user-attachments/assets/dae9d0bd-7340-4731-b561-b7b4e74d9d4f"
/>
## AI or LLM usage
None
## Description
Fixes some issues when using an external player:
- Send playback started before launching so the last played date is
updated
- Only use VLC's position if >0 since it returns 0 when playback
completes
### Related issues
Follow up to #1256
### Testing
Emulator & nvidia shield
## Screenshots
N/A
## AI or LLM usage
None
## Description
Previously the home page always tried to load the "watching rows" (Next
up, Continue watching, or combined) first. This meant that even if the
user's customized home page did not put these rows at the top, they
would always be listed first anyway.
This PR fixes this so rows on the home page are always listed in the
right order.
### Related issues
Fixes#1275
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Adds a row for season level extras on the series overview page below the
people rows. The extras will update when switching between season tabs.
Like elsewhere in the app, an single extra of a type is show inline and
multiple extras of the same type open a grid when clicked.
### Related issues
Closes#504
### Testing
Emulator
## Screenshots
<img width="1280" height="720" alt="season_extras Large"
src="https://github.com/user-attachments/assets/bc62bef4-66c8-4412-9eca-ec0105d0d0fa"
/>
## AI or LLM usage
None
## Description
If the Wholphin OS screensaver starts before Wholphin (the app) is
opened, a default image loader is used. Then when Wholphin is opened, it
will crash when trying to set the app's image loader.
This PR adds configuring the image loader to the screensaver as well. It
is safe to do this multiple times. It's only an error to try to replace
the default image loader.
### Related issues
None
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes a crash if there is a network error when starting the screensaver.
Instead, a black screen with an error message shows. The error message
fades in/out to different parts of the screen. This applies to both
in-app and OS screensavers.
### Related issues
Fixes#1247
### Testing
Emulator w/ simulated errors
## Screenshots
N/A
## AI or LLM usage
None
## Description
Ports two changes in the official jellyfin android TV app here:
- https://github.com/jellyfin/jellyfin-androidtv/pull/5240
- https://github.com/jellyfin/jellyfin-androidtv/pull/5186
The code changes are copied under GPL-2.0 from the above pull requests.
### Related issues
Closes#1260
### Testing
Emulator mostly
## Screenshots
N/A
## AI or LLM usage
None
---------
Co-authored-by: Niels van Velzen <git@ndat.nl>
Co-authored-by: clams4shoes <prestidgeandrew@gmail.com>
## Description
Adds a new playback "backend" to play media in another app such as VLC.
By default, Wholphin will use the system default app. Typically if you
haven't chosen one, a dialog will show to pick which app. You can also
set a specific external app to use in Wholphin independent of the system
default.
Currently, this only support single item playback, ie playing next up
episodes is not supported yet.
Also since there is no standardized way to send resume position,
external subtitle info, etc, Wholphin makes a best effort. VLC,
mpv-android, & MX-Player are specifically tested/supported.
### Related issues
Closes#85
### Testing
Emulator & nvidia shield w/ VLC, mpv-android, & MX-player
## Screenshots
<img width="543" height="407" alt="image"
src="https://github.com/user-attachments/assets/ab37d41e-2909-40ed-b537-191ebb54d979"
/>
## AI or LLM usage
None
## Description
Issue 943 where trickplay images were misaligned with seek preview
mages. I made a post in issues but figured i'd go ahead and make the
pull request.
per gemini:
In SeekPreviewImage.kt, the code calculates which tile in the grid to
display based on the current timestamp:
val x = (tileIndex % trickPlayInfo.tileWidth) // x position within tile
grid
val y = (tileIndex / trickPlayInfo.tileHeight) // y position <-- BUG IS
HERE
To find the correct row (y) in a grid, you are supposed to divide the
current index by the width of the row (the number of columns), not the
height.
Why this breaks: Let's assume a standard trickplay grid that is 10
images wide (tileWidth = 10) and 5 images tall (tileHeight = 5).
If you are looking at the 12th image (tileIndex = 11), it should be on
Row 1 (the second row).
The code calculates y = 11 / 5 = 2. It skips to Row 2!
Because it divides by the smaller height value, the y coordinate
increases much faster than it should. This causes the preview to
visually "jump" down to future rows prematurely, and then snap back as
the x coordinate resets, causing the exact "flashing back and forth" you
saw with the credits and intros.
### Related issue
Fixes#943
### Testing
Tested in Android TV (Android 9) and it does indeed display proper seek
previews using trickplay images.
## AI or LLM usage
Gemini Pro was used to find and fix this bug.