Commit graph

170 commits

Author SHA1 Message Date
f60a22e435 Build the Wolfskin TV shell and navigation 2026-11-05 14:38:38 +01:00
670e95f2fa v1.1.0
All checks were successful
review/code-claude Claude cross-family review: approve, no blocking findings
-----BEGIN SSH SIGNATURE-----
 U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgrqffh93Kw9xITbVISXK/jkih9K
 Q1NSQeC6TBqiLCg2oAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
 AAAAQOwlHRfQqaoMZESsY18BqmXMIMwtJzU8cAEB2FWHNv5x2j/ZsGi8ES7VNW+rYtgV/B
 KF9ctdqeDoocL8r8da+AY=
 -----END SSH SIGNATURE-----

Merge upstream v1.1.0 while preserving Wolfskin customizations
2026-11-05 01:39:09 +01:00
Clint Bird
d2713ff2f5
Can Select Artist or Album Artist to be displayed on Music > Artists Page (#2127)
## Description
The Music / Artists view currently appears to use the artist metadata
from individual tracks. While at a track level this makes perfect sense,
it can result in a very noisy and fragmented artists view.

For example, an album by Eminem might contain tracks with artists such
as:
- Eminem
- Eminem feat. 50 Cent
- Eminem ft. Rihanna
- Eminem & Dr. Dre

Each of these seem to appear as a separate artist entry (even though
they are all tracks from the same album by Eminem)

This becomes particularly noticeable in large music libraries, where
featured artists, collaborations, remixes, and slightly different artist
metadata ends up resulting in a large number of sparsely populated or
duplicate / strange looking artist entries.

This PR adds an option / toggle to determine which metadata field is
used to populate the artists view. This option sits neatly within the
current artist view settings e.g. Music > Artists > View options >
Artist source
- Artist (current behavior)
- Album Artist (use the album artist metadata instead)

That Artist setting stays as the default choice (so nobody sees a change
unless they pick it) but now gives the option to filter down only to
Album Artists if desired - this choice is saved per library and applies
immediately.

### Related issues
Closes #1868

### Testing
I've tested it extensively on an Amazon Fire TV Cube Gen 2 (using the
firetv debug variant) the following manual tests were performed:
- The list changes when you pick Album artist and importantly the
selection survives a full app restart
- It was tested on a large library and can confirm only the Album
Artists remained (e.g. only one Eminem entry remained)

Automated checks were run (testFiretvDebugUnitTest & pre-commit) As well
as two new tests being added to the CollectionFolderViewModelTest.kt:
- For letter counting its checking via the album artist endpoint (and
not the standard one) when the source is set as ALBUM_ARTIST
- When the source is changed via the saveViewOptions its triggering a
load from the album artist endpoint

## Screenshots
Please see the screenshots below showing the UI impact / modification:
<img width="4624" height="3472" alt="1"
src="https://github.com/user-attachments/assets/6b53575e-ad15-4f66-b9c0-074657128a1d"
/>
<img width="4624" height="3472" alt="2"
src="https://github.com/user-attachments/assets/528c5766-44d8-43d3-8519-778f5aab7441"
/>
<img width="4624" height="3472" alt="3"
src="https://github.com/user-attachments/assets/5de2fb6d-173d-4ac3-ad1b-e08f27f4dafd"
/>

## AI or LLM usage
The code was written / supported with Claude - the approach (e.g. design
/ storing the choice in ViewOptions) endpoint research etc was done by
myself - I reviewed the approaches / refactoring and than deployed a
debug.apk to my local device to confirm everything was working as
expected.

I've reviewed each line and can explain it / the thinking to approaches
/ logic etc and am comfortable submitting the PR.

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2026-10-31 14:21:41 -04:00
85365aa3c6 Show each episode's own TMDB score next to the series ratings
All checks were successful
review/code-claude Claude code review: pass, no blocking findings (episode TMDB badge)
2026-10-29 21:35:13 +01:00
SergeiAK
2f7804fd5e
Convert Dolby Vision profile 7 to 8.1 on devices without a profile 7 decoder (#2017)
## Description

**On Amlogic boxes (S905X4 and similar) Dolby Vision Profile 7 does not
play as Dolby Vision.**
The server transcodes it, or, with "Direct play Dolby Vision Profile 7"
switched on by hand, the
decoder answers `NoSupport` and fallback ends in HDR10. Devices with a
native Profile 7 decoder,
such as the Shield, are not affected and nothing changes for them.

This PR converts Profile 7 to 8.1 on the fly. It has two halves and one
decision.

The preference `convertDolbyVisionProfile7` is proto field 6 in the
experimental settings, off by
default. In `WholphinRenderersFactory` the filter comes first in the
list, followed by the HDR10+
masking from #1876.

**What this PR does not do.** The enhancement layer is dropped; that is
the price of the
conversion, which is why devices with a native Profile 7 decoder are
left alone.
`BlockAdditional` (an enhancement layer outside the stream) is not read
— like the rest of
Wholphin today — so such a file stays HDR10, as it is now.

### Related issues

Closes #244

Builds on #1876 (the `BitstreamFilter` list). Related to #1540. @fanni42
asked for exactly this on
an S905X4 in #1876.

### Testing

**Hardware** — a debug build of this branch, Homatics box (Amlogic
S905X4, Android 14) + LG BX,
Jellyfin 12.1.0, a Profile 7 FEL remux with the enhancement layer in
band, played from the start
for 39 seconds. Only the new preference was switched on; manual "Direct
play Dolby Vision
Profile 7" was **off**:

* `DolbyVisionProfile7FilterTest` (14) — a fake rewriter on a direct
buffer: offset ≠ 0,
position/limit untouched, every "bytes stay as they were" branch,
three-byte start codes,
  `UnsatisfiedLinkError` tried once;
* `DolbyVisionProfile7ExtractorsFactoryTest` (5, mockk) — only the video
track is rewritten;
* `DolbyVisionProfile7ConversionTest` (6) — codec strings, DRM, `dvh1`.

CI in my fork ran on this branch plus a debug signing commit:
`pre-commit`,
`testDefaultDebugUnitTest` and `assembleDefaultDebug` are all green. The
hardware measurement
above is that build.

## Screenshots

The only UI change is one toggle in the experimental settings.

## AI or LLM usage

The code was written with Claude (Claude Code): the filter, the
extractor wrapper, the condition
and the tests. I reviewed every line and can explain it. It was tested
with the unit tests and
the hardware measurement above. This description was written by me in
Russian and translated
into English with the same assistant.

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Damontecres <damontecres@gmail.com>
2026-10-28 15:16:42 -04:00
Damontecres
f66746cf47
Auto-configure Discover from Wholphin server plugin (#2134)
## Description
https://github.com/damontecres/jellyfin-plugin-wholphin/pull/3 added a
new endpoint for Seerr configuration in Wholphin server plugin.

This PR adds support for reading that configuration and either
pre-filling the URL or automatically logging in.

Some code was copied from #1418 (thanks @matschi95!), but that PR worked
by inserting a DB record for the plugin provided server. Since the local
DB was preferred, this meant plugin config changes wouldn't be reflected
in the client. This PR instead attempts the connection and only updates
the in-memory connection state, so user switching and app restarts will
re-fetch from the plugin.

If the server plugin is not installed or no Seerr server is configured,
nothing in Wholphin changes.

### Related issues
#598 

This PR replaces #1418


### Testing
Emulator with different scenarios

## Screenshots
N/A

## AI or LLM usage
None
2026-10-26 14:18:56 -04:00
Damontecres
6cde8ce8a6
Show warning for future unsupported server version (#2115)
## Description
Now that Jellyfin 12 has been out for over six weeks, it's time to start
considering dropping support for Jellyfin 10 & 11 as part of #1640.

This PR adds a warning message on the switch server, switch user, &
preferences pages if the current server version is <12.

### Related issues
See https://github.com/damontecres/Wholphin/discussions/1640 for further
discussion!

### Testing
Emulator w/ faked data

## Screenshots
N/A, reuses the same error message space

## AI or LLM usage
None
2026-10-25 20:52:20 -04:00
bobberb
9218940a69
Rename music "Top Rated Unwatched" row to "Top Rated" (#2118)
## Description
Rename music "Top Rated Unwatched" row to "Top Rated"

### Related issues
Typo.

### Testing
Android TV

## Screenshots
<!-- Please include screenshots if the PR alters any UI elements -->
<img width="1920" height="1080" alt="pr2-music-recommended-top-rated"
src="https://github.com/user-attachments/assets/3978bc9b-a020-4ee7-ae35-feb19e19ebae"
/>

## AI or LLM usage
Claude wrote the code, I reviewed, deploed a -debug.apk to my device and
tested live.

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 20:52:04 -04:00
e499c3f118 Rebrand the TV app as Wolfskin 2026-10-22 15:05:37 +02:00
Damontecres
551501fa75
Add support for server plugin (#1384)
## Description
PR to add support for a Wholphin server plugin:
https://github.com/damontecres/jellyfin-plugin-wholphin

Note: The plugin is not required to use Wholphin. It adds features the
server admin can use to set default settings like the home page or
eventually Seerr connection info.

### Changes
Wholphin will use the home page settings in order of:
1. Saved on the device locally
2. Saved on the server in the user's profile settings (display
preferences)
3. Provided by `jellyfin-plugin-wholphin`
4. Default fallback: combined continue watching & recently added in
libraries

Under customize home page, you can now see the "source" of the home
settings. This also allows to pick a different source

Finally, instead of the home customization being saved in the background
only locally, if there are any changes, a dialog is shown with options
to save locally, server-side user profile, or discard.

So overall, it's more clear where the home page settings are from and
where the user wants to save them.

### Install

[See instructions
here](https://github.com/damontecres/Wholphin/releases/tag/develop-server-plugin)

### Related issues
Related to #598

### Testing
WIP

## Screenshots
N/A

## AI or LLM usage
None

---------

Co-authored-by: Mario Reisinger <marioreisinger95@gmail.com>
2026-10-19 14:41:08 -04:00
Damontecres
3ef221bf91
Improve track persistence for series & episodes (#1802)
## Description
This PR overhauls how audio and subtitle track persistence works for
series! Previously, when you chose an audio or subtitle track for an
episode, only the language was saved and used for subsequent episodes.
This meant aspects about why that choice were lost such as a forced or
hearing impaired track.

This PR changes the persistence to include more details about the chosen
track. Additionally, the persistence is saved at both the season and
series levels.

## How it works

Selecting the track uses the first success option:
1. Episode specific - User has explicitly chosen an audio/subtitle track
for this episode
2. Season specific - User has chosen the track for another episode in
this season
3. Series specific - User has chosen the track for another episode in
this series
4. User preferences - User has _not_ chosen a track for the episode,
season, nor series, so determine track based on the preferred audio
language, preferred subtitle language, and subtitle mode

Additionally, the season or series specific choices use a scoring
algorithm to find the best suited track. For example, if the chosen
tracks for an episode in the season had the forced flag, this will be
preferred for subsequent episodes. Same for SDH/hearing impaired or
title, etc. This means that the common case, where a season has
substantially identical tracks, will use the same ones across all
episodes (after choosing for one, otherwise falling back to the series
or user preferences).

Finally, this also means that users that prefer SDH/hearing impaired
subtitles can be prioritized now, though there is no global preference
for this yet.

The previous track language choices are migrated to the new algorithm.
They lack the additional context, but this makes for a seamless
transition.

## UI changes

The context menu for choosing audio or subtitle tracks now displays why
that track was chosen.

### Related issues
Fixes #1795
Maybe fixes #1783
Related to #1136 & #1798
Closes #1470

### Testing
Previous unit tests for track selection all pass, plus there are a few
additional unit tests. I've done some testing on the emulator and it
seems to work well. But I think real world testing will be needed.

## AI or LLM usage
None
2026-10-16 10:53:44 -04:00
Jeff Whiting
9f557416ea
New user preference to force enable or disable common HDR and Dolby Vision formats (#1644)
Description
Adding per-format HDR override preferences (HDR10, HDR10+, Dolby Vision
Profile 5/7/8) to control device compatibility information sent to the
Jellyfin server, so users can force specific formats on or off
independently instead of disabling Dolby Vision as a whole.

Related issues
This is a common problem across the Jellyfin ecosystem, but there isn't
a specific issue for Wholphin. My experience is the issue is FireTV
(model and generation) + TV dependent + media dependent. I tested videos
from
https://kodi.wiki/view/Samples with the same DOVIWithHDR10 flag that
worked while other movies I have with It is a very frustrating user
experience and the current workaround of setting the bitrate really low
to force a transcode is sub-optimal IMO as it lowers the video quality.
This allows the user to maintain full quality while disabling only the
specific format(s) causing problems.

https://github.com/jellyfin/jellyfin-androidtv/issues/4021
https://github.com/jellyfin/jellyfin-androidtv/issues/4892
https://github.com/nova-video-player/aos-AVP/issues/1503

https://www.reddit.com/r/jellyfin/comments/12jqoxh/dolby_vision_video_not_working_on_fire_stick_4k/

Testing

<!-- Describe how this change was tested and on what device(s) -->
FireTV 4K (gen 1) + Vizio
FireTV 4K Max (gen 1) + LG
FireTV 4K Max (gen 2) + Vizio
FireTV (gen 1) + Olevia


AI or LLM usage
Claude code assisted and wrote much of the code in this PR. I've
reviewed it all and run the pre-commit linting and formatting.

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2026-10-13 15:41:53 -04:00
Damontecres
559abe2458
Add setting to force transcoding above a max resolution (#1955)
## Description
Adds a new setting to pick a maximum resolution (by height). Any
playback that has a larger resolution will be transcoded down to the
maximum resolution.

Playback equal or less than the maximum resolution will not be affected
and will direct play if otherwise able. This setting is also independent
of the maximum bitrate (ie if max resolution is 4K and max bitrate is
2mbps, playing 4K will transcode).

This setting is pretty much equivalent to the Web UI setting "Maximum
Allowed Video Transcoding Resolution" with "Limit maximum supported
video resolution" enabled.

Note: this setting does not affect which version is chosen by default

### Related issues
Closes #756
Closes #1594

### Testing
Manual emulator testing

## Screenshots
N/A

## AI or LLM usage
None
2026-10-03 18:41:18 -04:00
Damontecres
b0d270380d
Better home page header for Seasons (#2016)
## Description
Updates the home page header & card text when a Season type is shown,
such as in recently added for a TV Show library.

The title or logo for the series is shown with the season name as the
title. The "quick details" has the year of the season. The card shows
the unplayed count of episodes.

### Related issues
Closes #1958

### Testing
Emulator over a few days to see different seasons

## Screenshots
<img width="313" height="153" alt="image"
src="https://github.com/user-attachments/assets/c41e9edd-9f2a-4f62-b76d-e452e83dd8bf"
/>

## AI or LLM usage
None
2026-09-30 17:35:29 -04:00
Jycreyn
a577ae9f1a
Add option to prefer Dolby Vision over HDR10+ on hybrid videos (#1876)
## Description

Adds a "Prefer Dolby Vision over HDR10+" switch (off by default) under
Experimental settings. That screen only shows up once "Experimental
settings" is enabled under Advanced, and until then the switch is read
as off: it goes through `experimentalPreferences.get {}`, so nothing is
wrapped and the playback path is untouched.

Most current 4K web releases carry both Dolby Vision (profile 8.1) RPUs
and HDR10+ dynamic metadata in the same HEVC stream. Some MediaTek based
devices (Philips and TCL TVs, some Fire TV models) latch onto the HDR10+
metadata on those files and never engage Dolby Vision, even though a
Dolby Vision decoder is selected.

I isolated this on my Philips 55OLED810 by playing the same episode
three ways, direct play in all three cases:

| | Stream | TV shows |
|---|---|---|
| A | MKV with DV 8.1 + HDR10+ | HDR10+ |
| B | Same MKV with the HDR10+ metadata removed using
[hdr10plus_tool](https://github.com/quietvoid/hdr10plus_tool), DV
untouched | Dolby Vision |
| C | Same stream remuxed to MP4, both kinds of metadata present |
HDR10+ |

The container doesn't matter and the Dolby Vision signaling is picked up
correctly. The only thing the app can do is keep the HDR10+ metadata
away from the decoder.

When the switch is on, and only when a Dolby Vision decoder was actually
selected, the HDR10+ SEI messages (SMPTE ST 2094-40, recognized by their
ITU-T T.35 header `B5 003C 0001`) are masked in each access unit before
it is queued to MediaCodec. The SEI payload type byte is overwritten
with an unused value (254), so the decoder skips the message. That is
one byte rewritten in place per message: the masking filter returns the
size it was given, so the access unit is queued exactly as long as it
came out of the extractor, which is what makes it safe with both the
synchronous and asynchronous MediaCodec adapters. media3 does the same
thing for HAGC metadata in `HevcSeiUtil`; this filter only targets ST
2094-40, so other T.35 SEI such as CEA-708 captions are not affected.
The filter was written from the H.265 spec, no Kodi or media3 code was
copied.

The hook is generic rather than HDR10+ specific, as asked in the thread.
`BitstreamFilteringCodecAdapterFactory` wraps the codec adapter with a
`List<BitstreamFilter>`, and a filter is `(ByteBuffer, offset, size) ->
Int` where the returned `Int` is the new size of the access unit: the
adapter queues the size the chain reports, and hands each filter the
size the previous one reported. A filter which only overwrites bytes
returns the size unchanged, which is what the HDR10+ masking does; a
filter which drops NAL units compacts what it keeps and reports the
shorter size. A reported size which is negative or larger than the one
the filter was given is ignored rather than queued. That is what lets
the Dolby Vision profile 7 to 8.1 conversion of #244 arrive later as one
more filter instead of a second copy of the adapter plumbing.

When the switch is off, the playback path is unchanged. On a device
without a Dolby Vision decoder (or a display without DV support) the
wrapper is never installed, so HDR10+ only devices keep their metadata.
Encrypted samples, codec config buffers and empty buffers are passed
through untouched.

Kodi has an equivalent option for the same reason: xbmc/xbmc@032cbfeb
and xbmc/xbmc@e2c54e7f.

### Related issues

Implements what was requested in #1855. The filter list is what #244
(Dolby Vision profile 7 direct play) needs, so that conversion can be
added as another filter. #1895 implemented the same masking
independently and was closed in favour of this PR; the device profile
part of it was not carried over, see the note under Testing. Upstream:
androidx/media#1895, where the maintainers say the bug is in the device
codecs and that they don't plan a workaround in ExoPlayer itself.

## AI or LLM usage

The implementation (bitstream filter, MediaCodecAdapter wiring, unit
tests) were written with AI assistance (Claude). I reviewed the changes
and validated the behavior myself on a real MediaTek TV (Philips
55OLED810), with the setting on and off, on hybrid and DV-only content.

---------

Co-authored-by: Jycreyn <github.2ilp7@passmail.com>
2026-09-29 12:41:40 -04:00
Damontecres
616565f671
Fixes to v1.0.7 (#1953)
## Description
Collection of minor bug fixes for `v1.0.7`

- Fixes a possible race condition crash when navigating to the search
page
- Uses friendlier error message when login fails due to parental
restrictions (based on
[`jellyfin-web`](https://github.com/jellyfin/jellyfin-web/blob/v10.11.11/src/controllers/session/login/index.js#L38-L41))
- Don't re-sort search results by name, just by relevance scoring
- Consume the key event when dim is active (ie if the screen is dimmed,
pressing a key will un-dim and not perform another action)

### Related issues
Fixes #1922 
Fixes #1951
Related to #1848 (search sorting)

### Testing
Emulator & nvidia shield

## Screenshots
N/A

## AI or LLM usage
None
2026-09-11 15:40:11 -04:00
Damontecres
9c56965c82
Add controls to edit playlists (#1927)
## Description
Adds support to remove items from a playlist and move items within a
playlist

The remove option is in the context menu. Moving has buttons on the
right side. The buttons are available if the user has edit permissions
and the playlist is sorted by "Default" (the playlist order). Remove
from playlist option is available if the user has edit permissions.

Also, thumb images are now preferred instead of primary/poster images
since the layout is much wider than tall.

### Related issues
Closes #1881

### Testing
Emulator with both a user with & without permissions to edit

## Screenshots
### With move buttons
<img width="1280" height="720" alt="playlist_buttons Large"
src="https://github.com/user-attachments/assets/ce7880c3-b823-4b69-9ad4-cfc9e7ee5fd5"
/>

### Without move buttons
<img width="1280" height="720" alt="playlist_no_buttons Large"
src="https://github.com/user-attachments/assets/f2027052-4628-4d44-8257-6c2a5e8c3af4"
/>


## AI or LLM usage
None
2026-09-10 17:18:26 -04:00
Tal Sarid
1f3a861c47
Localized formatting for season and episode display (#1884)
## Description
Added localized formatting for season/episode numbers across the UI
because it was in English-only in every UI language.

### Related issues
None

### Testing
Tested on a physical Google TV Streamer 4K device. Checked manually
relevant screens while browsing and during playback.

## Screenshots
No frontend changes are visible in English and new translations will be
contributed through Weblate for other languages later, as usual.

## AI or LLM usage
Generated initial code with AI, then manually passed over it while
cleaning and refactoring where needed.

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2026-09-04 12:47:06 -04:00
Damontecres
fdde986029
Update favorites page with more types (#1864)
## Description
This PR adds many more data types as tabs to the favorites page.
Additionally, only tabs for the types the user has favorites for will
appear. For example, if you have no favorited music videos, that tab
will not show.

Added types:
- Collections
- TV Channels
- Music albums
- Music artists
- Music videos
- Songs
- Home videos
- Photos
- Photo albums

Dev note: The tabs are implemented using keys instead of indexes which
could be useful for the series overview season tabs. Plus it maybe even
be adapted for the episode list to eliminate the terrible index search
logic. A major difference is that the possible favorites tabs are
known/static list where seasons/episodes are queried & paginated.

### Related issues
Closes #1041
Closes #1844

### Testing
Manually on emulator, plus unit tests

## Screenshots
N/A

## AI or LLM usage
None
2026-08-26 21:50:13 -04:00
Damontecres
f91bca18ff
Add more searchable types & choose what to search (#1857)
## Description
This PR adds several more data types to search. It also adds a setting
(per use profile) to choose which types to include/exclude when
searching. The combined results now uses the same types instead of a
separate list.

A user can only search for types that they have access to. For example,
they need Live TV access for TV channels/programs or need access to a
movies-type library to search movies.

Added types to search:
- Photos & Photo albums
- Playlists
- People
- TV channels
- Live TV programs

Clicking a TV channel will play it. Clicking a TV program shows the
program dialog allowing for recording or watching live if it's currently
airing.

On the main search page you can also toggle whether to search Seerr or
not. This does not apply to the discover search tab.

Dev note: Some minor refactoring to move setting up/canceling live tv
recordings into a new service so it can be shared between with the live
tv & search pages. Also search related files are moved into the same
package now.

### Related issues
Closes #409
Closes #646 
Closes #1668
Closes #1750

### Testing
Emulator using users with different permissions and library access

## Screenshots
<img width="475" height="584" alt="image"
src="https://github.com/user-attachments/assets/ebcff697-07ba-4ddd-8c26-57f147cfa02a"
/>


## AI or LLM usage
None
2026-08-26 14:39:02 -04:00
Damontecres
c4264a3263
Adds option to dim the screensaver (#1834)
## Description
Adds a new sceensaver setting to add dimming. A larger value is darker

This works with or without the in-app screensaver. If dimming is
enabled, the screen be will be dimmed after inactivity. If both dimming
and the in-app screensaver are enabled, the screensaver will show dimmed
after inactivity.

### Related issues
Closes #1179

### Testing
Emulator

## Screenshots
N/A, it's just darker

## AI or LLM usage
None
2026-08-17 22:53:40 -04:00
Nehereus
1c0e9a5853
Add a preference option to disable hardware audio offloading (#1564)
## Description
By default, Wholphin plays music with hardware audio offloading enabled.
This delegates audio decoding to the device's hardware DSP, making
playback stability highly dependent on the manufacturer's system audio
implementation. On certain hardware (such as my TCL TVs, e.g., the
Chinese Model Q9L Pro), this implementation causes music playback to
hang indefinitely at 0 seconds.

### Related issues
#1372

### Testing
Tested on a TCL TV (Q9L Pro):
- Some musics playback hangs at 0s with offloading enabled.
- Disabling audio offloading fixes the issues for all medias.

## Screenshots
<!-- Please include screenshots if the PR alters any UI elements -->
<img width="4284" height="5712" alt="IMG_9486"
src="https://github.com/user-attachments/assets/ddf95e68-6ebd-42f9-9565-568de4fbfc42"
/>

## AI or LLM usage
Developed in pair with Gemini and human-reviewed, tested.

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2026-08-11 13:36:03 -04:00
Damontecres
8bae9c7f23
Fixes for error handling, UI padding, & more (#1759)
## Description
Another collection of small individual fixes that don't warrant a full
PR:
- Better error handling for series and collection detail pages
- Better error handling on Discover search tab
- Fix issues when changing view options on card grid without reloading
the page
- Better error handling when changing the refresh rate or resolution
- Fix some nav drawer items disappearing briefly when restarting the app
- Fix that the discover search row would not clear when the query is
cleared

And some UI tweaks:
- Use consistent padding for the different customize home page sections
- Convert the "Continue watching click behavior" setting from a toggle
to choice dialog (the options & behaviors have not changed)

### Related issues
I think the error handling when changing the refresh rate might help
with #1737

### Testing
Emulator mostly

## Screenshots
N/A, UI changes are minor

## AI or LLM usage
None
2026-07-29 10:21:49 -04:00
Damontecres
79cb93db08
Fixes to artist detail page (#1762)
## Description
Fixes an incorrect query for an artist's albums (thanks @StefanBS for
reporting & fixing in #1761!)

Additionally, another album row for "Appears on" is added. This is
definitely necessary because Wholphin only has a tab for all artists
which includes artists featured on albums attributed to a different
artist. So those albums will now show in the "Appears on" similar to the
web UI instead of an empty artist page.

Finally, the long-click context menu is added for music videos on an
artist's page.

### Related issues
Fixes #1760
Replaced #1761 

### Testing
Emulator, particularly with artists who are not album artists

Also, verified the query fix against the web UI dev console

## Screenshots
N/A

## AI or LLM usage
None, but the fix included from #1761 did use some AI

---------

Co-authored-by: Stefan Bullones <stefan.bullones@gmail.com>
2026-07-28 15:17:57 -04:00
Damontecres
9954365c6f
Add two new themes: Red & Brown (#1721)
## Description
Adds new two new theme colors: Red & Brown

### Related issues
Related to #91, #950
Closes #1646

### Testing
<!-- Describe how this change was tested and on what device(s) -->

## Screenshots
<img width="2727" height="2171" alt="image"
src="https://github.com/user-attachments/assets/ae19f98d-e782-466a-bafc-6c0502f64e00"
/>

## AI or LLM usage
None
2026-07-25 22:52:09 -04:00
Damontecres
e7b0be2660
Display server error message on server list (#1741)
## Description
On the switch server page, display error message at the bottom for the
focused server. This includes unsupported server version.

### Related issues
Jellyfin 10.11/12.0 support discussion: #1640

### Testing
Emulator

## Screenshots
<img width="1280" height="720" alt="server_error Large"
src="https://github.com/user-attachments/assets/1227e7e7-a364-48d9-9a77-cb3f78d134a1"
/>

## AI or LLM usage
None
2026-07-25 22:52:02 -04:00
Damontecres
26a23d673b
Add option for dpad skipping with no seek bar (#1742)
## Description
Adds a third option for d-pad seeking to not show any seek bar which
only shows the skip indicator and not the seek bar along the bottom

### Related issues
Original work to add other mode in #1650
Closes #1520

### Testing
Emulator testing

## Screenshots
<img width="546" height="347" alt="image"
src="https://github.com/user-attachments/assets/2872566e-4598-4284-92cb-95a45b307835"
/>

## AI or LLM usage
None
2026-07-25 16:10:00 -04:00
calebvetter
cf3c00a1e1
Add option for trickplay preview mode when D-Pad seeking (#1650)
## Description
Adds a setting to allow the user to choose between the current D-Pad
skip functionality, and a new simple trickplay overlay.

The setting is added in Advanced, under the Playback section, called
"D-Pad seek mode". The options are "Skip time" and "Trickplay previews".
I left the default as "Skip time" since that's how it operates now, and
nothing would change for users after this option is added unless they go
and set it.

When "Trickplay previews" is enabled, it shows an simple overlay when
using the D-Pad to seek (without the full overlay open). The new simple
overlay is the same implementation of the components in the full
overlay: seekbar, trickplay images, current playhead time, remaining
time. The components were pulled from the full overlay's inline UI code
into their own reusable components, now used in both the full overlay
and the simple overlay.

#### Notes
I could see there being an adjustment for the overlay hide delay. It's
currently hard coded to 1.5s.

This could be the default method, but it seems like preference is split
as to whether people want this, or the minimalistic skipped seconds only
version.

### Related issues
This is directly in response to this issue, as well as my own desire for
the feature :)
https://github.com/damontecres/Wholphin/discussions/1084

It's also loosely related to this issue, in that it would solve it since
it shows the playhead and remaining times.
https://github.com/damontecres/Wholphin/discussions/1122

### Testing
Built and tested on an Amazon Fire TV Stick 4K Max. I wouldn't
anticipate and compatibility or performance changes since it's a simple
settings/UI change involving already-used UI components.

## Screenshots
<img width="1920" height="1080" alt="wholphin-20260630-155708"
src="https://github.com/user-attachments/assets/52046cc2-7413-4f66-89dd-355464fa0f91"
/>
<img width="1920" height="1080" alt="wholphin-20260630-155723"
src="https://github.com/user-attachments/assets/57a4a271-9e44-4d2a-bea3-ce5c9cdc731a"
/>
<img width="1920" height="1080" alt="wholphin-20260630-153825"
src="https://github.com/user-attachments/assets/2cf664ff-3db5-4a2e-8626-10219946669c"
/>


## AI or LLM usage
AI was used to generate the change, automate some testing, and provide
information surrounding the change. I manually did some refactoring and
cleanup to keep it clean and consistent with the rest of the code
conventions.

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2026-07-23 15:32:40 -04:00
Damontecres
5bc874a9ff
Fix music artist listing & show music in collections (#1739)
## Description
Switches to use the Artists API instead of Items API when fetching the
list of artists in a library.

Enables fetching artists, albums, and music videos in a collection.

Also adds titles for the remaining `BaseItemKind` types for future
proofing even if they aren't used anywhere in the app.

### Related issues
Fixes #1733
Fixes #1734
Fixes #1735


### Testing
Emulator, created a new collection with the above. Also verified the
artist query against the web UI

## Screenshots
N/A

## AI or LLM usage
None
2026-07-23 14:23:48 -04:00
Damontecres
00490b14ec
Improvements to subtitle search & download (#1728)
## Description
Changes to searching & downloading subtitles:
- Activating newly downloaded subtitles more reliably
- Better audio index adjustment checks after downloading subtitles
- Sort subtitle downloadable options by whether the file hash matches
first
- Update the UI for subtitle downloadable options

Also, some improvements to the subtitle choice dialog:
- It now loops from top to bottom (and vice versa)
- It now focuses initially on current choice

### Dev notes
This PR now the selected tracks from `state.currentItemPlayback` to
`state.currentPlayback`. `currentItemPlayback` now only reflects the
user's choices saved in the database instead of a combination of DB and
"actual" state. `currentPlayback` stores the actual, resolved track
indexes regardless of how they were derived.

This means the indexes values in `state.currentItemPlayback` and
`state.currentPlayback` may be different. For example, if the user has
chosen "Only forced", `state.currentItemPlayback==-3` but
`state.currentPlayback` might be an actual forced track index.

### Related issues
Fixes #1549
Fixes #1718
Closes #1723
Fixes bug reported in
https://github.com/damontecres/Wholphin/issues/1498#issuecomment-5019965271

### Testing
Emulator

## Screenshots

Now shows SDH & hash matching

<img width="779" height="280" alt="image"
src="https://github.com/user-attachments/assets/4c33e5af-c9a1-4c9c-8217-6bc2ab3fcd27"
/>

## AI or LLM usage
None
2026-07-23 13:30:43 -04:00
Damontecres
35c4d13f8f
Various minor bug fixes (#1707)
## Description
Gathering several small bug fixes:
- Clear the backdrop when manually reloading the home page
- Convert the "# years old" string resource to plural
- Fix a spelling error in the source English strings
- Ensure #1680 is respected when searching for subtitles to download
- Slightly adjust padding for the header in collection details to match
other headers

### Related issues
Fixes string issues reported in
https://github.com/damontecres/Wholphin/issues/1705#issuecomment-4982909931

### Testing
Emulator

## Screenshots
N/A

## AI or LLM usage
None
2026-07-18 17:50:35 -04:00
Damontecres
3f60fa7550
Add option to override user profile settings for audio & subtitle languages (#1680)
## Description
Adds settings under the "User profile settings" section which allows for
specifying preferred languages for audio and subtitles and the preferred
subtitle mode.

By default (matching existing Wholphin behavior), the preferred
languages and subtitle mode are derived from the user's profile settings
provided by the server which can be set on the WebUI:
User->Settings->Playback or Subtitles. However, this isn't well
understood and Wholphin doesn't display these values anywhere, so many
users were confused.

The preferred languages and subtitle mode can now be configured from
within Wholphin. Setting these will **not** update the server. The
settings are **only** used locally.

### Related issues
Related to #319
Closes #790

### Testing
Emulator manually changing some settings, added additional unit tests to
ensure the overrides are respected when choosing tracks

## Screenshots
### Settings page
<img width="1280" height="720" alt="settings_01 Large"
src="https://github.com/user-attachments/assets/28cc2f6b-3a60-42a4-b268-48695086d566"
/>

### Clicking into "More user profile settings"
<img width="1280" height="720" alt="settings_02 Large"
src="https://github.com/user-attachments/assets/6c3be3aa-c177-4d44-8060-b76d15fb10d7"
/>

### Language choice dialog

Can filter languages by typing in the search box at the top

<img width="1280" height="720" alt="settings_03 Large"
src="https://github.com/user-attachments/assets/c014d0ba-8d5b-4201-a6ee-4876b478148c"
/>


## AI or LLM usage
None
2026-07-14 14:17:31 -04:00
Damontecres
d481aea85a
Experimental option to transcode surround sound audio to AC3 (#947)
## Description
Adds an experimental setting to prefer transcoding audio with more than
2 channels to AC3. Stereo audio does not transcode.

This is basically a workaround for HDMI ARC (not eARC) or optical audio
devices because instead of 2 uncompressed PCM channels, 6 AC3 channels
(ie 5.1) is possible.

An downside of enabling this is that embedded subtitles be burned in
causing a video transcode as well.

### Related issues
Fixes #255
Incorporates some code from #1410

### Testing
Just on the emulator so far to observe if the settings trigger the
transcode or not

## Screenshots
N/A

## AI or LLM usage
None

---------

Co-authored-by: darkflame91 <darkflame91@gmail.com>
2026-07-09 13:15:42 -04:00
Damontecres
013755208d
Update Seerr integration version & start blocklist handling logic (#1671)
## Description
Start testing against Seerr `3.3.0` which has been out for over a month.
The only significant change is that the new "blocklisted" status is
added, but it uses the same code as the previous "deleted" status. So
generally, Seerr `3.2.0` will still work.

This starts work on supporting Seerr's blocklist which, unfortunately,
is expected to be enforced on the client side. For now, blocklisted
items still show, but the request button is disabled and shows
"Unavailable" instead.

Finally, some Seerr parent permissions I missed in #1631 are added.

### Related issues
Related to #1626

### Testing
Emulator testing

## Screenshots
N/A

## AI or LLM usage
None
2026-07-07 13:56:22 -04:00
Tal Sarid
f6e00c7820
Add localized duration formatting and related string resources (#1571)
## Description
Instead of using English-only duration format (e.g. `HHh MMm SSs`) in
various places, I've added a format function that is based on several
new localized resources keys.

That includes:
1. Media runtime in Item view
2. Time remaining in Item view
3. End time in Player view
4. Time passed and time remained in Player view

### Related issues
None

### Testing
I installed the app on my Google TV Streamer, switched to my language,
browsed all item views that I could think of to see that the duration
labels are all localized in my language. I didn't commit those strings,
I will do it through the Weblate after it will get merged. I also played
a few items and saw that the labels there are localized as well.

## Screenshots
It looks the same in English as before, currently no other language has
custom resources for it yet.

## AI or LLM usage
Used Claude Sonnet to detect places that I missed that are related to
this localization change. Also it helped me to get access to my format
function from various places in the code.

---------

Co-authored-by: Damontecres <damontecres@gmail.com>
2026-07-06 08:43:06 -04:00
Damontecres
083d4e4fa8
Add experimental settings & video tunneling (#1624)
## Description
This PR introduces the concept of "experimental" settings or features.
These may cause instabilities or may need further testing. They may be
changed or removed any time. Also, the developers won't provide lots of
support for them.

The goal is expose some specialized settings that might only apply to a
small subset of users or test out tweaks to playback.

The first experimental feature is a toggle to enable [video
tunneling](https://developer.android.com/media/media3/exoplayer/track-selection#tunneling).

### Related issues
Related to #1283

### Testing
Emulator

## Screenshots
N/A

## AI or LLM usage
None
2026-06-27 14:29:37 -04:00
Damontecres
e5887dfa15
Better UX for separate SDR vs HDR subtitle styles (#1622)
## Description
This PR moves the separated HDR subtitle style behind a toggle. This
means users must now opt-in to using separated SDR vs HDR subtitle
styles. This is a better UX for users who want to customize the style
but use the same styles for both.

Users who have changed the HDR subtitles previously will have the toggle
enabled automatically. If the user hasn't changed HDR style or their SDR
& HDR styles are the the same, the toggle will be disabled.

Also, fixes a bug where when playback switched between SDR or HDR, the
subtitle styles might not be updated.

### Related issues
Closes #1603

### Testing
Emulator & unit tests for migration

## Screenshots
N/A

## AI or LLM usage
None
2026-06-24 19:26:05 -04:00
Damontecres
d705a3ea01
Add filtering & sorting for discover grid pages (#1614)
## Description
This PR adds sort & filter options for the discover grid pages.

Sort options:
- Popularity
- Release date
- "Community rating" (TMDB user vote)
- Name

Filter options:
- Genre
- Studio/Network
- "Community rating" (TMDB user vote)
- Parental rating
- Production status (TV only)

Also, two more tabs are added to the discover page for browsing movies
and TV. These are essentially the same as clicking "View more" on the
respective rows on the Discover tab.

### Limitations

This PR hardcodes the region used for studio listing and filtering to
"United States". I'll work on a follow up PR to enable users to specify
this.

The sort & filters are not persisted. I think they should be on the two
new tabs, but not elsewhere, but this will be a follow up PR.

### Related issues
Related to #702 
Implements some of #1511
Rewrites the filter logic in #1610 

### Testing
Emulator, but needs further testing

## Screenshots
<img width="1280" height="720" alt="discover_filters Large"
src="https://github.com/user-attachments/assets/cdefb95c-c4b7-4e06-9bac-b535d372ba03"
/>


## AI or LLM usage
None
2026-06-23 17:24:37 -04:00
Damontecres
f21b29fe1b
Discover movies & tv shows by genre (#1610)
## Description
Adds genre rows for movies & TV shows to the discover page. These work
the same as on the Seerr web UI, clicking one will show media in the
genre.

### Related issues
Related to https://github.com/damontecres/Wholphin/issues/702

### Testing
Just on the emulator so far

## Screenshots
<img width="1280" height="720" alt="discover_genres Large"
src="https://github.com/user-attachments/assets/93e5ef25-e253-49bc-9009-89f814889c98"
/>


## AI or LLM usage
None
2026-06-22 19:35:44 -04:00
Damontecres
77d7571276
Choose Seerr quality profile & root folder (#1604)
## Description
Adds option to select the quality profile and/or root folder when
requesting from Seerr.

The user needs "Advanced Requests" permission to use this feature. If
not, the options won't show.

### Related issues
Closes #863
Related to #702

### Testing
Emulator w/ different user permissions and different request
configurations

## Screenshots
<img width="1280" height="720" alt="request_movie Large"
src="https://github.com/user-attachments/assets/2665dcbb-e6c3-4d26-857c-b465edff6a02"
/>


## AI or LLM usage
None
2026-06-22 18:37:16 -04:00
Damontecres
ddbec0da73
Fix issues from #1530 2026-06-14 19:55:01 -04:00
Damontecres
fa5cc99c3b
De-duplicate string resource keys (#1560)
## Description
Ensures that all string & plural resource keys are unique. This should
help make sure all of the strings are shown in weblate's translation.

### Related issues
Related to #1551

### Testing
Emulator

## Screenshots
N/A

## AI or LLM usage
None
2026-06-12 01:24:24 -04:00
Damontecres
8ea6bbbfca
Improvements to home page customization (#1458)
## Description
Adds a few enhancements to home page customization:
- Add option to combined continue watching & next up to split it
- Add option to continue watching and next up rows to combine them
- Add option for sorting playlist or collections
- Show suggestions (recently updated) when searching for a playlist or
collection to add
- Better handling for loading vs unsupported types for suggestions

Also, the old toggle for combining continue watching & next up in
advanced settings is removed. Now by default the rows will be combined
unless changed in the home page customization settings.

### Related issues
Closes #340
Closes #1383
Closes #1350

### Testing
Just on the emulator so far

## Screenshots
N/A

## AI or LLM usage
None
2026-05-26 13:30:00 -04:00
Damontecres
982d9e6fe8
Add list view for libraries (#1428)
## 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
2026-05-24 18:07:56 -04:00
Damontecres
903c45dfb8
Support configuring interface language per user (#1406)
## 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 #513
Closes #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
2026-05-24 09:55:08 -04:00
JustinZeus
fa914845f4
Add option to hide the voice search button (#1423)
## 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>
2026-05-21 15:31:17 -04:00
Damontecres
366483599c
Customize which ratings to display (#1407)
## 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
2026-05-20 12:40:58 -04:00
Damontecres
45d466d76f
Add option to require server login for user profile (#1367)
## 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
2026-05-20 12:00:02 -04:00
Damontecres
87a109c6b6
Add option for click to play continue watching/next up rows (#1405)
## 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
2026-05-19 14:11:40 -04:00
Justin Caveda
98ffaf51ac
Search page improvements (#709)
## 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.
2026-05-13 10:02:33 -04:00