260 lines
12 KiB
Swift
260 lines
12 KiB
Swift
//
|
|
// Swiftfin is subject to the terms of the Mozilla Public
|
|
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
//
|
|
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
|
|
//
|
|
|
|
import Defaults
|
|
import Factory
|
|
import Foundation
|
|
import SwiftUI
|
|
import UIKit
|
|
|
|
// TODO: organize
|
|
// TODO: all user settings could be moved to `StoredValues`?
|
|
|
|
// Note: Only use Defaults for basic single-value settings.
|
|
// For larger data types and collections, use `StoredValue` instead.
|
|
|
|
// MARK: Suites
|
|
|
|
extension UserDefaults {
|
|
|
|
// MARK: App
|
|
|
|
/// Settings that should apply to the app
|
|
static let appSuite = UserDefaults(suiteName: "swiftfinApp")!
|
|
|
|
// MARK: Usser
|
|
|
|
// TODO: the Factory resolver cannot be used because it would cause freezes, but
|
|
// the Defaults value should always be in sync with the latest user and what
|
|
// views properly expect. However, this feels like a hack and should be changed?
|
|
static var currentUserSuite: UserDefaults {
|
|
userSuite(id: Defaults[.lastSignedInUserID] ?? "default")
|
|
}
|
|
|
|
static func userSuite(id: String) -> UserDefaults {
|
|
UserDefaults(suiteName: id)!
|
|
}
|
|
}
|
|
|
|
private extension Defaults.Keys {
|
|
|
|
static func AppKey<Value: Defaults.Serializable>(_ name: String) -> Key<Value?> {
|
|
Key(name, suite: .appSuite)
|
|
}
|
|
|
|
static func AppKey<Value: Defaults.Serializable>(_ name: String, default: Value) -> Key<Value> {
|
|
Key(name, default: `default`, suite: .appSuite)
|
|
}
|
|
|
|
static func UserKey<Value: Defaults.Serializable>(_ name: String, default: Value) -> Key<Value> {
|
|
Key(name, default: `default`, suite: .currentUserSuite)
|
|
}
|
|
}
|
|
|
|
// MARK: App
|
|
|
|
extension Defaults.Keys {
|
|
|
|
/// The _real_ accent color key to be used.
|
|
///
|
|
/// This is set externally whenever the app or user accent colors change,
|
|
/// depending on the current app state.
|
|
static var accentColor: Key<Color> = AppKey("accentColor", default: .jellyfinPurple)
|
|
|
|
/// The _real_ appearance key to be used.
|
|
///
|
|
/// This is set externally whenever the app or user appearances change,
|
|
/// depending on the current app state.
|
|
static let appearance: Key<AppAppearance> = AppKey("appearance", default: .system)
|
|
|
|
/// The accent color default for non-user contexts.
|
|
/// Only use for `set`, use `accentColor` for `get`.
|
|
static let appAccentColor: Key<Color> = AppKey("appAccentColor", default: .jellyfinPurple)
|
|
|
|
/// The appearance default for non-user contexts.
|
|
/// /// Only use for `set`, use `appearance` for `get`.
|
|
static let appAppearance: Key<AppAppearance> = AppKey("appAppearance", default: .system)
|
|
|
|
static let backgroundSignOutInterval: Key<TimeInterval> = AppKey("backgroundSignOutInterval", default: 3600)
|
|
static let backgroundTimeStamp: Key<Date> = AppKey("backgroundTimeStamp", default: Date.now)
|
|
static let lastSignedInUserID: Key<String?> = AppKey("lastSignedInUserID")
|
|
|
|
static let selectUserDisplayType: Key<LibraryDisplayType> = AppKey("selectUserDisplayType", default: .grid)
|
|
static let selectUserServerSelection: Key<SelectUserServerSelection> = AppKey("selectUserServerSelection", default: .all)
|
|
static let selectUserAllServersSplashscreen: Key<SelectUserServerSelection> = AppKey("selectUserAllServersSplashscreen", default: .all)
|
|
static let selectUserUseSplashscreen: Key<Bool> = AppKey("selectUserUseSplashscreen", default: true)
|
|
|
|
static let signOutOnBackground: Key<Bool> = AppKey("signOutOnBackground", default: true)
|
|
static let signOutOnClose: Key<Bool> = AppKey("signOutOnClose", default: false)
|
|
}
|
|
|
|
// MARK: User
|
|
|
|
extension Defaults.Keys {
|
|
|
|
/// The accent color default for user contexts.
|
|
/// Only use for `set`, use `accentColor` for `get`.
|
|
static var userAccentColor: Key<Color> { UserKey("userAccentColor", default: .jellyfinPurple) }
|
|
|
|
/// The appearance default for user contexts.
|
|
/// /// Only use for `set`, use `appearance` for `get`.
|
|
static var userAppearance: Key<AppAppearance> { UserKey("userAppearance", default: .system) }
|
|
|
|
enum Customization {
|
|
|
|
static let itemViewType: Key<ItemViewType> = UserKey("itemViewType", default: .compactLogo)
|
|
|
|
static let showPosterLabels: Key<Bool> = UserKey("showPosterLabels", default: true)
|
|
static let nextUpPosterType: Key<PosterDisplayType> = UserKey("nextUpPosterType", default: .portrait)
|
|
static let recentlyAddedPosterType: Key<PosterDisplayType> = UserKey("recentlyAddedPosterType", default: .portrait)
|
|
static let showRecentlyAdded: Key<Bool> = UserKey("showRecentlyAdded", default: true)
|
|
static let latestInLibraryPosterType: Key<PosterDisplayType> = UserKey("latestInLibraryPosterType", default: .portrait)
|
|
static let shouldShowMissingSeasons: Key<Bool> = UserKey("shouldShowMissingSeasons", default: true)
|
|
static let shouldShowMissingEpisodes: Key<Bool> = UserKey("shouldShowMissingEpisodes", default: true)
|
|
static let similarPosterType: Key<PosterDisplayType> = UserKey("similarPosterType", default: .portrait)
|
|
|
|
// TODO: have search poster type by types of items if applicable
|
|
static let searchPosterType: Key<PosterDisplayType> = UserKey("searchPosterType", default: .portrait)
|
|
|
|
enum CinematicItemViewType {
|
|
|
|
static let usePrimaryImage: Key<Bool> = UserKey("cinematicItemViewTypeUsePrimaryImage", default: false)
|
|
}
|
|
|
|
enum Episodes {
|
|
|
|
static let useSeriesLandscapeBackdrop: Key<Bool> = UserKey("useSeriesBackdrop", default: true)
|
|
}
|
|
|
|
enum Indicators {
|
|
|
|
static let showFavorited: Key<Bool> = UserKey("showFavoritedIndicator", default: true)
|
|
static let showProgress: Key<Bool> = UserKey("showProgressIndicator", default: true)
|
|
static let showUnplayed: Key<Bool> = UserKey("showUnplayedIndicator", default: true)
|
|
static let showPlayed: Key<Bool> = UserKey("showPlayedIndicator", default: true)
|
|
}
|
|
|
|
enum Library {
|
|
|
|
static let cinematicBackground: Key<Bool> = UserKey("libraryCinematicBackground", default: true)
|
|
static let enabledDrawerFilters: Key<[ItemFilterType]> = UserKey(
|
|
"libraryEnabledDrawerFilters",
|
|
default: ItemFilterType.allCases
|
|
)
|
|
static let letterPickerEnabled: Key<Bool> = UserKey("letterPickerEnabled", default: false)
|
|
static let letterPickerOrientation: Key<LetterPickerOrientation> = .init(
|
|
"letterPickerOrientation", default: .trailing
|
|
)
|
|
static let displayType: Key<LibraryDisplayType> = UserKey("libraryViewType", default: .grid)
|
|
static let posterType: Key<PosterDisplayType> = UserKey("libraryPosterType", default: .portrait)
|
|
static let listColumnCount: Key<Int> = UserKey("listColumnCount", default: 1)
|
|
static let randomImage: Key<Bool> = UserKey("libraryRandomImage", default: true)
|
|
static let showFavorites: Key<Bool> = UserKey("libraryShowFavorites", default: true)
|
|
|
|
static let rememberLayout: Key<Bool> = UserKey("libraryRememberLayout", default: false)
|
|
static let rememberSort: Key<Bool> = UserKey("libraryRememberSort", default: false)
|
|
}
|
|
|
|
enum Search {
|
|
|
|
static let enabledDrawerFilters: Key<[ItemFilterType]> = UserKey(
|
|
"searchEnabledDrawerFilters",
|
|
default: ItemFilterType.allCases
|
|
)
|
|
}
|
|
}
|
|
|
|
enum VideoPlayer {
|
|
|
|
static let appMaximumBitrate: Key<PlaybackBitrate> = UserKey("appMaximumBitrate", default: .auto)
|
|
static let appMaximumBitrateTest: Key<PlaybackBitrateTestSize> = UserKey("appMaximumBitrateTest", default: .regular)
|
|
static let autoPlayEnabled: Key<Bool> = UserKey("autoPlayEnabled", default: true)
|
|
static let barActionButtons: Key<[VideoPlayerActionButton]> = UserKey(
|
|
"barActionButtons",
|
|
default: VideoPlayerActionButton.defaultBarActionButtons
|
|
)
|
|
static let jumpBackwardLength: Key<VideoPlayerJumpLength> = UserKey("jumpBackwardLength", default: .fifteen)
|
|
static let jumpForwardLength: Key<VideoPlayerJumpLength> = UserKey("jumpForwardLength", default: .fifteen)
|
|
static let menuActionButtons: Key<[VideoPlayerActionButton]> = UserKey(
|
|
"menuActionButtons",
|
|
default: VideoPlayerActionButton.defaultMenuActionButtons
|
|
)
|
|
static let resumeOffset: Key<Int> = UserKey("resumeOffset", default: 0)
|
|
static let showJumpButtons: Key<Bool> = UserKey("showJumpButtons", default: true)
|
|
static let videoPlayerType: Key<VideoPlayerType> = UserKey("videoPlayerType", default: .swiftfin)
|
|
|
|
enum Gesture {
|
|
|
|
static let horizontalPanGesture: Key<PanAction> = UserKey("videoPlayerHorizontalPanGesture", default: .none)
|
|
static let horizontalSwipeGesture: Key<SwipeAction> = UserKey("videoPlayerHorizontalSwipeGesture", default: .none)
|
|
static let longPressGesture: Key<LongPressAction> = UserKey("videoPlayerLongPressGesture", default: .gestureLock)
|
|
static let multiTapGesture: Key<MultiTapAction> = UserKey("videoPlayerMultiTapGesture", default: .none)
|
|
static let doubleTouchGesture: Key<DoubleTouchAction> = UserKey("videoPlayerDoubleTouchGesture", default: .none)
|
|
static let pinchGesture: Key<PinchAction> = UserKey("videoPlayerSwipeGesture", default: .aspectFill)
|
|
static let verticalPanGestureLeft: Key<PanAction> = UserKey("videoPlayerVerticalPanGestureLeft", default: .none)
|
|
static let verticalPanGestureRight: Key<PanAction> = UserKey("videoPlayerVerticalPanGestureRight", default: .none)
|
|
}
|
|
|
|
enum Overlay {
|
|
|
|
static let chapterSlider: Key<Bool> = UserKey("chapterSlider", default: true)
|
|
static let playbackButtonType: Key<PlaybackButtonType> = UserKey("videoPlayerPlaybackButtonLocation", default: .large)
|
|
static let sliderColor: Key<Color> = UserKey("sliderColor", default: Color.white)
|
|
static let sliderType: Key<SliderType> = UserKey("sliderType", default: .capsule)
|
|
|
|
// Timestamp
|
|
static let trailingTimestampType: Key<TrailingTimestampType> = UserKey("trailingTimestamp", default: .timeLeft)
|
|
static let showCurrentTimeWhileScrubbing: Key<Bool> = UserKey("showCurrentTimeWhileScrubbing", default: true)
|
|
static let timestampType: Key<TimestampType> = UserKey("timestampType", default: .split)
|
|
}
|
|
|
|
enum Subtitle {
|
|
|
|
static let subtitleColor: Key<Color> = UserKey("subtitleColor", default: .white)
|
|
static let subtitleFontName: Key<String> = UserKey("subtitleFontName", default: UIFont.systemFont(ofSize: 14).fontName)
|
|
static let subtitleSize: Key<Int> = UserKey("subtitleSize", default: 16)
|
|
}
|
|
|
|
enum Transition {
|
|
static let pauseOnBackground: Key<Bool> = UserKey("pauseOnBackground", default: false)
|
|
static let playOnActive: Key<Bool> = UserKey("playOnActive", default: false)
|
|
}
|
|
}
|
|
|
|
// Experimental settings
|
|
enum Experimental {
|
|
|
|
static let downloads: Key<Bool> = UserKey("experimentalDownloads", default: false)
|
|
static let forceDirectPlay: Key<Bool> = UserKey("forceDirectPlay", default: false)
|
|
static let liveTVForceDirectPlay: Key<Bool> = UserKey("liveTVForceDirectPlay", default: false)
|
|
}
|
|
|
|
// tvos specific
|
|
static let downActionShowsMenu: Key<Bool> = UserKey("downActionShowsMenu", default: true)
|
|
static let confirmClose: Key<Bool> = UserKey("confirmClose", default: false)
|
|
}
|
|
|
|
// MARK: Debug
|
|
|
|
#if DEBUG
|
|
|
|
extension UserDefaults {
|
|
|
|
static let debugSuite = UserDefaults(suiteName: "swiftfinstore-debug-defaults")!
|
|
}
|
|
|
|
extension Defaults.Keys {
|
|
|
|
static func DebugKey<Value: Defaults.Serializable>(_ name: String, default: Value) -> Key<Value> {
|
|
Key(name, default: `default`, suite: .appSuite)
|
|
}
|
|
|
|
static let sendProgressReports: Key<Bool> = DebugKey("sendProgressReports", default: true)
|
|
}
|
|
#endif
|