## Description
Adds better error handling when loading home page rows. For example,
this fixes loading errors if a playlist row is configured, but the
playlist is deleted.
Also fixes an issue from #1116 where changing users doesn't go the home
page.
### Related issues
Related to #1124
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
This fixes some issues restoring the app state after it is killed by the
system, such as to free up memory while the screensaver is showing.
### Dev notes
Reproduce:
1. Start playing media from beginning
2. Pause at 10 minute mark
3. Wait for screensaver to start
4. Press a button
5. Media starts from beginning
Note: It may take a few iterations of 2-4 before the OS destroys the
app.
If the app is killed during playback, ideally Wholphin restores state to
_previous_ page, not playback since restoring playback is complex.
Before this PR, the back stack was maintained by Compose's
`rememberSerializable` and would be restored _after_ the
`PlaybackLifecycleObserver` cleans up the playback destination.
This meant that the app would be restored, from scratch, to the playback
page. The `PlaybackViewModel` would be initialized from scratch as it
was originally called, ie play from beginning.
The fix is to save and restore the back stack outside of Compose.
### Related issues
Fixes#767
### Testing
Emulator & nvidia shield
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes debug install updates from trying to install the release APK and
use debug ones instead.
### Related issues
Fixes#1098
### Testing
Unit tests
## Screenshots
N/A
## AI or LLM usage
None
## Description
This PR makes changes to how images are fetched for discover/Seerr
items.
If the discovered item is available on the Jellyfin server, the images
will be fetched from the Jellyfin server.
Then if the Seerr server has image caching enabled, the images will be
fetched from the Seerr server. Otherwise, images are fetched from TMDB .
TMDB was the previous behavior for all images.
### Dev notes
This PR also updates the Seerr server URLs stored in the database, so
it's not backwards compatible.
### Related issues
Fixes#1079
### Testing
Emulator against Jellyseer 2.7.3 & Seerr 3.0.1
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes a race condition saving preferences. It would be triggered if you
have "Remember selected tabs" enabled and either: 1) changed settings
while on a library grid page or 2) changed settings on a page navigated
_from_ a library grid page and then returned to the grid
### Related issues
I think this will fix#1075
### Testing
Emulator following the steps above
## Screenshots
N/A
## AI or LLM usage
None
## Description
A few fixes
- Better crossfade for photo slideshow
- Fix "Go to" in context menu for photos
- Fix certain home video/photo libraries not working for photos
- Fix removing seerr server in some cases
### Related issues
Closes#835Fixes#1069
Addresses
https://github.com/damontecres/Wholphin/issues/634#issuecomment-4018580518
### Testing
Emulator mostly
## Screenshots
N/A
## AI or LLM usage
None
## Description
Adds a dialog to select individual seasons for a TV show when requesting
it via Discover/Jellyseerr
If a request is already pending, it can be updated. If there's more than
7 seasons, a second submit button is added at the bottom of the dialog
for easier access.
Also, adds a button from Jellyfin series details to its Discover
equivalent and added a request button for partially available series to
request more seasons.
### Related issues
Closes#961
### Testing
Emulator & Jellyseerr 2.7.3
## Screenshots

## AI or LLM usage
None
## Description
Fix a screensaver crash after the last item
Also adds some extra error checking
### Related issues
Fixes#1053
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
Unfortunately, there seem to be issues with switching to
`libass-android`, so reverting those changes so I can cut a release and
troubleshoot later.
Reverts damontecres/Wholphin#569
## Description
Add better ASS/SSA support to ExoPlayer by using
[`libass-android`](https://github.com/peerless2012/libass-android).
This is enabled with the "Use libass for ASS subtitles" advanced
settings for ExoPlayer. It is enabled by default.
### Related issues
Related to #22
## Description
This PR improves the logic used to choose a display mode when refresh
rate and resolution switching are enabled.
As before, matching the refresh rate is prioritized over picking the
resolution. For example, with the display modes of 1080@30 & 720@60 for
a 720@30 video, 1080@30 is used because the frame rate exactly matches.
### Related issues
Fixes#1036
### Testing
Unit tests, added test cases for more situations
## Screenshots
N/A
## AI or LLM usage
None
## Description
A follow up to #1014 to add the delete option in more context menus.
Also improves the "reaction" logic which updates previous pages from
deletions on later pages.
### Related issues
Addresses
https://github.com/damontecres/Wholphin/pull/1014#issuecomment-3987205355
Related to #104
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes some issues with Jellyseerr login. Also makes error message more
clear by showing the URLs that were tested and the error that occurred.
Also fixes an issue where you could not remove a Jellyseerr server if it
was previously configured but can no longer connect.
### Related issues
Fixes#1028
Should fix#1022
Related to #747
### Testing
Emulator, tested adding and removing valid & invalid IPs
## Screenshots
N/A
## AI or LLM usage
None
## Description
This PR is mostly a proof-of-concept for setting up automated UI
testing. The tests use Roboelectric so they can run without an emulator.
There is also a sample instrumented test for running on emulators or
devices for future tests.
It adds two basic automated UI tests for adding a server. These are sort
integration tests because they use the actual implementations for the
view model and services like `ServerRepository` and `JellyfinServerDao`.
Also, moves the bulk of `MainActivity`'s compose code into a function
for future tests.
### Related issues
N/A
### Testing
Local testing
## Screenshots
N/A
## AI or LLM usage
None
## Description
Adds a setting to enable "Media management" which adds a context menu
item to delete media. This is accessible using either the More button or
long clicking.
You can delete episodes, seasons, series and movies/videos.
If order for the option to appear the current user must have server-side
settings for "Allow media deletion from" enabled for the library and the
in-app setting under Settings->Advanced Settings->"Show media management
options".
### Related issues
Closes#104
### Testing
Emulator
## Screenshots
### Context menu

### Confirmation

## AI or LLM usage
None
## Description
- Aims to further optimize performance for the suggestions fetching
### Related issues
Fixes#833
### Testing
Android Emulator
NVIDIA Shield Pro 2019
## Screenshots
N/A
## AI or LLM usage
AI being used to assist with updating/creating unit tests
## Description
- Restores corner text for episode cards
- Always show end time on playback overlay instead of it being
controlled by the "Show Clock" setting
- Better logic to determine person's role in media
### Related issues
Fixes#1010Fixes#1004Fixes#975
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
- Catch network exceptions when querying to populate the nav drawer
- Perform screensaver work on IO thread
- Fix possible crash if screensaver service runs while regular activity
is destroyed
- Fix genre images & backdrop images not loading
This PR also adds an Jellyfin SDK `ApiClient` wrapper to push all
network calls onto the IO thread. And tries to use a more strict
network-on-main policy for debug builds.
### Related issues
Fixes#994Fixes#1001
Should fix#1003
### Testing
Emulator with simulated exception throws
## Screenshots
N/A
## AI or LLM usage
None
## Description
Adds both an optional in-app and Android TV OS (DreamService)
screensaver
Has settings for:
- Starting delay, options from 30s to 1 hour
- Duration to show each image, 30s to 2 minutes
- Show clock (separate from app-wide clock)
- Toggle animated zooming
- Set a max age rating to limit what content is shown
- Included media types: movies, tv shows, and/or photos
By default only Movies & TV Shows are included. But if you have like
family albums on your server, you could enable Photos too.
There's also an button to start the screensaver so you can see what it
looks like.
### Related issues
Closes#230
### Testing
Emulator, Onn 4k pro, nvidia shield using both in-app and OS
screensavers
## Screenshots

## AI or LLM usage
None
## Acknowledgements
Some of the skeleton code for setting up the `DreamService` with the
right lifecycle was copied and modified from the [official app's
implementation](https://github.com/jellyfin/jellyfin-androidtv/blob/master/app/src/main/java/org/jellyfin/androidtv/integration/dream/DreamServiceCompat.kt).
## Description
A few more home page fixes
* Focus issue between settings & preset buttons
* Fix default genre card size for "Wholphin Default" preset
* Cache genre image urls for 2 hours so that they don't change on every
refresh
### Related issues
Related to #399
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes clicking on a genre card added to the home page
### Related issues
Fixes#952
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Show Jellyseerr connection errors in settings. If an error occurred
trying to login, in setting it will show "Server error" and clicking
gives more error info and option to remove the server.
### Related issues
Fixes#907
### Testing
Emulator with simulated errors
## Screenshots
N/A
## AI or LLM usage
None
## Description
Adds some metadata about playing media for consumption in remote control
apps such as Google Home or others.
### Related issues
Partially address #889, doesn't add explicit controls yet, but Google
Home works
### Testing
Nvidia shield + Google Home app
## Screenshots
iOS Google Home app:

## AI or LLM usage
None
## Description
Hopefully this is the last round of bug fixes for customizing the home
page!
Fixes a possible crash when scrolling after adding a row after resetting
to default or loading remote settings that have more rows than the
original settings
Fixes some incorrect titles
### Related issues
Related to #399 & #803
### Testing
Emulator & nvidia shield
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes/improves thumb image handling by falling back to backdrop images
if available. Episodes without a parent thumb/backdrop will fall back to
their primary image.
Also fixes the nav drawer selected item not updating (bug introduced by
#886).
### Related issues
Fixes#642Fixes#914
### Testing
Emulator in various situations with missing thumbs
## Screenshots
N/A
## AI or LLM usage
None
## Description
Fixes several issues with home page customization such as
- Displaying wrong episode-specific display options
- Smaller text on cards without images
- Prefer fill scaling for posters, like the old home page
### Related issues
Related to #803
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
An attempt to fix#769
1. Always fetch the `DisplayManager` when switching refresh rates
2. Use the Activity context instead of Application context
### Related issues
Fixes#769
### Testing
I still haven't reproduced #769 myself, but this change works fine on my
shield + LG C2
## Screenshots
N/A
## AI or LLM usage
None
## Description
Improves home page customization for Live TV & Recordings
- Add row for live tv channels
- Add row for "on now" programs
- Clicking on a TV channel or TV program starts playback
- Better name for "Recently recorded" instead of "Recently added in
Recordings"
Also fixes a back stack issue after adding rows
### Related issues
Follow up from #803
### Testing
Emulator
## Screenshots
<img width="663" height="190" alt="image"
src="https://github.com/user-attachments/assets/49d41953-42ab-4621-92f1-b7936aab7e97"
/>
## AI or LLM usage
None
## Description
Customizing the home page (#803) and nav drawer (#886) were developed
independently, so this PR just cleans up somethings so that those two
changes work together.
This PR restores the default home page when there is no customization to
be the same as before: continue watching/next up row(s) followed by the
order of the nav drawer libraries' recently added rows.
Finally gets rid of `NavDrawerIteRepository` and related functions which
all had weird, hard to follow code.
### Related issues
Related to #803 & #886
### Testing
Emulator testing
## Screenshots
N/A
## AI or LLM usage
None
## Description
Allows for reordering the items in the navigation drawer
This does not change the home page row order since #803 decouples the
nav drawer and home page rows.
The initial order will be the "Library Order" settings on the web under
Profile->Home. Making any changes locally in Wholphin will set the
order. If any new libraries are added or if Seerr integration is
enabled, these will added to the end of the "pinned" list.
### Related issues
Closes#822
Related to #399 & #803
### Testing
Tested on emulator
- Re-ordering
- Granting/Revoking user permission to a new library
## Screenshots
N/A, nav drawer is the same, just sorted differently
## AI or LLM usage
None
## Description
This PR adds the ability to customize the home page in-app
### Features
- Add, remove, & reorder rows
- Persist the configuration locally
- Save the configuration to the server, allowing to pull down on other
devices
- Adjust view options for rows such as card height, image type,
preferring series images, or aspect ratio (similar to libraries)
- Pull down the web client's home rows (no plugins are supported yet!)
- Preview of the home page which is usable & updated as changes are made
### Row options
These are row types that can be added in-app via the UI:
- Continue watching
- Next up
- Combined continue waiting & next up
- Recently added in a library
- Recently released in a library
- Genres in a library
- Suggestions for a library (movie & TV show libraries only)
- Favorite movies, tv shows, episodes, etc
Additionally, there are more row types that don't have a UI to add them
(yet):
- Simple query to get items from a parent ID such as a collection or
playlist
- Complex query to get arbitrary items via the `/Items` API endpoint
### Dev notes
Settings are loaded in order:
1. Locally saved
2. Remote saved
3. Fallback to default similar to Wholphin's original home rows
The remote saved settings are stored via the display preferences API.
I know some server admins would prefer to push a default setup to their
clients. This PR does not have that ability, but it does define a
straightforward API for defining the settings. Something like the
potential server plugin work started in #625 could be slimmed down to
expose a URL to be added in the load order.
I'm also investigating integration with popular home page plugins to
allow for further customization, but will take more time.
### Related issues
Closes#399Closes#361Closes#282
Related to #340
## Description
Fix a bug where movie suggestions would get stuck loading when the
on-disk cache file doesn't exist.
### Related issues
Fixes#876
### Testing
Ran unit tests locally.
## Screenshots
N/A
## AI or LLM usage
Used AI to add testing for this scenario to unit test
---------
Co-authored-by: Ray <154766448+damontecres@users.noreply.github.com>
## Description
A rewrite of the `SuggestionsCache` to simplify it as a read-through
cache. The downside of this is that updated suggestions won't be
reflected in the UI unless the user reloads the page, but I think that's
an okay trade off.
Also adds parallelism limits to fetching suggestions to reduce the
number of simultaneous API calls. And moved the combining logic to use
the `Default` dispatcher to free up an IO one.
Also adds an initial delay to both the suggestions & tv provider
workers, so a cold start of the app isn't starved.
### Related issues
Related to #849
### Testing
Emulator & unit testing
## Screenshots
N/A
## AI or LLM usage
None
## Description
Add a settings to set the maximum amount of time items can appear in
Next Up.
Options range from 7 days to a year, or no limit (current & default
behavior)
### Related issues
Closes#662
### Testing
Tested on the emulator and verified URLs, added unit tests
## Screenshots
N/A, just a new slider bar setting
## AI or LLM usage
None
## Description
Adds a item in the More menu to send information about the media item to
the server (and app logs).
This includes the "media sources" which is info about the files and
stream/tracks in the files. It also includes device info, the playback
preferences, and the device's transcoding profile. All of this info is
useful for debugging playback issues.
### Related issues
N/A
### Testing
Emulator testing
## Screenshots
N/A
## AI or LLM usage
None
## Description
Addresses suggestion logic oversight in recently merged suggestions fix,
and improve performance (especially app homepage startup time)
- Re-implements the logic that sorts/categorizes tailored suggestions
based on the seed items that are queried. This was implemented in the
original PR at first, but I overlooked moving that logic
- Removes `OneTimeWorkRequestBuilder` and replaces with trigger in
`PeriodicWorkRequest` to fire with a 30 seconds delay if cache is empty.
### Related issues
Fixes#833
### Testing
Will be testing in:
Android TV emulator in Android Studio
NVIDIA Shield TV Pro 2019
## AI or LLM usage
I will use AI to help with writing the tests/testing services.
## Description
This PR aims to fix#638 where the "Suggestions" row was mixing up
content from different libraries that shared the same library type. For
example you were in the Anime library, you'd see regular TV shows
showing up, as the TV Shows and Anime libraries would both be "Show"
libraries.
As @damontecres mentioned in the issue discussion, the
`/Items/Suggestions` endpoint Wholphin is using just returns random
items from the same library type, with no special logic or
recommendation algorithm.
I also looked at how the official WebUI handles this. It basically just
mixes "Resume," "Next Up," and "Latest Items" together. That felt a bit
redundant since we usually have dedicated rows for those things anyway;
I wanted to try something that helps discover new content.
I replaced the broken endpoint with a few custom `GetItemsRequest`
calls. These work correctly with the `ParentId` filter, so we only get
results from the library we are actually looking at. Additionally, I
added in some logic that takes into account what the user has been
watching to tailor the suggestions a little bit.
The new logic uses a 40/30/30 mix (this can of course be tweaked as
needed)
- Tailored (40%): Grabs your recently watched items from this library,
checks their genres, and returns items from the same genre.
- Random (30%): Random unwatched stuff from this library.
- New (30%): Recently added items.
This is implemented using only `GetItemsRequest` API calls using
filters, rather than any specialized endpoints like the
`/Items/Suggestions` endpoint. This means the feature should be
predictable and stable. If Jellyfin ever adds an actual recommendation
algorithm and endpoint to call it, I imagine we would want to switch to
that in the future though.
I also added some failsafe logic to make sure there will be diversity in
the "recently watched" items that get pulled, in case a user might have
recently binged a TV show. We wouldn't want every single recommendation
to be based off of that one show.
To fix this, I changed the query to fetch the last 20 history items
instead of just the top 3. Then, we filter that list client-side to find
unique Series IDs. If the user watched 10 episodes of One Piece in a
row, the logic collapses them into a single "One Piece" entry and moves
on to the next distinct show they watched. This guarantees we get
variety in the source material for recommendations.
This is a work in progress right now, mainly due to performance. For my
server it takes about 10-15 seconds to load the Suggestions row when I
tested. This is unacceptable in my opinion, especially if we ever intend
to add a Suggestions row like this to the home page like Plex does. I
have some ideas on how to improve performance, but I'm open to
suggestions.
### Related issues
Resolves#638
### Screenshots
Before:
<img width="1953" height="1162" alt="suggestions1"
src="https://github.com/user-attachments/assets/6e301c67-1a46-46b5-8184-3adb9e52b330"
/>
After:
<img width="1937" height="1108" alt="suggestions3"
src="https://github.com/user-attachments/assets/b9563865-4055-40b6-b452-f94c26c8b6e9"
/>
### AI/LLM usage
I used Claude Code to help write the Kotlin Coroutines so the API calls
run at the same time. I also used it to write the tests in
`TestSuggestionsLogic.kt`.
---------
Co-authored-by: Damontecres <damontecres@gmail.com>
## Description
Add support for viewing photos in photo albums
### Features
- Browse and view albums & photos
- View an album as a slideshow
- Show overlay with photo details and controls
- Rotate, zoom, & pan photos
- Apply basic filters to photos or albums such as contrast, saturation,
red/green/blue, etc
- Setting to include video clips during slideshows
### Controls
- D-Pad left or right: scroll between photos in album
- Hold D-Pad up or down: zoom in or out of the current photo
- D-Pad left/right/up/down, while zoomed: pan around photo
- Back, while zoomed: revert the zoom
- Otherwise: show photo overlay
### Related issues
Closes#458Closes#634
### Screenshots
#### Overlay

#### Applying filters

## Description
Can now configure a different subtitle style for HDR playback.
There is also a new setting to change the opacity/dim image based
subtitles. This is primarily for HDR to dim very bright PGS subtitles,
but the setting is available for SDR too.
Please remember that the styles only apply to unstyled text formats like
SRT.
I haven't been able to consistently get the preview to switch the
display into HDR mode, so the preview is not 100% accurate.
### Related issues
Closes#583
### Testing
Shield pro 2019 w/ LG C2
## AI or LLM usage
None
## Description
Simplifies the refresh rate/display mode change code by removing the
live data go between.
Also, instead of a `CountDownLatch` that blocks the thread, use a
`Deferred` to suspend the coroutine instead.
### Related issues
Might help with #769
### Testing
Tested on nvidia shield
## Description
Add ability to sort and filter items in a playlist. There's a new button
for each added to the playlist details page. Starting playback will run
in the order selected.
The sort and filter are persisted locally per playlist, so returning to
the playlist will remember the previous settings.
Note: playlist playback is still limited to 100 items (#42)
### Related issues
Closes#285
### Testing
Emulator & nvidia shield
## Screenshots

## AI or LLM usage
None
## Description
When using LOCAL or JELLYFIN authentication methods to connect to Seerr,
the login flow was not properly establishing session cookies and user
permissions. The login would 'succeed' and you were led to thinking it
worked, but then...
This caused:
- Request functionality to be greyed out even though the user should
have access
- Users to appear to have no permissions after login (permissions=0)
## Solution
This PR fixes the authentication flow by:
**Fetching full user config after login**: For LOCAL and JELLYFIN
auth methods, the login endpoints (`authLocalPost()` and
`authJellyfinPost()`) establish the session cookie but return incomplete
user data. This PR now calls `authMeGet()` immediately after login to
fetch the fully-populated user configuration including proper
permissions.
## Tests
- Have working apk on my dev fork.
- Ran logins as Local + API. Cannot test Jellyfin due to environment,
but codewise, it looks correct.
## Related issues
Related to https://github.com/damontecres/Wholphin/issues/747
---------
Co-authored-by: Ray <154766448+damontecres@users.noreply.github.com>
## Description
Due a few more MPV bugs showing up, this PR reverts the part of #736
that made "Prefer MPV" the default player option.
User can still manually switch to "Prefer MPV" and its full functional
remains. It's just not set to be the default anymore.
## Description
Fixes several bugs and makes it easier to log in to a Jellyseer instance
- Fix initial focus & next focus on the add server dialog
- Don't use an API key for non-API key auth (credit to @voc0der in #734
for suggesting this)
- Show trailers for TV shows
- Fix incorrect/missing similar and recommended rows for both movies &
TV shows
- Allow empty password for Jellyfin users without a password
Log in will now try variations of the input URL such as add the protocol
and/or default port. This is similar to the regular Jellyfin login
process.
### Related issues
Fixes#778Fixes#750Fixes#740
Might help with #747
Fixes
https://github.com/damontecres/Wholphin/issues/764#issuecomment-3801324648
## Description
Disables gpu-next by default in MPV settings. This renderer is
experimental and causes broken playback (purple screen) on some older
devices like the NVIDIA Shield 2019 Pro.
Also adds a migration to ensure gpu-next is turned off for existing
users who upgrade, avoiding playback regressions for users being newly
moved over to the Prefer MPV settings so that they can experience a
smooth transition.
### Related issues
Fixes#754?
### Screenshots
N/A
### AI/LLM usage
PR drafting
## Description
The MPV backend is no longer considered experimental. This PR adds a
setting for player backend "Prefer MPV" which uses MPV for all playback
unless the video is HDR which then uses ExoPlayer.
Switching occurs per video. So if there's a playlist with both SDR &
HDR, the player will switch back and forth as needed.
### Related issues
Closes#253
Related to #235
## Description
Adds the [`dav1d` decoder
module](https://github.com/androidx/media/tree/release/libraries/decoder_av1)
for ExoPlayer as an option. It can be enabled in advanced settings.
Performance will vary between devices.
### Related issues
Closes#103
### Dev notes
As with the ffmpeg module, this one is not required to build the entire
app so it's easier for developers to get started.
This also introduces a customized `DefaultRenderersFactory` for
ExoPlayer, but its largely copied from the super class's implementation.