mirror of
https://github.com/jellyfin/jellyfin-androidtv.git
synced 2026-10-26 16:45:23 +00:00
Refactor preference code
- Allow migrations in all store types - Remove blocking functions from the preference module - Move Preference.xx functions to global functions
This commit is contained in:
1 parent
0e9281388a
commit
33005e3939
22 files changed
+155
-130
No files matched your search
@@ -3,25 +3,27 @@ package org.jellyfin.androidtv.preference
|
||||
import android.content.Context
|
||||
import org.jellyfin.androidtv.auth.model.AuthenticationSortBy
|
||||
import org.jellyfin.androidtv.preference.constant.UserSelectBehavior
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.booleanPreference
|
||||
import org.jellyfin.preference.enumPreference
|
||||
import org.jellyfin.preference.store.SharedPreferenceStore
|
||||
import org.jellyfin.preference.stringPreference
|
||||
|
||||
class AuthenticationPreferences(context: Context) : SharedPreferenceStore(
|
||||
sharedPreferences = context.getSharedPreferences("authentication", Context.MODE_PRIVATE)
|
||||
) {
|
||||
companion object {
|
||||
val autoLoginUserBehavior = Preference.enum("auto_login_user_behavior", UserSelectBehavior.LAST_USER)
|
||||
val autoLoginUserId = Preference.string("auto_login_user_id", "")
|
||||
val autoLoginUserBehavior = enumPreference("auto_login_user_behavior", UserSelectBehavior.LAST_USER)
|
||||
val autoLoginUserId = stringPreference("auto_login_user_id", "")
|
||||
|
||||
val systemUserBehavior = Preference.enum("system_user_behavior", UserSelectBehavior.LAST_USER)
|
||||
val systemUserId = Preference.string("system_user_id", "")
|
||||
val systemUserBehavior = enumPreference("system_user_behavior", UserSelectBehavior.LAST_USER)
|
||||
val systemUserId = stringPreference("system_user_id", "")
|
||||
|
||||
val sortBy = Preference.enum("sort_by", AuthenticationSortBy.LAST_USE)
|
||||
val alwaysAuthenticate = Preference.boolean("always_authenticate", false)
|
||||
val sortBy = enumPreference("sort_by", AuthenticationSortBy.LAST_USE)
|
||||
val alwaysAuthenticate = booleanPreference("always_authenticate", false)
|
||||
|
||||
/**
|
||||
* Do not set directly, use [SessionRepository] instead.
|
||||
*/
|
||||
val lastUserId = Preference.string("last_user_id", "")
|
||||
val lastUserId = stringPreference("last_user_id", "")
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,9 @@ import org.jellyfin.androidtv.constant.PosterSize
|
||||
import org.jellyfin.androidtv.preference.store.DisplayPreferencesStore
|
||||
import org.jellyfin.apiclient.model.entities.SortOrder
|
||||
import org.jellyfin.apiclient.model.querying.ItemSortBy
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.booleanPreference
|
||||
import org.jellyfin.preference.enumPreference
|
||||
import org.jellyfin.preference.stringPreference
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
|
||||
class LibraryPreferences(
|
||||
@@ -17,17 +19,17 @@ class LibraryPreferences(
|
||||
api = api,
|
||||
) {
|
||||
companion object {
|
||||
val posterSize = Preference.enum("PosterSize", PosterSize.AUTO)
|
||||
val imageType = Preference.enum("ImageType", ImageType.DEFAULT)
|
||||
val gridDirection = Preference.enum("GridDirection", GridDirection.HORIZONTAL)
|
||||
val enableSmartScreen = Preference.boolean("SmartScreen", false)
|
||||
val posterSize = enumPreference("PosterSize", PosterSize.AUTO)
|
||||
val imageType = enumPreference("ImageType", ImageType.DEFAULT)
|
||||
val gridDirection = enumPreference("GridDirection", GridDirection.HORIZONTAL)
|
||||
val enableSmartScreen = booleanPreference("SmartScreen", false)
|
||||
|
||||
// Filters
|
||||
val filterFavoritesOnly = Preference.boolean("FilterFavoritesOnly", false)
|
||||
val filterUnwatchedOnly = Preference.boolean("FilterUnwatchedOnly", false)
|
||||
val filterFavoritesOnly = booleanPreference("FilterFavoritesOnly", false)
|
||||
val filterUnwatchedOnly = booleanPreference("FilterUnwatchedOnly", false)
|
||||
|
||||
// Item sorting
|
||||
val sortBy = Preference.string("SortBy", ItemSortBy.SortName)
|
||||
val sortOrder = Preference.enum("SortOrder", SortOrder.Ascending)
|
||||
val sortBy = stringPreference("SortBy", ItemSortBy.SortName)
|
||||
val sortOrder = enumPreference("SortOrder", SortOrder.Ascending)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@ package org.jellyfin.androidtv.preference
|
||||
|
||||
import org.jellyfin.androidtv.preference.store.DisplayPreferencesStore
|
||||
import org.jellyfin.apiclient.model.querying.ItemSortBy
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.booleanPreference
|
||||
import org.jellyfin.preference.stringPreference
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
|
||||
class LiveTvPreferences(
|
||||
@@ -12,13 +13,13 @@ class LiveTvPreferences(
|
||||
api = api,
|
||||
) {
|
||||
companion object {
|
||||
val channelOrder = Preference.string("livetv-channelorder", ItemSortBy.DatePlayed)
|
||||
val colorCodeGuide = Preference.boolean("guide-colorcodedbackgrounds", false)
|
||||
val favsAtTop = Preference.boolean("livetv-favoritechannelsattop", true)
|
||||
val showHDIndicator = Preference.boolean("guide-indicator-hd", false)
|
||||
val showLiveIndicator = Preference.boolean("guide-indicator-live", true)
|
||||
val showNewIndicator = Preference.boolean("guide-indicator-new", false)
|
||||
val showPremiereIndicator = Preference.boolean("guide-indicator-premiere", true)
|
||||
val showRepeatIndicator = Preference.boolean("guide-indicator-repeat", false)
|
||||
val channelOrder = stringPreference("livetv-channelorder", ItemSortBy.DatePlayed)
|
||||
val colorCodeGuide = booleanPreference("guide-colorcodedbackgrounds", false)
|
||||
val favsAtTop = booleanPreference("livetv-favoritechannelsattop", true)
|
||||
val showHDIndicator = booleanPreference("guide-indicator-hd", false)
|
||||
val showLiveIndicator = booleanPreference("guide-indicator-live", true)
|
||||
val showNewIndicator = booleanPreference("guide-indicator-new", false)
|
||||
val showPremiereIndicator = booleanPreference("guide-indicator-premiere", true)
|
||||
val showRepeatIndicator = booleanPreference("guide-indicator-repeat", false)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jellyfin.androidtv.preference
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import kotlin.collections.set
|
||||
|
||||
@@ -19,7 +20,7 @@ class PreferencesRepository(
|
||||
libraryPreferences[preferencesId] = store
|
||||
|
||||
// FIXME: Make [getLibraryPreferences] suspended when usages are converted to Kotlin
|
||||
if (store.shouldUpdate) store.updateBlocking()
|
||||
if (store.shouldUpdate) runBlocking { store.update() }
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@ package org.jellyfin.androidtv.preference
|
||||
|
||||
import android.content.Context
|
||||
import org.jellyfin.androidtv.preference.constant.PreferredVideoPlayer
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.booleanPreference
|
||||
import org.jellyfin.preference.enumPreference
|
||||
import org.jellyfin.preference.store.SharedPreferenceStore
|
||||
import org.jellyfin.preference.stringPreference
|
||||
|
||||
/**
|
||||
* System preferences are not possible to modify by the user.
|
||||
@@ -19,48 +21,48 @@ class SystemPreferences(context: Context) : SharedPreferenceStore(
|
||||
/**
|
||||
* Stores the channel that was active before leaving the app
|
||||
*/
|
||||
val liveTvLastChannel = Preference.string("sys_pref_last_tv_channel", "")
|
||||
val liveTvLastChannel = stringPreference("sys_pref_last_tv_channel", "")
|
||||
|
||||
/**
|
||||
* Also stores the channel that was active before leaving the app I think
|
||||
*/
|
||||
val liveTvPrevChannel = Preference.string("sys_pref_prev_tv_channel", "")
|
||||
val liveTvPrevChannel = stringPreference("sys_pref_prev_tv_channel", "")
|
||||
|
||||
// Live TV - Guide Filters
|
||||
/**
|
||||
* Stores whether the kids filter is active in the channel guide or not
|
||||
*/
|
||||
val liveTvGuideFilterKids = Preference.boolean("guide_filter_kids", false)
|
||||
val liveTvGuideFilterKids = booleanPreference("guide_filter_kids", false)
|
||||
|
||||
/**
|
||||
* Stores whether the movies filter is active in the channel guide or not
|
||||
*/
|
||||
val liveTvGuideFilterMovies = Preference.boolean("guide_filter_movies", false)
|
||||
val liveTvGuideFilterMovies = booleanPreference("guide_filter_movies", false)
|
||||
|
||||
/**
|
||||
* Stores whether the news filter is active in the channel guide or not
|
||||
*/
|
||||
val liveTvGuideFilterNews = Preference.boolean("guide_filter_news", false)
|
||||
val liveTvGuideFilterNews = booleanPreference("guide_filter_news", false)
|
||||
|
||||
/**
|
||||
* Stores whether the premiere filter is active in the channel guide or not
|
||||
*/
|
||||
val liveTvGuideFilterPremiere = Preference.boolean("guide_filter_premiere", false)
|
||||
val liveTvGuideFilterPremiere = booleanPreference("guide_filter_premiere", false)
|
||||
|
||||
/**
|
||||
* Stores whether the series filter is active in the channel guide or not
|
||||
*/
|
||||
val liveTvGuideFilterSeries = Preference.boolean("guide_filter_series", false)
|
||||
val liveTvGuideFilterSeries = booleanPreference("guide_filter_series", false)
|
||||
|
||||
/**
|
||||
* Stores whether the sports filter is active in the channel guide or not
|
||||
*/
|
||||
val liveTvGuideFilterSports = Preference.boolean("guide_filter_sports", false)
|
||||
val liveTvGuideFilterSports = booleanPreference("guide_filter_sports", false)
|
||||
|
||||
// Other persistent variables
|
||||
/**
|
||||
* Chosen player for play with button. Changes every time user chooses a player with "play with" button.
|
||||
*/
|
||||
var chosenPlayer = Preference.enum("chosen_player", PreferredVideoPlayer.VLC)
|
||||
var chosenPlayer = enumPreference("chosen_player", PreferredVideoPlayer.VLC)
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,12 @@ import org.jellyfin.androidtv.preference.constant.RatingType
|
||||
import org.jellyfin.androidtv.preference.constant.WatchedIndicatorBehavior
|
||||
import org.jellyfin.androidtv.preference.constant.defaultAudioBehavior
|
||||
import org.jellyfin.androidtv.util.DeviceUtils
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.booleanPreference
|
||||
import org.jellyfin.preference.enumPreference
|
||||
import org.jellyfin.preference.intPreference
|
||||
import org.jellyfin.preference.migration.putEnum
|
||||
import org.jellyfin.preference.store.SharedPreferenceStore
|
||||
import org.jellyfin.preference.stringPreference
|
||||
|
||||
/**
|
||||
* User preferences are configurable by the user and change behavior of the application.
|
||||
@@ -36,170 +39,170 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
|
||||
/**
|
||||
* Select the app theme
|
||||
*/
|
||||
var appTheme = Preference.enum("app_theme", AppTheme.DARK)
|
||||
var appTheme = enumPreference("app_theme", AppTheme.DARK)
|
||||
|
||||
/**
|
||||
* Enable background images while browsing
|
||||
*/
|
||||
var backdropEnabled = Preference.boolean("pref_show_backdrop", true)
|
||||
var backdropEnabled = booleanPreference("pref_show_backdrop", true)
|
||||
|
||||
/**
|
||||
* Show premieres on home screen
|
||||
*/
|
||||
var premieresEnabled = Preference.boolean("pref_enable_premieres", false)
|
||||
var premieresEnabled = booleanPreference("pref_enable_premieres", false)
|
||||
|
||||
/**
|
||||
* Show a little notification to celebrate a set of holidays
|
||||
*/
|
||||
var seasonalGreetingsEnabled = Preference.boolean("pref_enable_themes", true)
|
||||
var seasonalGreetingsEnabled = booleanPreference("pref_enable_themes", true)
|
||||
|
||||
/* Playback - General*/
|
||||
/**
|
||||
* Maximum bitrate in megabit for playback. A value of [MAX_BITRATE_AUTO] is used when
|
||||
* the bitrate should be automatically detected.
|
||||
*/
|
||||
var maxBitrate = Preference.string("pref_max_bitrate", "100")
|
||||
var maxBitrate = stringPreference("pref_max_bitrate", "100")
|
||||
|
||||
/**
|
||||
* Auto-play next item
|
||||
*/
|
||||
var mediaQueuingEnabled = Preference.boolean("pref_enable_tv_queuing", true)
|
||||
var mediaQueuingEnabled = booleanPreference("pref_enable_tv_queuing", true)
|
||||
|
||||
/**
|
||||
* Enable the next up screen or not
|
||||
*/
|
||||
var nextUpBehavior = Preference.enum("next_up_behavior", NextUpBehavior.EXTENDED)
|
||||
var nextUpBehavior = enumPreference("next_up_behavior", NextUpBehavior.EXTENDED)
|
||||
|
||||
/**
|
||||
* Next up timeout before playing next item
|
||||
* Stored in milliseconds
|
||||
*/
|
||||
var nextUpTimeout = Preference.int("next_up_timeout", 1000 * 7)
|
||||
var nextUpTimeout = intPreference("next_up_timeout", 1000 * 7)
|
||||
|
||||
/**
|
||||
* Duration in seconds to subtract from resume time
|
||||
*/
|
||||
var resumeSubtractDuration = Preference.string("pref_resume_preroll", "0")
|
||||
var resumeSubtractDuration = stringPreference("pref_resume_preroll", "0")
|
||||
|
||||
/**
|
||||
* Enable cinema mode
|
||||
*/
|
||||
var cinemaModeEnabled = Preference.boolean("pref_enable_cinema_mode", true)
|
||||
var cinemaModeEnabled = booleanPreference("pref_enable_cinema_mode", true)
|
||||
|
||||
/* Playback - Video */
|
||||
/**
|
||||
* Preferred video player.
|
||||
*/
|
||||
var videoPlayer = Preference.enum("video_player", PreferredVideoPlayer.EXOPLAYER)
|
||||
var videoPlayer = enumPreference("video_player", PreferredVideoPlayer.EXOPLAYER)
|
||||
|
||||
/**
|
||||
* Enable refresh rate switching when device supports it
|
||||
*/
|
||||
var refreshRateSwitchingEnabled = Preference.boolean("pref_refresh_switching", false)
|
||||
var refreshRateSwitchingEnabled = booleanPreference("pref_refresh_switching", false)
|
||||
|
||||
/**
|
||||
* Send a path instead to the external player
|
||||
*/
|
||||
var externalVideoPlayerSendPath = Preference.boolean("pref_send_path_external", false)
|
||||
var externalVideoPlayerSendPath = booleanPreference("pref_send_path_external", false)
|
||||
|
||||
/* Playback - Audio related */
|
||||
/**
|
||||
* Preferred behavior for audio streaming.
|
||||
*/
|
||||
var audioBehaviour = Preference.enum("audio_behavior", defaultAudioBehavior)
|
||||
var audioBehaviour = enumPreference("audio_behavior", defaultAudioBehavior)
|
||||
|
||||
/**
|
||||
* Enable DTS
|
||||
*/
|
||||
var dtsEnabled = Preference.boolean("pref_bitstream_dts", false)
|
||||
var dtsEnabled = booleanPreference("pref_bitstream_dts", false)
|
||||
|
||||
/**
|
||||
* Enable AC3
|
||||
*/
|
||||
var ac3Enabled = Preference.boolean("pref_bitstream_ac3", !DeviceUtils.isFireTvStickGen1())
|
||||
var ac3Enabled = booleanPreference("pref_bitstream_ac3", !DeviceUtils.isFireTvStickGen1())
|
||||
|
||||
/**
|
||||
* Default audio delay in milliseconds for libVLC
|
||||
*/
|
||||
var libVLCAudioDelay = Preference.int("libvlc_audio_delay", 0)
|
||||
var libVLCAudioDelay = intPreference("libvlc_audio_delay", 0)
|
||||
|
||||
/* Live TV */
|
||||
/**
|
||||
* Use direct play
|
||||
*/
|
||||
var liveTvDirectPlayEnabled = Preference.boolean("pref_live_direct", true)
|
||||
var liveTvDirectPlayEnabled = booleanPreference("pref_live_direct", true)
|
||||
|
||||
/**
|
||||
* Preferred video player for live TV
|
||||
*/
|
||||
var liveTvVideoPlayer = Preference.enum("live_tv_video_player", PreferredVideoPlayer.AUTO)
|
||||
var liveTvVideoPlayer = enumPreference("live_tv_video_player", PreferredVideoPlayer.AUTO)
|
||||
|
||||
/**
|
||||
* Shortcut used for changing the audio track
|
||||
*/
|
||||
var shortcutAudioTrack = Preference.int("shortcut_audio_track", KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK)
|
||||
var shortcutAudioTrack = intPreference("shortcut_audio_track", KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK)
|
||||
|
||||
/**
|
||||
* Shortcut used for changing the subtitle track
|
||||
*/
|
||||
var shortcutSubtitleTrack = Preference.int("shortcut_subtitle_track", KeyEvent.KEYCODE_CAPTIONS)
|
||||
var shortcutSubtitleTrack = intPreference("shortcut_subtitle_track", KeyEvent.KEYCODE_CAPTIONS)
|
||||
|
||||
/* Developer options */
|
||||
/**
|
||||
* Show additional debug information
|
||||
*/
|
||||
var debuggingEnabled = Preference.boolean("pref_enable_debug", false)
|
||||
var debuggingEnabled = booleanPreference("pref_enable_debug", false)
|
||||
|
||||
/**
|
||||
* Use playback rewrite module
|
||||
*/
|
||||
var playbackRewriteEnabled = Preference.boolean("playback_new", false)
|
||||
var playbackRewriteEnabled = booleanPreference("playback_new", false)
|
||||
|
||||
/* ACRA */
|
||||
/**
|
||||
* Enable ACRA crash reporting
|
||||
*/
|
||||
var acraEnabled = Preference.boolean(ACRA.PREF_ENABLE_ACRA, true)
|
||||
var acraEnabled = booleanPreference(ACRA.PREF_ENABLE_ACRA, true)
|
||||
|
||||
/**
|
||||
* Never prompt to report crash logs
|
||||
*/
|
||||
var acraNoPrompt = Preference.boolean(ACRA.PREF_ALWAYS_ACCEPT, false)
|
||||
var acraNoPrompt = booleanPreference(ACRA.PREF_ALWAYS_ACCEPT, false)
|
||||
|
||||
/**
|
||||
* Include system logs in crash reports
|
||||
*/
|
||||
var acraIncludeSystemLogs = Preference.boolean(ACRA.PREF_ENABLE_SYSTEM_LOGS, true)
|
||||
var acraIncludeSystemLogs = booleanPreference(ACRA.PREF_ENABLE_SYSTEM_LOGS, true)
|
||||
|
||||
/**
|
||||
* When to show the clock.
|
||||
*/
|
||||
var clockBehavior = Preference.enum("pref_clock_behavior", ClockBehavior.ALWAYS)
|
||||
var clockBehavior = enumPreference("pref_clock_behavior", ClockBehavior.ALWAYS)
|
||||
|
||||
/**
|
||||
* Set which ratings provider should show on MyImageCardViews
|
||||
*/
|
||||
var defaultRatingType = Preference.enum("pref_rating_type", RatingType.RATING_TOMATOES)
|
||||
var defaultRatingType = enumPreference("pref_rating_type", RatingType.RATING_TOMATOES)
|
||||
|
||||
/**
|
||||
* Set when watched indicators should show on MyImageCardViews
|
||||
*/
|
||||
var watchedIndicatorBehavior = Preference.enum("pref_watched_indicator_behavior", WatchedIndicatorBehavior.ALWAYS)
|
||||
var watchedIndicatorBehavior = enumPreference("pref_watched_indicator_behavior", WatchedIndicatorBehavior.ALWAYS)
|
||||
|
||||
/**
|
||||
* Enable series thumbnails in home screen rows
|
||||
*/
|
||||
var seriesThumbnailsEnabled = Preference.boolean("pref_enable_series_thumbnails", true)
|
||||
var seriesThumbnailsEnabled = booleanPreference("pref_enable_series_thumbnails", true)
|
||||
|
||||
/**
|
||||
* Enable subtitles background
|
||||
*/
|
||||
var subtitlesBackgroundEnabled = Preference.boolean("subtitles_background_enabled", true)
|
||||
var subtitlesBackgroundEnabled = booleanPreference("subtitles_background_enabled", true)
|
||||
|
||||
/**
|
||||
* Set default subtitles font size
|
||||
*/
|
||||
var defaultSubtitlesSize = Preference.int("subtitles_size", 28)
|
||||
var defaultSubtitlesSize = intPreference("subtitles_size", 28)
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@@ -2,7 +2,8 @@ package org.jellyfin.androidtv.preference
|
||||
|
||||
import org.jellyfin.androidtv.constant.HomeSectionType
|
||||
import org.jellyfin.androidtv.preference.store.DisplayPreferencesStore
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.enumPreference
|
||||
import org.jellyfin.preference.intPreference
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
|
||||
class UserSettingPreferences(
|
||||
@@ -13,16 +14,16 @@ class UserSettingPreferences(
|
||||
app = "emby",
|
||||
) {
|
||||
companion object {
|
||||
val skipBackLength = Preference.int("skipBackLength", 10000)
|
||||
val skipForwardLength = Preference.int("skipForwardLength", 30000)
|
||||
val skipBackLength = intPreference("skipBackLength", 10000)
|
||||
val skipForwardLength = intPreference("skipForwardLength", 30000)
|
||||
|
||||
val homesection0 = Preference.enum("homesection0", HomeSectionType.LIBRARY_TILES_SMALL)
|
||||
val homesection1 = Preference.enum("homesection1", HomeSectionType.RESUME)
|
||||
val homesection2 = Preference.enum("homesection2", HomeSectionType.RESUME_AUDIO)
|
||||
val homesection3 = Preference.enum("homesection3", HomeSectionType.RESUME_BOOK)
|
||||
val homesection4 = Preference.enum("homesection4", HomeSectionType.LIVE_TV)
|
||||
val homesection5 = Preference.enum("homesection5", HomeSectionType.NEXT_UP)
|
||||
val homesection6 = Preference.enum("homesection6", HomeSectionType.LATEST_MEDIA)
|
||||
val homesection0 = enumPreference("homesection0", HomeSectionType.LIBRARY_TILES_SMALL)
|
||||
val homesection1 = enumPreference("homesection1", HomeSectionType.RESUME)
|
||||
val homesection2 = enumPreference("homesection2", HomeSectionType.RESUME_AUDIO)
|
||||
val homesection3 = enumPreference("homesection3", HomeSectionType.RESUME_BOOK)
|
||||
val homesection4 = enumPreference("homesection4", HomeSectionType.LIVE_TV)
|
||||
val homesection5 = enumPreference("homesection5", HomeSectionType.NEXT_UP)
|
||||
val homesection6 = enumPreference("homesection6", HomeSectionType.LATEST_MEDIA)
|
||||
}
|
||||
|
||||
val homesections
|
||||
|
||||
+7
-1
@@ -2,6 +2,7 @@ package org.jellyfin.androidtv.preference.store
|
||||
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.PreferenceEnum
|
||||
import org.jellyfin.preference.migration.MigrationContext
|
||||
import org.jellyfin.preference.store.AsyncPreferenceStore
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.exception.ApiClientException
|
||||
@@ -11,11 +12,12 @@ import org.jellyfin.sdk.model.api.ScrollDirection
|
||||
import org.jellyfin.sdk.model.api.SortOrder
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
abstract class DisplayPreferencesStore(
|
||||
protected var displayPreferencesId: String,
|
||||
protected var app: String = "jellyfin-androidtv",
|
||||
private val api: ApiClient,
|
||||
) : AsyncPreferenceStore() {
|
||||
) : AsyncPreferenceStore<Unit, Unit>() {
|
||||
private var displayPreferencesDto: DisplayPreferencesDto? = null
|
||||
private var cachedPreferences: MutableMap<String, String?> = mutableMapOf()
|
||||
override val shouldUpdate: Boolean
|
||||
@@ -122,6 +124,10 @@ abstract class DisplayPreferencesStore(
|
||||
}
|
||||
)
|
||||
|
||||
override fun runMigrations(body: MigrationContext<Unit, Unit>.() -> Unit) {
|
||||
TODO("The DisplayPreferencesStore does not support migrations")
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty [DisplayPreferencesDto] with default values.
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,7 @@ class DisplayPreferencesScreen : OptionsFragment() {
|
||||
private val preferencesId by lazy { requireArguments().getString(ARG_PREFERENCES_ID) }
|
||||
private val allowViewSelection by lazy { requireArguments().getBoolean(ARG_ALLOW_VIEW_SELECTION) }
|
||||
|
||||
override val stores: Array<PreferenceStore>
|
||||
override val stores: Array<PreferenceStore<*, *>>
|
||||
get() = arrayOf(libraryPreferences)
|
||||
|
||||
override val screen by optionsScreen {
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.jellyfin.androidtv.ui.presentation.HorizontalGridPresenter;
|
||||
import org.jellyfin.androidtv.ui.shared.BaseActivity;
|
||||
import org.jellyfin.androidtv.ui.shared.KeyListener;
|
||||
import org.jellyfin.androidtv.ui.shared.MessageListener;
|
||||
import org.jellyfin.androidtv.util.CoroutineUtils;
|
||||
import org.jellyfin.androidtv.util.KeyProcessor;
|
||||
import org.jellyfin.androidtv.util.Utils;
|
||||
import org.jellyfin.apiclient.interaction.EmptyResponse;
|
||||
@@ -348,7 +349,7 @@ public class StdGridFragment extends GridFragment {
|
||||
libraryPreferences.set(LibraryPreferences.Companion.getFilterUnwatchedOnly(), mGridAdapter.getFilters().isUnwatchedOnly());
|
||||
libraryPreferences.set(LibraryPreferences.Companion.getSortBy(), mGridAdapter.getSortBy());
|
||||
libraryPreferences.set(LibraryPreferences.Companion.getSortOrder(), getSortOption(mGridAdapter.getSortBy()).order);
|
||||
libraryPreferences.commitBlocking();
|
||||
CoroutineUtils.runBlocking((coroutineScope, continuation) -> libraryPreferences.commit(continuation));
|
||||
}
|
||||
|
||||
protected void addTools() {
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.jellyfin.androidtv.ui.ProgramGridCell;
|
||||
import org.jellyfin.androidtv.ui.ScrollViewListener;
|
||||
import org.jellyfin.androidtv.ui.shared.BaseActivity;
|
||||
import org.jellyfin.androidtv.ui.shared.MessageListener;
|
||||
import org.jellyfin.androidtv.util.CoroutineUtils;
|
||||
import org.jellyfin.androidtv.util.ImageUtils;
|
||||
import org.jellyfin.androidtv.util.InfoLayoutHelper;
|
||||
import org.jellyfin.androidtv.util.TimeUtils;
|
||||
@@ -595,7 +596,7 @@ public class LiveTvGuideActivity extends BaseActivity implements LiveTvGuide {
|
||||
prefs.set(LiveTvPreferences.Companion.getShowRepeatIndicator(), mRepeat.isChecked());
|
||||
prefs.set(LiveTvPreferences.Companion.getChannelOrder(), mCurrentSort);
|
||||
prefs.set(LiveTvPreferences.Companion.getShowLiveIndicator(), mLive.isChecked());
|
||||
prefs.commitBlocking();
|
||||
CoroutineUtils.runBlocking((coroutineScope, continuation) -> prefs.commit(continuation));
|
||||
|
||||
TvManager.clearCache();
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ abstract class OptionsFragment : LeanbackPreferenceFragmentCompat() {
|
||||
* Preference stores used in current screen. Fragment will automatically call the update and
|
||||
* commit functions for all async stores.
|
||||
*/
|
||||
protected open val stores: Array<PreferenceStore> = emptyArray()
|
||||
protected open val stores: Array<PreferenceStore<*, *>> = emptyArray()
|
||||
|
||||
// Used to not build twice during onCreate()
|
||||
private var skippedInitialResume = false
|
||||
@@ -31,8 +31,8 @@ abstract class OptionsFragment : LeanbackPreferenceFragmentCompat() {
|
||||
// Refresh all data in async stores
|
||||
runBlocking {
|
||||
stores
|
||||
.filterIsInstance<AsyncPreferenceStore>()
|
||||
.map { async { it.update() } }
|
||||
.filterIsInstance<AsyncPreferenceStore<*, *>>()
|
||||
.map { async { it.update() } }
|
||||
.awaitAll()
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ abstract class OptionsFragment : LeanbackPreferenceFragmentCompat() {
|
||||
// Save all data in async stores
|
||||
runBlocking {
|
||||
stores
|
||||
.filterIsInstance<AsyncPreferenceStore>()
|
||||
.map { async { it.commit() } }
|
||||
.filterIsInstance<AsyncPreferenceStore<*, *>>()
|
||||
.map { async { it.commit() } }
|
||||
.awaitAll()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class OptionsItemEnum<T : Enum<T>>(
|
||||
|
||||
// Add exact copy of the OptionsItemMutable.bind function so the correct
|
||||
// store getter and setter will be used.
|
||||
override fun bind(store: PreferenceStore, preference: Preference<T>) = bind {
|
||||
override fun bind(store: PreferenceStore<*, *>, preference: Preference<T>) = bind {
|
||||
get { store[preference] }
|
||||
set { store[preference] = it }
|
||||
default { store.getDefaultValue(preference) }
|
||||
|
||||
@@ -11,7 +11,7 @@ abstract class OptionsItemMutable<T : Any> : OptionsItem {
|
||||
protected var dependencyCheckFun: () -> Boolean = { true }
|
||||
protected lateinit var binder: OptionsBinder<T>
|
||||
|
||||
open fun bind(store: PreferenceStore, preference: Preference<T>) = bind {
|
||||
open fun bind(store: PreferenceStore<*, *>, preference: Preference<T>) = bind {
|
||||
get { store[preference] }
|
||||
set { store[preference] = it }
|
||||
default { store.getDefaultValue(preference) }
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import org.koin.android.ext.android.inject
|
||||
class HomePreferencesScreen : OptionsFragment() {
|
||||
private val userSettingPreferences: UserSettingPreferences by inject()
|
||||
|
||||
override val stores: Array<PreferenceStore>
|
||||
override val stores: Array<PreferenceStore<*, *>>
|
||||
get() = arrayOf(userSettingPreferences)
|
||||
|
||||
override val screen by optionsScreen {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
@file:JvmName("CoroutineUtils")
|
||||
package org.jellyfin.androidtv.util
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
fun <T: Any> runBlocking(block: suspend CoroutineScope.() -> T) = kotlinx.coroutines.runBlocking {
|
||||
block()
|
||||
}
|
||||
@@ -6,12 +6,12 @@ data class Preference<T : Any>(
|
||||
val key: String,
|
||||
val defaultValue: T,
|
||||
val type: KClass<T>
|
||||
) {
|
||||
companion object {
|
||||
fun int(key: String, defaultValue: Int) = Preference(key, defaultValue, Int::class)
|
||||
fun long(key: String, defaultValue: Long) = Preference(key, defaultValue, Long::class)
|
||||
fun boolean(key: String, defaultValue: Boolean) = Preference(key, defaultValue, Boolean::class)
|
||||
fun string(key: String, defaultValue: String) = Preference(key, defaultValue, String::class)
|
||||
inline fun <reified T : Any> enum(key: String, defaultValue: T) = Preference(key, defaultValue, T::class)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
fun intPreference(key: String, defaultValue: Int) = Preference(key, defaultValue, Int::class)
|
||||
fun longPreference(key: String, defaultValue: Long) = Preference(key, defaultValue, Long::class)
|
||||
fun booleanPreference(key: String, defaultValue: Boolean) = Preference(key, defaultValue, Boolean::class)
|
||||
fun stringPreference(key: String, defaultValue: String) = Preference(key, defaultValue, String::class)
|
||||
fun <T : Any> enumPreference(key: String, defaultValue: T, type: KClass<T>) = Preference(key, defaultValue, type)
|
||||
|
||||
inline fun <reified T : Any> enumPreference(key: String, defaultValue: T) = enumPreference(key, defaultValue, T::class)
|
||||
@@ -2,8 +2,6 @@ package org.jellyfin.preference.migration
|
||||
|
||||
import android.content.SharedPreferences
|
||||
|
||||
typealias MigrationEditor = SharedPreferences.Editor
|
||||
|
||||
fun <T : Enum<T>> MigrationEditor.putEnum(key: String, value: T) {
|
||||
fun <T : Enum<T>> SharedPreferences.Editor.putEnum(key: String, value: T) {
|
||||
putString(key, value.toString())
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.jellyfin.preference.store
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
abstract class AsyncPreferenceStore : PreferenceStore() {
|
||||
abstract class AsyncPreferenceStore<ME, MV> : PreferenceStore<ME, MV>() {
|
||||
abstract val shouldUpdate: Boolean
|
||||
|
||||
/**
|
||||
@@ -34,21 +32,11 @@ abstract class AsyncPreferenceStore : PreferenceStore() {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
suspend fun transaction(body: AsyncPreferenceStore.() -> Unit): Boolean {
|
||||
suspend fun transaction(body: AsyncPreferenceStore<ME, MV>.() -> Unit): Boolean {
|
||||
if (shouldUpdate) update()
|
||||
|
||||
body()
|
||||
|
||||
return commit()
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatability with old Java classes.
|
||||
*/
|
||||
fun updateBlocking() = runBlocking { update() }
|
||||
|
||||
/**
|
||||
* Compatability with old Java classes.
|
||||
*/
|
||||
fun commitBlocking() = runBlocking { commit() }
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jellyfin.preference.store
|
||||
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.migration.MigrationContext
|
||||
|
||||
/**
|
||||
* Abstract class defining the required functions for a preference store.
|
||||
@@ -8,7 +9,8 @@ import org.jellyfin.preference.Preference
|
||||
* This implements shared functionality (such as Enum handling), whilst allowing for
|
||||
* different backing stores.
|
||||
*/
|
||||
abstract class PreferenceStore {
|
||||
@Suppress("TooManyFunctions")
|
||||
abstract class PreferenceStore<ME, MV> {
|
||||
// val value = store[Preference.x]
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
operator fun <T : Any> get(preference: Preference<T>): T =
|
||||
@@ -62,4 +64,7 @@ abstract class PreferenceStore {
|
||||
protected abstract fun <T : Enum<T>> getEnum(preference: Preference<T>): T
|
||||
|
||||
protected abstract fun <V : Enum<V>> setEnum(preference: Preference<*>, value: Enum<V>)
|
||||
|
||||
// Migrations
|
||||
protected abstract fun runMigrations(body: MigrationContext<ME, MV>.() -> Unit)
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package org.jellyfin.preference.store
|
||||
import android.content.SharedPreferences
|
||||
import org.jellyfin.preference.Preference
|
||||
import org.jellyfin.preference.PreferenceEnum
|
||||
import org.jellyfin.preference.intPreference
|
||||
import org.jellyfin.preference.migration.MigrationContext
|
||||
import org.jellyfin.preference.migration.MigrationEditor
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
@@ -26,12 +26,13 @@ import timber.log.Timber
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@Suppress("TooManyFunctions")
|
||||
abstract class SharedPreferenceStore(
|
||||
/**
|
||||
* SharedPreferences to read from and write to
|
||||
*/
|
||||
protected val sharedPreferences: SharedPreferences
|
||||
) : PreferenceStore() {
|
||||
) : PreferenceStore<SharedPreferences.Editor, SharedPreferences>() {
|
||||
// Internal helpers
|
||||
private fun transaction(body: SharedPreferences.Editor.() -> Unit) {
|
||||
val editor = sharedPreferences.edit()
|
||||
@@ -79,8 +80,8 @@ abstract class SharedPreferenceStore(
|
||||
}
|
||||
|
||||
// Migrations
|
||||
protected fun runMigrations(body: MigrationContext<MigrationEditor, SharedPreferences>.() -> Unit) {
|
||||
val context = MigrationContext<MigrationEditor, SharedPreferences>()
|
||||
override fun runMigrations(body: MigrationContext<SharedPreferences.Editor, SharedPreferences>.() -> Unit) {
|
||||
val context = MigrationContext<SharedPreferences.Editor, SharedPreferences>()
|
||||
context.body()
|
||||
|
||||
this[VERSION] = context.applyMigrations(this[VERSION]) { migration ->
|
||||
@@ -95,6 +96,6 @@ abstract class SharedPreferenceStore(
|
||||
/**
|
||||
* Version of the preference store. Used for migration.
|
||||
*/
|
||||
val VERSION = Preference.int("store_version", -1)
|
||||
val VERSION = intPreference("store_version", -1)
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package org.jellyfin.preference
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import org.jellyfin.preference.migration.MigrationContext
|
||||
import org.jellyfin.preference.store.PreferenceStore
|
||||
|
||||
/**
|
||||
@@ -17,14 +18,14 @@ class PreferenceStoreTests : FunSpec({
|
||||
}
|
||||
|
||||
test("Reading and writing primitives works correctly") {
|
||||
verifySimpleType(1, Preference.int("key", 0))
|
||||
verifySimpleType(1L, Preference.long("key", 0L))
|
||||
verifySimpleType(true, Preference.boolean("key", false))
|
||||
verifySimpleType("string", Preference.string("key", ""))
|
||||
verifySimpleType(1, intPreference("key", 0))
|
||||
verifySimpleType(1L, longPreference("key", 0L))
|
||||
verifySimpleType(true, booleanPreference("key", false))
|
||||
verifySimpleType("string", stringPreference("key", ""))
|
||||
}
|
||||
|
||||
test("Reading and writing enums works correctly") {
|
||||
val pref = Preference.enum("key", TestEnum.NOT_SET)
|
||||
val pref = enumPreference("key", TestEnum.NOT_SET)
|
||||
val expectedVal = TestEnum.SET
|
||||
val instance = TestStub()
|
||||
instance[pref] = expectedVal
|
||||
@@ -33,7 +34,7 @@ class PreferenceStoreTests : FunSpec({
|
||||
}
|
||||
})
|
||||
|
||||
private class TestStub : PreferenceStore() {
|
||||
private class TestStub : PreferenceStore<Unit, Unit>() {
|
||||
var key: String? = null
|
||||
private var int: Int? = null
|
||||
private var long: Long? = null
|
||||
@@ -79,6 +80,10 @@ private class TestStub : PreferenceStore() {
|
||||
override fun <T : Any> delete(preference: Preference<T>) {
|
||||
throw NotImplementedError("Not required for tests")
|
||||
}
|
||||
|
||||
override fun runMigrations(body: MigrationContext<Unit, Unit>.() -> Unit) {
|
||||
throw NotImplementedError("Not required for tests")
|
||||
}
|
||||
}
|
||||
|
||||
private enum class TestEnum { NOT_SET, SET }
|
||||
Reference in new issue
Block a user