Commit graph

38 commits

Author SHA1 Message Date
Ray
a5a7ed97b7
A few more UI tweaks (#603)
## Description
- Use series poster for seasons without a poster
- Larger logo on playback overlay
- Fix an issue where corner text on card on the home page would not
properly update

### Related issues
Closes #590
Closes #601
Fixes
https://github.com/damontecres/Wholphin/pull/586#issuecomment-3698613927
2025-12-30 18:39:48 -05:00
Ray
aa194f5a2d
Fix duplicates being added to Android TV watch next channel (#588)
## Description
Fixes the logic for determining which items need to be added to the
watch next channel row

Also adds some code to clean up existing duplicates. This code can be
removed around the next release.

Adds a channel to the home screen for recently added media. This is
needed to ensure full integration with the OS to allow toggling off any
of the Wholphin channels including watch next.

### Related issues
#372 introduced the bug
Fixes #587
2025-12-28 17:14:14 -05:00
Ray
9ae4965c2a
Add resume/continue watching items to Android TV watch next row (#372)
## Details

Adds resume and continue watching items for the logged in user to the
Android TV OS level watch next "channel"
(https://developer.android.com/training/tv/discovery/watch-next-add-programs).

## Issues
Closes #206
Related to #581
2025-12-27 15:40:45 -05:00
Ray
639ce0de71
Don't flash previous app content when resuming app & auto sign-in is off (#585)
## Description
When the app is put into the background with auto sign-in disabled, it
will remove the current page and show a loading indicator. This way when
the app is resumed, the previous content won't flash on screen for a
split second.

The above should technically fix #584 on its own, but as additional safe
guide, this PR also makes sure the `ApiClient` is configured before
trying to create image URLs.

### Related issues
Fixes #584
2025-12-27 15:13:45 -05:00
Ray
494ff07b72
Fix smart & default subtitle selection logic (#579)
## Description
Fixes the logic for subtitle selection when using `Smart` or `Default`
server modes. Also takes into account unknown languages.

This is heavily inspired by [the server selection
logic](https://github.com/jellyfin/jellyfin/blob/release-10.11.z/Emby.Server.Implementations/Library/MediaStreamSelector.cs).
For better or for worse, Wholphin implements this client side.

### Related issues
Fixes #570
2025-12-27 14:22:40 -05:00
Ray
b671e14826
Better restoration for auto sign in (#566)
## Description
Improves how the app restores state when auto sign in is enabled. If
auto sign in is enabled, the app will restore back to the last page.

#538 altered the app start up logic. This caused the app to reset state
more often when it goes into the background.

### Related issues
Related to #552
2025-12-24 16:44:41 -05:00
Ray
eb4e9b93be
Add setting to toggle automatic sign in (#538)
## Description
The major user facing change in this PR is adding back the setting to
toggle automatic sign in on or off. This controls whether to restore the
app to where you left off or go the user selection page.

If enabled: re-opening the app will restore the previous user's session

If disabled: re-opening the app will always start with the user
selection page for the most recent server, or if there isn't a recent
server, the server selection page

This also separate this setting from the PIN protection settings in
previous PRs.

### Dev changes

This PR refactors the "setup" UI (server & user selection) to be
separate from the "app" UI (the actually app content). There is now a
`NavDisplay` for the setup flow which ends with displaying the
`ApplicationContent`'s `NavDisplay`. Most of the logic is moved out of
Compose code and into a `ViewModel`.

This means to switch users/server, the `SetupNavigationManager` must be
used instead of `NavigationManager`.


### Related issues
Closes #396
Fixes #376
2025-12-22 14:52:09 -05:00
Ray
925a4b9d82
Add multi-part videos to playback queue (#520)
## Description
When playing media with multiple parts, the additional parts will be
added to the playback queue. This means a multi-part movie or episode
will be play all of the parts in order before the next item in the
queue.

This only affects the playback queue. There's no UI changes and no
indication that a movie or episode has multiple parts. I'll work on that
in a separate PR.

### Related issues
Related to #455
2025-12-21 21:30:00 -05:00
Ray
693398536e
Better images for genre grid (#501)
## Description
Overhauls the genre cards for Movies & TV Show libraries.

Now the cards use a semi-transparent, consistent, generated color using
the same logic as in #478. And a random item from the library with that
genre is show in the background. This is heavily inspired from Plex.

If there are not applicable items for the genre, then just the colored
card is shown.

### Related issues
Fixes #490
2025-12-19 10:46:57 -05:00
Ray
8b40e89b8a
Update MPV playback threading model (#481)
There's no user facing changes in this PR

This PR updates `MpvPlayer` to use a threading model more similar to
[ExoPlayer's
model](https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlayer#threading-model).

There's now a dedicated thread looper message queue between the UI
interactions on the main thread and calls to `libmpv`. This is necessary
because previously, the main thread would make the calls into `libmpv`.
`libmpv` uses internal mutex locking for some operations which meant
that the main thread would be blocked momentarily.

Now, the UI issues a command (eg seek to X position) and the command is
added to the thread looper queue and processed on that separate thread.
This uses the standard Android Handler/Looper mechanisms.

Related to #235
2025-12-17 18:24:25 -05:00
YogiBear12
801ff5e67b
Redesign Select Server and Select User screens (#478)
Redesign Select Server and Select User screens with horizontal card
layout, similar to traditional streaming services

- Replace vertical lists with horizontal list of icons
- Center align text in Quick Connect and Username/Password modals
- Display Jellyfin profile images
- Fallback to first letter of username if no image is available
- Filter out duplicate server entries in the auto-discovery list

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2025-12-17 11:56:19 -05:00
Ray
bbfbc13532
Backdrop improvements (#476)
## Description

The backdrop image shown on most pages is now configurable in advanced
settings:
* Image w/ dynamic color - Shows the backdrop with dynamic color filling
the entire space (new default)
* Image only - Shows only the backdrop image (current Wholphin behavior)
* None - Don't show any backdrops

Additionally, the backdrop is retained between page loads for the same
items.

## Acknowledgements

Big thanks to @YogiBear12 from which the idea and implementation for the
dynamic color was adapted from!

Code adapted from
https://github.com/YogiBear12/Halfin/blob/main/COLOR_EXTRACTION_AND_BACKDROP.md#backdrop-fading-and-transitions

## Issues

Closes #221
Closes #461
Closes #442



https://github.com/user-attachments/assets/1acbc487-c697-44d7-89ed-e7e4c9169360
2025-12-17 11:18:57 -05:00
damontecres
ebfc00c016
Always save series audio & subtitle preferences regardless of preferred languages (#473)
## Description

This PR adjust the logic for audio & subtitle track selection for TV
series. Instead of only saving for future episodes if the newly selected
track is a different language than the user's preferred, always save it.

Basically this means if you change the audio or subtitle language for an
episode, the same audio or subtitle language will be used for future
episodes (if available).

Also, fixes the "default" subtitle mode to take the user's preferred
language into consideration.

## Issues
Follow up to https://github.com/damontecres/Wholphin/issues/378 &
https://github.com/damontecres/Wholphin/issues/427

Fixes #469
2025-12-15 12:15:17 -05:00
damontecres
ff43f8b1b5
Use sdk provided device name (#457)
Use the SDK to get the device name since it handles older Android
versions and has a fallback.

This should not change the device ID or name if the device was working
before this change.

Maybe related to #454
2025-12-14 10:07:46 -05:00
damontecres
a386028b6b
Fix possible NPE during refresh rate switch (#448)
Use current thread's looper or fallback to the main looper for the
display change callback.

This is the behavior in newer versions of Android whereas older versions
assumed a non-null looper.

Fixes #446
2025-12-13 17:58:30 -05:00
damontecres
6edcfb1067
Customize TV guide display (#443)
Adds a view options button for the TV guide to allow some basic
customization:
* Show details header
* Adjust how channels are sorted
* Toggle color coding for programs

Related to #250 
Closes #288 
Fixes #439
2025-12-12 22:05:01 -05:00
damontecres
c5c0dff705
Fix subtitle smart mode to check chosen audio language (#420)
Fixes how the smart subtitle mode logic works

Fixes #406
2025-12-11 12:52:21 -05:00
damontecres
0f4254c6ec
Persist audio & subtitle track changes for series if in different language (#405)
This only applies if the user has set a preferred audio and/or subtitle
language on the web UI!

If the user chooses an audio/subtitle track that is a different language
than their preferred, it will be remembered for that series. Playback of
future episodes of the series will pick a matching language.

The audio & subtitle selections are independent. You can make the choice
before playback or during playback.

Closes #378
2025-12-11 10:16:45 -05:00
damontecres
e0d50baf15
Fix bugs in #380 & #381 (#391)
Just a few minor bugs fixes introduced in recent PRs
2025-12-06 21:28:29 -05:00
damontecres
9e7742034a
Update style for ktlint 1.8 (#390)
Updated `ktlint`, so lots of code style changes, no user facing changes
2025-12-06 18:11:07 -05:00
damontecres
20bef8fb6a
Automatic refresh rate switching setting (#382)
Adds an advanced playback setting to enable automatic refresh rate
switching during playback

When enabled, the app looks at the available display modes, chooses the
best candidate, and attempts to switch to it. After playback ends, the
display is switched back to the original mode.

Closes #62
Closes #379
2025-12-06 16:35:43 -05:00
damontecres
e669f3ad59
Fix combining continue/next-up for new episode premieres (#381)
Better handling for combining continue/next-up by considering the
premiere date of the episode. So episodes will use the previously
watched one's last played date or the episode's premiere date, whichever
is newer.

This means when a new season comes out or the show returns from a break,
the new episodes will show earlier in the list like the next up rows
shows when not combined.

Fixes #377
2025-12-06 15:35:29 -05:00
damontecres
ac10517028
Add setting for subtitle outline size (#375)
Adds a settings allowing for adjusting the thickness of unstyled
subtitle outlines, if outline is enabled.

This is applied for both ExoPlayer & MPV

Closes #179

![outline
Large](https://github.com/user-attachments/assets/dfef74a5-a4d4-49db-a8d2-231e46ab151e)

Dev note: the ExoPlayer implementation is bad code, don't write code
like this. It works though
2025-12-05 16:55:46 -05:00
damontecres
8ea84b3efe
Add setting to protect a user profile with a PIN (#356)
Allows for setting a per-user profile PIN that must be entered to switch
to the user. The PIN is a sequence of directional buttons, ie D-Pad
left/right/up/down.

This PIN is per device per user per server. The PIN is stored locally
and not sent nor shared with the server. If you forget your PIN, can
still access the app using server credentials which also removes the
PIN.

Additionally, there is another setting to disable automatically sign in.
When enabled (default) the last user is automatically restored, even if
there is a PIN. If disabled, a server & user must always be selected
when opening the app.

Closes #268
Closes #321
2025-12-04 14:37:27 -05:00
damontecres
a294661520
Support custom mpv.conf (#327)
Part of #235 
Closes #305

Adds a preference for specifying a custom `mpv.conf`

Also adds a preference to toggle between `vo=gpu` and `vo=gpu-next`, see
https://github.com/mpv-player/mpv/wiki/GPU-Next-vs-GPU

There are some caveats:
* Multi-line text entry via a remote is rough
* [Track selection
options](https://mpv.io/manual/stable/#track-selection) may not work as
expected because Wholphin manages this itself
* Bad settings will crash the app hard

Dev note: This rewrites the text field inputs to use the [state based
implementations](https://developer.android.com/develop/ui/compose/text/migrate-state-based)
2025-12-04 13:21:40 -05:00
damontecres
384401a72c
Customize display of library grid pages (#368)
## Details

Adds options to customize how grid pages are displayed. Every grid page
can be individually customized.

The options are saved per user on the device and restored when
navigating back to the page. The pages that support it have a new button
next to the sort/filter buttons and changes are updated live.

The options are:
* Primary or Thumb image
* Aspect ratio
* Show details header w/ backdrop (similar to the one on the home page)
* Number of columns
* Spacing between cards
* Card image content scale (eg Fit, Fill, Crop, etc)

Note: the Genre tabs' grids cannot be customized yet

### Other changes
- Nav drawer now opens over top of content instead of pushing it
- Images for most cards are fetched with actual fill size

### Possible future work
* Customize Genre grids
* Add more image types, banners?
* Add similar customization options to pages with rows, eg Home page and
Recommended tabs

## Example

For example, this is a movie library using thumb images with 8 columns
and reduced spacing. It also shows the details header

## Issues
Closes #186
Related to #72
2025-12-04 12:20:50 -05:00
damontecres
bddf51e076
Fix some threading issues (#364)
Fixes thread used by changes from #359 

Also create the device direct play profile lazily-ish off of the main
thread because this can take some time to create.

Should help address some of the "too much work" reported in #363, and
also fixes the network-on-main exception in the logs on #363
2025-12-02 19:17:28 -05:00
damontecres
56bf3cb7a0
Optimizes recommended content & image caching (#359)
## Details
This PR contains a number of optimizations

### Images
Updates to request images with maximum sizes

The max sizes are estimates on the maximum number of pixels that will be
actually displayed. This means the server is downscaling large images
which means 1) better quality downscaling and 2) smaller images sent
over the network and cached

This should mean slightly better quality images and more images that can
be cached locally

### Paging
Reduces network calls when fetching paginated data, ie grid pages and
some rows. This PR combines the total record count & first page queries
which slightly reduces total time to load paginated data.

Additionally, on movies/tv show recommended pages, the rows now only
fetch a limited number of items (same as number on home page). While
they previously fetched using pagination, there is an overhead required
to paginate requests, so this is slightly faster.

### Async recommended fetching
On movies/tv show recommended pages, the rows are now fetched completely
separately from each other. Previously, the rows were requested
separtely, but each was only added to the UI in order as each completed.
Now they will add as the data arrived.

Note: Top unwatched TV shows is still very slow on `10.11.x`, see #204


### Image cache

The local, on-disk image cache size is increased from 100mb to 200mb.
Combined with the smaller images, this covers about 1500-2000 poster
images, but will vary by server.

The cache size is now also configurable in advanced settings from 25mb
to 1000mb. Additionally, you can see how much of both the disk and
memory caches are in use.

## Issues
Closes #330 
Related to #120
2025-12-02 16:00:21 -05:00
damontecres
296d7b9226
Setting for subtitle margin & fix subtitle opacity settings (#338)
Adds a subtitle style option to set the margin below unstyled subtitles.
This is roughly the percent of the screen below the subtitles. It
applies to both ExoPlayer & MPV.

Also fixes font & background opacity not being applied in some cases.

Fixes #225
Closes #178
2025-11-28 15:57:11 -05:00
damontecres
7be4fb5fdf
Fix possible TV guide crash & update Play All libraries (#315)
- Fixes a possible crash if the server has Live TV enabled, but no
channels
- Disable Play All/Shuffle for Collections "library"
2025-11-24 11:40:15 -05:00
damontecres
5fbe12e6cf
Fix crash when go backing too quickly (#309)
Fixes #306 

Also fixes network-on-main and potential concurrency issues
2025-11-23 17:19:01 -05:00
damontecres
50dc4b9a35
Play all or shuffle libraries, shows, collections, etc (#278)
Adds ability to play all (or shuffle play) most libraries, collections,
folders, TV series, TV seasons, etc

This adds buttons to play all or shuffle play at the top of grid pages
that support. Additionally, a shuffle button is added to TV Series
details. And play all or shuffle play is added when long clicking TV
seasons.

Note: Until #42 is completed, only the first 100 items will play
back-to-back

Closes #197
2025-11-22 18:40:08 -05:00
damontecres
78e6304571
Prep work for play store distribution (#301)
Allows for disabling in-app updates and more flexible tag/version codes
2025-11-22 12:57:47 -05:00
damontecres
4517dcd0cf
Simplify PlaybackViewModel (#252)
`PlaybackViewModel` was becoming very unwieldy at over 1,300 LOC. This
PR breaks it up and simplifies some fields so it's easier to work with.

There are no user facing changes
2025-11-18 19:18:38 -05:00
damontecres
cda5b118a3
Option to combine continue watching & next up rows (#192)
A real implementation for combining the `Continue Watching` and `Next
Up` rows on the home page.

It requires a query for every next up item, so it could become slow
especially for many items and larger servers. The app makes a best
effort to cache the information.

The order is determined by querying each episode in next up to associate
it to its immediately previous episode's last played date. Then both
continue watching & next up items are reversed sorted by the last played
data. So this only makes sense if you watch series in order.

Closes #19
2025-11-18 15:21:50 -05:00
damontecres
6be2662d4e
Add experimental MPV player backend (#161)
Experimental MPV player backend

Related to #14, #22, & #85

You can switch to MPV in advanced settings and toggle using hardware
decoding or not.

This uses code and buildscripts from
https://github.com/mpv-android/mpv-android, plus other third party
libraries to build MPV
2025-11-16 18:46:25 -05:00
damontecres
93d82a263d
Show extras for Movies & TV Shows (#224)
## Description
Shows local extras (clips, interviews, etc) for movies and tv shows

Extras are grouped by type and clicking on the type will go to a grid
page listing all of the items. However, if there is just one of that
type, it is shown in-line.

Trailers still have on their own row. And theme songs & theme videos are
not shown.

## Issues
Closes #123
2025-11-15 13:25:44 -05:00
damontecres
b7cb6efc4f
Dev: Move services into their own package (#214)
Moves service classes into their own files and package for easier
organization and discovery

No user facing changes in the PR
2025-11-13 19:39:37 -05:00