mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-05 18:30:59 +01:00
## 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
105 lines
5.8 KiB
Markdown
105 lines
5.8 KiB
Markdown
# Wholphin developer's guide
|
|
|
|
See also the [Contributing](CONTRIBUTING.md) guide for general information on contributing to the project.
|
|
|
|
## Overview
|
|
|
|
This project is an Android TV client for Jellyfin. It is written in Kotlin and uses the official [Jellyfin Kotlin SDK](https://github.com/jellyfin/jellyfin-sdk-kotlin) to interact with the server.
|
|
|
|
The app is a single Activity (`MainActivity`) with MVVM architecture.
|
|
|
|
The app uses:
|
|
* [Compose](https://developer.android.com/jetpack/compose) for the UI
|
|
* [Navigation 3](https://developer.android.com/guide/navigation/navigation-3) for navigating app screen
|
|
* [Room](https://developer.android.com/training/data-storage/room) & [DataStore](https://developer.android.com/topic/libraries/architecture/datastore) for local data storage
|
|
* [Hilt](https://developer.android.com/training/dependency-injection/hilt-android) for dependency injection
|
|
* [Media3/ExoPlayer](https://developer.android.com/media/media3/exoplayer) for media playback
|
|
* [MPV/libmpv](https://github.com/mpv-player/mpv) for media playback
|
|
* [Coil](https://coil-kt.github.io/coil/) for image loading
|
|
* [OkHttp](https://square.github.io/okhttp/) for HTTP requests
|
|
|
|
## Getting started
|
|
|
|
We follow GitHub's fork & pull request model for contributions.
|
|
|
|
After forking and cloning your fork, you can import the project into Android Studio.
|
|
|
|
### Development environment
|
|
|
|
It is recommended to use a recent version of [Android Studio](https://developer.android.com/studio). Make sure the [version is compatible](https://developer.android.com/build/releases/gradle-plugin#android_gradle_plugin_and_android_studio_compatibility) with Wholphin's AGP version.
|
|
|
|
Code formatting should follow [ktlint's](https://github.com/pinterest/ktlint) rules. Find the `ktlint` version in [`.pre-commit-config.yaml`](./.pre-commit-config.yaml). Optionally, install the [ktlint plugin](https://plugins.jetbrains.com/plugin/15057-ktlint) in Android Studio to run automatically. Configure the version in `Settings->Tools->KtLint->Ruleset Version`.
|
|
|
|
Also, it's recommend to add an extra ruleset jar for Compose-specific KtLint: https://mrmans0n.github.io/compose-rules/ktlint/#using-with-ktlint-cli-or-the-ktlint-intellij-plugin
|
|
|
|
Also setup [pre-commit](https://github.com/pre-commit/pre-commit) which will run `ktlint` as well on each commit, plus check for other common issues.
|
|
|
|
#### Extensions
|
|
|
|
Wholphin uses several native components for extra playback compatibility. This includes Media3 ffmpeg/av1 decoders and `libmpv`. These extensions are not required to build the app, but without them some functionality will not work.
|
|
|
|
If you want to include these in a local build, see the [instructions here](https://github.com/damontecres/wholphin-extensions?tab=readme-ov-file#usage) for configuring the repository.
|
|
|
|
You can also build the extensions locally from https://github.com/damontecres/wholphin-extensions and include them in `app/libs`. The gradle build dependency resolution prefers these local files over fetching from the remote maven registry.
|
|
|
|
Finally, if no `wholphin-mpv` implementation is found, `wholphin-mpv-stub` will be used. This allows the app to compile, but any runtime usage of MPV will throw an exception.
|
|
|
|
## Code organization
|
|
|
|
Code is split into several packages:
|
|
- `data` - app-specific data models and services
|
|
- `preferences` - Non-UI related code for user settings and preferences
|
|
- `services` - hilt injectable services often used by ViewModels for API calls
|
|
- `ui` - User interface code and ViewModels
|
|
- `util` - Utility classes and functions
|
|
|
|
### Settings
|
|
|
|
There are a few different ways user settings are stored:
|
|
1. `AppPreferences` via DataStore
|
|
2. Room database
|
|
3. Key-Value DataStore
|
|
|
|
#### App preferences
|
|
|
|
These are generally settings that apply across the whole app regardless of the currently active user.
|
|
|
|
The `AppPreferences` object can be retrieved from the `UserPreferencesService` or directly via injecting `DataStore<AppPreferences>`.
|
|
|
|
The `AppPreference` (note the `s` differences) objects are used to create the UI for configuring settings using the composable functions in `com.github.damontecres.wholphin.ui.preferences`.
|
|
|
|
##### How to add a new app setting
|
|
|
|
1. Add entry in `WholphinDataStore.proto` & build to generate classes
|
|
2. Add new `AppPreference` object in `AppPreference.kt`
|
|
3. Add new object to a `PreferenceGroup` (listed in `AppPreference.kt`)
|
|
4. Update `AppPreferencesSerializer` to set the default value for new installs
|
|
5. If needed, update `AppUpgradeHandler` to set the default value for app upgrades
|
|
- Since preferences use proto3, the [default values](https://protobuf.dev/programming-guides/proto3/#default) are zero, false, or the first enum, so only need this step if the default value is different
|
|
|
|
#### Room settings
|
|
|
|
These are settings were generally are applied per user. They are stored in several different tables. The entities are defined in `com.github.damontecres.wholphin.data.model`.
|
|
|
|
Additionally, all server and user info for both Jellyfin and Seerr are stored in Room tables.
|
|
|
|
Some examples are:
|
|
- `JellyfinServer`
|
|
- `JellyfinUser`
|
|
- `SeerrServer`
|
|
- `LibraryDisplayInfo`
|
|
- `ItemPlayback`
|
|
|
|
Some of the models, such as `GetItemsFilter` or `ViewOptions`, are stored as JSON in a column instead of defined entities. This should be used sparingly.
|
|
|
|
#### Key-value settings
|
|
|
|
These settings are similar to Room ones and are usually stored per user. These can be accessed via `KeyValueService`. The values are `@Serializable` objects saved as JSON.
|
|
|
|
This should be used sparingly.
|
|
|
|
#### Experimental
|
|
|
|
Some settings are considered "experimental". These may cause instabilities or may need further testing. They may be changed or removed any time.
|
|
|
|
These are stored in the `ExperimentalPreferences` object in `AppPreferences`. Accessing them should always be gated with `ExperimentalPreferences.enabled`. There are a few helper functions for this purpose.
|