## 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
This PR has no user facing changes.
Upgrade AGP to 9.x and Gradle to 9.x. Also updates some dependencies as
well.
Note: still using deprecated `android.newDsl=false` because the protobuf
plugin is not yet compatible:
https://github.com/google/protobuf-gradle-plugin/issues/793.
### Related issues
N/A
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## Description
Update dependencies
### Related issues
Just updating some of the dependencies in #858 that don't require AGP 9
### Testing
Emulator
## Screenshots
N/A
## AI or LLM usage
None
## 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
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
Bumps dependency versions.
AGP (and hilt by extension) are not yet updated cause moving to AGP 9
has many breaking changes and I think one or two may affect the build
scripts.
Also, one day I will add Renovate to automate these PRs.
## Description
This PR is a rewrite of a previously submitted PR for this same feature.
It implements native Voice Search for Android TV using Android's
SpeechRecognizer API.
Key Changes
New Files:
- VoiceInputManager.kt - Handles SpeechRecognizer lifecycle, permission
management, and audio level normalization
- VoiceSearchButton.kt - Composable button with audio-reactive pulse and
full-screen listening dialog
UI/UX:
- Audio-reactive microphone button that pulses based on input volume
- Full-screen listening overlay with animated states:
- Listening - Pulsing bubble with ripple rings, shows partial
transcription
- Processing - Animated dots while waiting for final result
- Error - Red bubble with localized error message, auto-dismisses after
3s
### Related issues
Resolves https://github.com/damontecres/Wholphin/issues/515
### AI/LLM usage
The initial draft of this change from the prior PR was created with the
assistance of Claude Code, which was heavily leaned on for the overlay.
I have taken the initial draft, gone through it, and re-implemented by
hand to clean it up, narrow the scope (AI loves to touch and change
things unrelated to what you're working on) and make it more readable.
AI was used in the last stage to assist with finding any logic
errors/bugs I may have missed (by looking through code and also by
looking over ADB logs from testing on Nvidia Shield).. AI was also used
to create the tests found in TestVoiceInputManager.kt. Lastly, I fed the
diffs to an AI to help summarize the changes for this PR in an easy to
read manner.
---------
Co-authored-by: Damontecres <damontecres@gmail.com>
## Description
This PR add the ability to integrate with a [Jellyseerr/Seerr
server](https://github.com/seerr-team/seerr).
### Features
- Login to the Seerr server using API Key, Jellyfin credentials, or
local Seerr credentials
- Separate Seerr logins per user profile
- Search Seerr from the search page
- Discover media from Seerr on the nav drawer `Discover` page
- Also from movie, series, or person pages
- Seamless integration with existing media, i.e. selecting media found
from Seerr that already exists on the Jellyfin server, will go directly
to the regular media page
- Mostly consistent UI between Jellyfin media & Seerr media
- Submit requests to Seerr
- Cancel submitted requests
### Screenshots

### Related issues
Closes#54
## Acknowledgements
The `app/src/main/seerr/seerr-api.yml` file is copied & modified from
https://github.com/seerr-team/seerr/blob/develop/seerr-api.yml. I hope
to try to upstream some of the changes in the future.
## Description
Check if playback is for a remote source and, if so, play that remote
URL directly. Works for both ExoPlayer & MPV.
Also adds support for direct playback for DASH in ExoPlayer.
### Related issues
Closes#471Closes#666
## Description
Creates a `MediaSession` during playback which allows for external
control such as via smart speakers, Google Home app, etc
Note: one limitation is that seeking previous/next items in the playlist
isn't supported. This is because Wholphin manages that independent of
the `Player`, so additional dev work is needed for this.
### Related issues
Closes#622
Might help with #415
Fixes#113
- Ensures all audio and subtitle options are shown during playback
- Fix home rows not being at top when going back
- Show error message when background home page refresh fails
Also shows more details for login failures and adds a link to the debug
page (with log info) after multiple login failure attempts. Hopefully
this can help diagnose #112 and #18
Fixes#99
While not an actual error, it does look like a transitive dependency of
the Jellyfin Kotlin SDK may log using slf4j, so it would be good to
include an slf4j implementation just in case.
Adds ability to send app crash reports to the last connected server. The
app prompts you before sending. There is an advanced settings to disable
this as well.
Additionally, there is an advanced settings button to send the app logs
to the current server.
The resulting reports can be found on the server's web UI under
Dashboard->Logs
If sharing the logs, make sure there's no private information present!
Closes#1
Adds support for Live TV & DVR functionality.
TODO:
- [x] EPG / TV Guide
- [x] View DVR schedule
- [x] Play live TV channel
- [x] Record program
- [x] Record Series
- [x] Cancel recordings
- [x] Access previously recorded content
Remembers changes in playback tracks across playbacks. So, if you change
the audio track, quit the app, and return to the same id, the app will
play the audio track previously chosen.
Additionally, this PR fixes a UI inconsistency when there are multiple
versions of a item. Previously sometimes the audio/subtitle tracks for
wrong version would be shown during playback.