mirror of
https://github.com/jellyfin/Swiftfin.git
synced 2024-11-23 05:59:51 +00:00
Some More Cleanup, Reset User Settings (#1060)
This commit is contained in:
parent
66c26553ad
commit
8d6167c00b
@ -65,7 +65,7 @@ struct CaseIterablePicker<Element: CaseIterable & Displayable & Hashable>: View
|
||||
|
||||
extension CaseIterablePicker {
|
||||
|
||||
init(title: String, selection: Binding<Element?>) {
|
||||
init(_ title: String, selection: Binding<Element?>) {
|
||||
self.init(
|
||||
selection: selection,
|
||||
label: { Text($0.displayTitle) },
|
||||
@ -75,7 +75,7 @@ extension CaseIterablePicker {
|
||||
)
|
||||
}
|
||||
|
||||
init(title: String, selection: Binding<Element>) {
|
||||
init(_ title: String, selection: Binding<Element>) {
|
||||
let binding = Binding<Element?> {
|
||||
selection.wrappedValue
|
||||
} set: { newValue, _ in
|
||||
|
@ -140,9 +140,9 @@ extension Defaults.Keys {
|
||||
|
||||
enum Library {
|
||||
|
||||
static let cinematicBackground: Key<Bool> = UserKey("Customization.Library.cinematicBackground", default: true)
|
||||
static let cinematicBackground: Key<Bool> = UserKey("libraryCinematicBackground", default: true)
|
||||
static let enabledDrawerFilters: Key<[ItemFilterType]> = UserKey(
|
||||
"Library.enabledDrawerFilters",
|
||||
"libraryEnabledDrawerFilters",
|
||||
default: ItemFilterType.allCases
|
||||
)
|
||||
static let displayType: Key<LibraryDisplayType> = UserKey("libraryViewType", default: .grid)
|
||||
@ -158,7 +158,7 @@ extension Defaults.Keys {
|
||||
enum Search {
|
||||
|
||||
static let enabledDrawerFilters: Key<[ItemFilterType]> = UserKey(
|
||||
"Search.enabledDrawerFilters",
|
||||
"searchEnabledDrawerFilters",
|
||||
default: ItemFilterType.allCases
|
||||
)
|
||||
}
|
||||
|
@ -11,8 +11,6 @@ import CoreStore
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
// TODO: observation
|
||||
|
||||
/// A property wrapper for a stored `AnyData` object.
|
||||
@propertyWrapper
|
||||
struct StoredValue<Value: Codable>: DynamicProperty {
|
||||
@ -116,6 +114,9 @@ extension StoredValue {
|
||||
// Stored value doesn't exist but we want to observe it.
|
||||
// Create default and get new publisher
|
||||
|
||||
// TODO: this still store unnecessary data if never changed,
|
||||
// observe if changes were made and delete on deinit
|
||||
|
||||
do {
|
||||
try AnyStoredData.store(
|
||||
value: key.defaultValue(),
|
||||
|
@ -12,7 +12,7 @@ import JellyfinAPI
|
||||
// Note: Temporary values to avoid refactoring or
|
||||
// reduce complexity at local sites.
|
||||
//
|
||||
// Values can be cleaned up at any time so and are
|
||||
// Values can be cleaned up at any time and are
|
||||
// meant to have a short lifetime.
|
||||
|
||||
extension StoredValues.Keys {
|
||||
|
@ -92,7 +92,7 @@ extension StoredValues.Keys {
|
||||
static func libraryDisplayType(parentID: String?) -> Key<LibraryDisplayType> {
|
||||
CurrentUserKey(
|
||||
parentID,
|
||||
domain: "libraryDisplayType",
|
||||
domain: "setting-libraryDisplayType",
|
||||
default: Defaults[.Customization.Library.displayType]
|
||||
)
|
||||
}
|
||||
@ -100,7 +100,7 @@ extension StoredValues.Keys {
|
||||
static func libraryListColumnCount(parentID: String?) -> Key<Int> {
|
||||
CurrentUserKey(
|
||||
parentID,
|
||||
domain: "libraryListColumnCount",
|
||||
domain: "setting-libraryListColumnCount",
|
||||
default: Defaults[.Customization.Library.listColumnCount]
|
||||
)
|
||||
}
|
||||
@ -108,7 +108,7 @@ extension StoredValues.Keys {
|
||||
static func libraryPosterType(parentID: String?) -> Key<PosterDisplayType> {
|
||||
CurrentUserKey(
|
||||
parentID,
|
||||
domain: "libraryPosterType",
|
||||
domain: "setting-libraryPosterType",
|
||||
default: Defaults[.Customization.Library.posterType]
|
||||
)
|
||||
}
|
||||
@ -119,7 +119,7 @@ extension StoredValues.Keys {
|
||||
static func libraryFilters(parentID: String?) -> Key<ItemFilterCollection> {
|
||||
CurrentUserKey(
|
||||
parentID,
|
||||
domain: "libraryFilters",
|
||||
domain: "setting-libraryFilters",
|
||||
default: ItemFilterCollection.default
|
||||
)
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ extension UserState {
|
||||
try SwiftfinStore.dataStack.perform { transaction in
|
||||
let userData = try transaction.fetchAll(
|
||||
From<AnyStoredData>()
|
||||
.where(\.$ownerID == id)
|
||||
.where(combineByAnd: Where(\.$ownerID == id), Where("%K BEGINSWITH %@", "domain", "setting"))
|
||||
)
|
||||
|
||||
transaction.delete(userData)
|
||||
|
@ -44,7 +44,7 @@ struct ChevronButton: View {
|
||||
|
||||
extension ChevronButton {
|
||||
|
||||
init(title: String, subtitle: String? = nil) {
|
||||
init(_ title: String, subtitle: String? = nil) {
|
||||
self.init(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
|
@ -51,7 +51,7 @@ struct AppSettingsView: View {
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// ChevronButton(title: "Logs")
|
||||
// ChevronButton("Logs")
|
||||
// .onSelect {
|
||||
// router.route(to: \.log)
|
||||
// }
|
||||
|
@ -62,7 +62,7 @@ struct CustomizeViewsSettings: View {
|
||||
|
||||
Section {
|
||||
|
||||
ChevronButton(title: "Indicators")
|
||||
ChevronButton("Indicators")
|
||||
.onSelect {
|
||||
router.route(to: \.indicatorSettings)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ struct SettingsView: View {
|
||||
}
|
||||
|
||||
ChevronButton(
|
||||
title: L10n.server,
|
||||
L10n.server,
|
||||
subtitle: viewModel.userSession.server.name
|
||||
)
|
||||
.onSelect {
|
||||
@ -60,7 +60,7 @@ struct SettingsView: View {
|
||||
|
||||
InlineEnumToggle(title: "Video Player Type", selection: $videoPlayerType)
|
||||
|
||||
ChevronButton(title: L10n.videoPlayer)
|
||||
ChevronButton(L10n.videoPlayer)
|
||||
.onSelect {
|
||||
router.route(to: \.videoPlayerSettings)
|
||||
}
|
||||
@ -70,12 +70,12 @@ struct SettingsView: View {
|
||||
|
||||
Section {
|
||||
|
||||
ChevronButton(title: L10n.customize)
|
||||
ChevronButton(L10n.customize)
|
||||
.onSelect {
|
||||
router.route(to: \.customizeViewsSettings)
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.experimental)
|
||||
ChevronButton(L10n.experimental)
|
||||
.onSelect {
|
||||
router.route(to: \.experimentalSettings)
|
||||
}
|
||||
@ -86,7 +86,7 @@ struct SettingsView: View {
|
||||
|
||||
Section {
|
||||
|
||||
ChevronButton(title: "Logs")
|
||||
ChevronButton("Logs")
|
||||
.onSelect {
|
||||
router.route(to: \.log)
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ struct VideoPlayerSettingsView: View {
|
||||
|
||||
Section {
|
||||
ChevronButton(
|
||||
title: "Resume Offset",
|
||||
"Resume Offset",
|
||||
subtitle: resumeOffset.secondLabel
|
||||
)
|
||||
.onSelect {
|
||||
@ -55,7 +55,7 @@ struct VideoPlayerSettingsView: View {
|
||||
}
|
||||
|
||||
Section {
|
||||
ChevronButton(title: L10n.subtitleFont, subtitle: subtitleFontName)
|
||||
ChevronButton(L10n.subtitleFont, subtitle: subtitleFontName)
|
||||
.onSelect {
|
||||
router.route(to: \.fontPicker, $subtitleFontName)
|
||||
}
|
||||
|
@ -3773,13 +3773,11 @@
|
||||
E18E021E2887492B0022598C /* RowDivider.swift in Sources */,
|
||||
E1DC983E296DEB9B00982F06 /* UnwatchedIndicator.swift in Sources */,
|
||||
E107BB9427880A8F00354E07 /* CollectionItemViewModel.swift in Sources */,
|
||||
E1575E7E293E77B5001665B1 /* ItemFilterCollection.swift in Sources */,
|
||||
E1D37F592B9CEF4B00343D2B /* DeviceProfile+SwiftfinProfile.swift in Sources */,
|
||||
53ABFDE9267974EF00886593 /* HomeViewModel.swift in Sources */,
|
||||
E1575E99293E7B1E001665B1 /* UIColor.swift in Sources */,
|
||||
E1575E92293E7B1E001665B1 /* CGSize.swift in Sources */,
|
||||
E1575E7E293E77B5001665B1 /* ItemFilterCollection.swift in Sources */,
|
||||
E1575E7E293E77B5001665B1 /* ItemFilterCollection.swift in Sources */,
|
||||
C46DD8EF2A8FB56E0046A504 /* LiveBottomBarView.swift in Sources */,
|
||||
C46DD8EA2A8FB45C0046A504 /* LiveOverlay.swift in Sources */,
|
||||
E11E376D293E9CC1009EF240 /* VideoPlayerCoordinator.swift in Sources */,
|
||||
@ -4307,7 +4305,6 @@
|
||||
E1D3044428D1991900587289 /* LibraryViewTypeToggle.swift in Sources */,
|
||||
C45C36542A8B1F2C003DAE46 /* LiveVideoPlayerManager.swift in Sources */,
|
||||
E148128B28C15526003B8787 /* ItemSortBy.swift in Sources */,
|
||||
E148128B28C15526003B8787 /* ItemSortBy.swift in Sources */,
|
||||
E10231412BCF8A3C009D71FC /* ChannelLibraryView.swift in Sources */,
|
||||
E1F0204E26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */,
|
||||
E1A3E4CB2BB74EFD005C59F8 /* EpisodeHStack.swift in Sources */,
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"originHash" : "558c2e760c073dbad0a2bfbade5ccfa1b2962fdd8ab5f658d9bbfc4310623441",
|
||||
"originHash" : "68a42015b2d42a14d418b6e13427443de55c970d5b3764bbc969e1b3f8c3a78b",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "blurhashkit",
|
||||
@ -34,7 +34,7 @@
|
||||
"location" : "https://github.com/LePips/CollectionVGrid",
|
||||
"state" : {
|
||||
"branch" : "main",
|
||||
"revision" : "b50b5241df5fc1d71e5a09f6a87731c67c2a79e5"
|
||||
"revision" : "7204e5f717ea571efb4600ecb71c2412e0dec921"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -114,8 +114,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/kean/Nuke",
|
||||
"state" : {
|
||||
"revision" : "4625c73ea00a9fb4b4f3e28d95d0021a44af7e59",
|
||||
"version" : "12.5.0"
|
||||
"revision" : "8e431251dea0081b6ab154dab61a6ec74e4b6577",
|
||||
"version" : "12.6.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -123,8 +123,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/kean/Pulse",
|
||||
"state" : {
|
||||
"revision" : "d647e99f06abc94d63579e335ad4ce368195c149",
|
||||
"version" : "4.0.5"
|
||||
"revision" : "4f34c4f91cda623a7627e6d5e35dbbbb514b8daa",
|
||||
"version" : "4.1.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -195,8 +195,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/siteline/SwiftUI-Introspect",
|
||||
"state" : {
|
||||
"revision" : "0cd2a5a5895306bc21d54a2254302d24a9a571e4",
|
||||
"version" : "1.1.3"
|
||||
"revision" : "7dc5b287f8040e4ad5038739850b758e78f77808",
|
||||
"version" : "1.1.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ struct ChevronButton: View {
|
||||
|
||||
extension ChevronButton {
|
||||
|
||||
init(title: String, subtitle: String? = nil) {
|
||||
init(_ title: String, subtitle: String? = nil) {
|
||||
self.init(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
|
@ -39,7 +39,7 @@ struct AboutAppView: View {
|
||||
trailing: "\(UIApplication.appVersion ?? .emptyDash) (\(UIApplication.bundleVersion ?? .emptyDash))"
|
||||
)
|
||||
|
||||
ChevronButton(title: L10n.sourceCode)
|
||||
ChevronButton(L10n.sourceCode)
|
||||
.leadingView {
|
||||
Image(.logoGithub)
|
||||
.resizable()
|
||||
@ -51,7 +51,7 @@ struct AboutAppView: View {
|
||||
UIApplication.shared.open(.swiftfinGithub)
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.bugsAndFeatures)
|
||||
ChevronButton(L10n.bugsAndFeatures)
|
||||
.leadingView {
|
||||
Image(systemName: "plus.circle.fill")
|
||||
.resizable()
|
||||
@ -65,7 +65,7 @@ struct AboutAppView: View {
|
||||
UIApplication.shared.open(.swiftfinGithubIssues)
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.settings)
|
||||
ChevronButton(L10n.settings)
|
||||
.leadingView {
|
||||
Image(systemName: "gearshape.fill")
|
||||
.resizable()
|
||||
|
@ -37,21 +37,21 @@ struct AppSettingsView: View {
|
||||
var body: some View {
|
||||
Form {
|
||||
|
||||
ChevronButton(title: L10n.about)
|
||||
ChevronButton(L10n.about)
|
||||
.onSelect {
|
||||
router.route(to: \.about, viewModel)
|
||||
}
|
||||
|
||||
Section(L10n.accessibility) {
|
||||
|
||||
ChevronButton(title: L10n.appIcon)
|
||||
ChevronButton(L10n.appIcon)
|
||||
.onSelect {
|
||||
router.route(to: \.appIconSelector, viewModel)
|
||||
}
|
||||
|
||||
if !selectUserUseSplashscreen {
|
||||
CaseIterablePicker(
|
||||
title: L10n.appearance,
|
||||
L10n.appearance,
|
||||
selection: $appearance
|
||||
)
|
||||
}
|
||||
@ -85,7 +85,7 @@ struct AppSettingsView: View {
|
||||
|
||||
SignOutIntervalSection()
|
||||
|
||||
ChevronButton(title: L10n.logs)
|
||||
ChevronButton(L10n.logs)
|
||||
.onSelect {
|
||||
router.route(to: \.log)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ struct MediaSourceInfoView: View {
|
||||
{
|
||||
Section(L10n.video) {
|
||||
ForEach(videoStreams, id: \.self) { stream in
|
||||
ChevronButton(title: stream.displayTitle ?? .emptyDash)
|
||||
ChevronButton(stream.displayTitle ?? .emptyDash)
|
||||
.onSelect {
|
||||
router.route(to: \.mediaStreamInfo, stream)
|
||||
}
|
||||
@ -37,7 +37,7 @@ struct MediaSourceInfoView: View {
|
||||
{
|
||||
Section(L10n.audio) {
|
||||
ForEach(audioStreams, id: \.self) { stream in
|
||||
ChevronButton(title: stream.displayTitle ?? .emptyDash)
|
||||
ChevronButton(stream.displayTitle ?? .emptyDash)
|
||||
.onSelect {
|
||||
router.route(to: \.mediaStreamInfo, stream)
|
||||
}
|
||||
@ -50,7 +50,7 @@ struct MediaSourceInfoView: View {
|
||||
{
|
||||
Section(L10n.subtitle) {
|
||||
ForEach(subtitleStreams, id: \.self) { stream in
|
||||
ChevronButton(title: stream.displayTitle ?? .emptyDash)
|
||||
ChevronButton(stream.displayTitle ?? .emptyDash)
|
||||
.onSelect {
|
||||
router.route(to: \.mediaStreamInfo, stream)
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ struct CustomizeViewsSettings: View {
|
||||
|
||||
if UIDevice.isPhone {
|
||||
Section {
|
||||
CaseIterablePicker(title: L10n.items, selection: $itemViewType)
|
||||
CaseIterablePicker(L10n.items, selection: $itemViewType)
|
||||
}
|
||||
|
||||
if itemViewType == .cinematic {
|
||||
@ -91,12 +91,12 @@ struct CustomizeViewsSettings: View {
|
||||
|
||||
Section {
|
||||
|
||||
ChevronButton(title: L10n.library)
|
||||
ChevronButton(L10n.library)
|
||||
.onSelect {
|
||||
router.route(to: \.itemFilterDrawerSelector, $libraryEnabledDrawerFilters)
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.search)
|
||||
ChevronButton(L10n.search)
|
||||
.onSelect {
|
||||
router.route(to: \.itemFilterDrawerSelector, $searchEnabledDrawerFilters)
|
||||
}
|
||||
@ -114,28 +114,28 @@ struct CustomizeViewsSettings: View {
|
||||
|
||||
Section(L10n.posters) {
|
||||
|
||||
ChevronButton(title: L10n.indicators)
|
||||
ChevronButton(L10n.indicators)
|
||||
.onSelect {
|
||||
router.route(to: \.indicatorSettings)
|
||||
}
|
||||
|
||||
Toggle(L10n.showPosterLabels, isOn: $showPosterLabels)
|
||||
|
||||
CaseIterablePicker(title: L10n.next, selection: $nextUpPosterType)
|
||||
CaseIterablePicker(L10n.next, selection: $nextUpPosterType)
|
||||
|
||||
CaseIterablePicker(title: L10n.recentlyAdded, selection: $recentlyAddedPosterType)
|
||||
CaseIterablePicker(L10n.recentlyAdded, selection: $recentlyAddedPosterType)
|
||||
|
||||
CaseIterablePicker(title: L10n.latestWithString(L10n.library), selection: $latestInLibraryPosterType)
|
||||
CaseIterablePicker(L10n.latestWithString(L10n.library), selection: $latestInLibraryPosterType)
|
||||
|
||||
CaseIterablePicker(title: L10n.recommended, selection: $similarPosterType)
|
||||
CaseIterablePicker(L10n.recommended, selection: $similarPosterType)
|
||||
|
||||
CaseIterablePicker(title: L10n.search, selection: $searchPosterType)
|
||||
CaseIterablePicker(L10n.search, selection: $searchPosterType)
|
||||
}
|
||||
|
||||
Section("Libraries") {
|
||||
CaseIterablePicker(title: L10n.library, selection: $libraryDisplayType)
|
||||
CaseIterablePicker(L10n.library, selection: $libraryDisplayType)
|
||||
|
||||
CaseIterablePicker(title: L10n.posters, selection: $libraryPosterType)
|
||||
CaseIterablePicker(L10n.posters, selection: $libraryPosterType)
|
||||
|
||||
if libraryDisplayType == .list, UIDevice.isPad {
|
||||
BasicStepper(
|
||||
|
@ -38,23 +38,23 @@ struct GestureSettingsView: View {
|
||||
|
||||
Section {
|
||||
|
||||
CaseIterablePicker(title: "Horizontal Pan", selection: $horizontalPanGesture)
|
||||
CaseIterablePicker("Horizontal Pan", selection: $horizontalPanGesture)
|
||||
.disabled(horizontalSwipeGesture != .none && horizontalPanGesture == .none)
|
||||
|
||||
CaseIterablePicker(title: "Horizontal Swipe", selection: $horizontalSwipeGesture)
|
||||
CaseIterablePicker("Horizontal Swipe", selection: $horizontalSwipeGesture)
|
||||
.disabled(horizontalPanGesture != .none && horizontalSwipeGesture == .none)
|
||||
|
||||
CaseIterablePicker(title: "Long Press", selection: $longPressGesture)
|
||||
CaseIterablePicker("Long Press", selection: $longPressGesture)
|
||||
|
||||
CaseIterablePicker(title: "Multi Tap", selection: $multiTapGesture)
|
||||
CaseIterablePicker("Multi Tap", selection: $multiTapGesture)
|
||||
|
||||
CaseIterablePicker(title: "Double Touch", selection: $doubleTouchGesture)
|
||||
CaseIterablePicker("Double Touch", selection: $doubleTouchGesture)
|
||||
|
||||
CaseIterablePicker(title: "Pinch", selection: $pinchGesture)
|
||||
CaseIterablePicker("Pinch", selection: $pinchGesture)
|
||||
|
||||
CaseIterablePicker(title: "Left Vertical Pan", selection: $verticalPanGestureLeft)
|
||||
CaseIterablePicker("Left Vertical Pan", selection: $verticalPanGestureLeft)
|
||||
|
||||
CaseIterablePicker(title: "Right Vertical Pan", selection: $verticalPanGestureRight)
|
||||
CaseIterablePicker("Right Vertical Pan", selection: $verticalPanGestureRight)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Gestures")
|
||||
|
@ -39,7 +39,7 @@ struct SettingsView: View {
|
||||
|
||||
// TODO: admin users go to dashboard instead
|
||||
ChevronButton(
|
||||
title: L10n.server,
|
||||
L10n.server,
|
||||
subtitle: viewModel.userSession.server.name
|
||||
)
|
||||
.onSelect {
|
||||
@ -58,30 +58,30 @@ struct SettingsView: View {
|
||||
|
||||
Section(L10n.videoPlayer) {
|
||||
CaseIterablePicker(
|
||||
title: L10n.videoPlayerType,
|
||||
L10n.videoPlayerType,
|
||||
selection: $videoPlayerType
|
||||
)
|
||||
|
||||
ChevronButton(title: L10n.nativePlayer)
|
||||
ChevronButton(L10n.nativePlayer)
|
||||
.onSelect {
|
||||
router.route(to: \.nativePlayerSettings)
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.videoPlayer)
|
||||
ChevronButton(L10n.videoPlayer)
|
||||
.onSelect {
|
||||
router.route(to: \.videoPlayerSettings)
|
||||
}
|
||||
}
|
||||
|
||||
Section(L10n.accessibility) {
|
||||
CaseIterablePicker(title: L10n.appearance, selection: $appearance)
|
||||
CaseIterablePicker(L10n.appearance, selection: $appearance)
|
||||
|
||||
ChevronButton(title: L10n.customize)
|
||||
ChevronButton(L10n.customize)
|
||||
.onSelect {
|
||||
router.route(to: \.customizeViewsSettings)
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.experimental)
|
||||
ChevronButton(L10n.experimental)
|
||||
.onSelect {
|
||||
router.route(to: \.experimentalSettings)
|
||||
}
|
||||
@ -93,14 +93,14 @@ struct SettingsView: View {
|
||||
Text(L10n.accentColorDescription)
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.logs)
|
||||
ChevronButton(L10n.logs)
|
||||
.onSelect {
|
||||
router.route(to: \.log)
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
ChevronButton(title: "Debug")
|
||||
ChevronButton("Debug")
|
||||
.onSelect {
|
||||
router.route(to: \.debugSettings)
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ struct ResetUserPasswordView: View {
|
||||
}
|
||||
.foregroundStyle(.red, .red.opacity(0.2))
|
||||
} else {
|
||||
ListRowButton("Reset") {
|
||||
ListRowButton("Save") {
|
||||
focusedPassword = nil
|
||||
viewModel.send(.reset(current: currentPassword, new: confirmNewPassword))
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ struct UserLocalSecurityView: View {
|
||||
List {
|
||||
|
||||
Section {
|
||||
CaseIterablePicker(title: "Security", selection: $signInPolicy)
|
||||
CaseIterablePicker("Security", selection: $signInPolicy)
|
||||
} footer: {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
Text(
|
||||
|
@ -17,6 +17,9 @@ struct UserProfileSettingsView: View {
|
||||
@ObservedObject
|
||||
var viewModel: SettingsViewModel
|
||||
|
||||
@State
|
||||
private var isPresentingConfirmReset: Bool = false
|
||||
|
||||
@ViewBuilder
|
||||
private var imageView: some View {
|
||||
ImageView(
|
||||
@ -63,23 +66,45 @@ struct UserProfileSettingsView: View {
|
||||
}
|
||||
|
||||
Section {
|
||||
ChevronButton(title: L10n.quickConnect)
|
||||
ChevronButton(L10n.quickConnect)
|
||||
.onSelect {
|
||||
router.route(to: \.quickConnect)
|
||||
}
|
||||
|
||||
ChevronButton(title: "Password")
|
||||
ChevronButton("Password")
|
||||
.onSelect {
|
||||
router.route(to: \.resetUserPassword)
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
ChevronButton(title: "Local Security")
|
||||
ChevronButton("Security")
|
||||
.onSelect {
|
||||
router.route(to: \.localSecurity)
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
// TODO: move under future "Storage" tab
|
||||
// when downloads implemented
|
||||
Button("Reset Settings") {
|
||||
isPresentingConfirmReset = true
|
||||
}
|
||||
.foregroundStyle(.red)
|
||||
} footer: {
|
||||
Text("Reset Swiftfin user settings")
|
||||
}
|
||||
}
|
||||
.alert("Reset Settings", isPresented: $isPresentingConfirmReset) {
|
||||
Button("Reset", role: .destructive) {
|
||||
do {
|
||||
try viewModel.userSession.user.deleteSettings()
|
||||
} catch {
|
||||
viewModel.logger.error("Unable to reset user settings: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
} message: {
|
||||
Text("Are you sure you want to reset all user settings?")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,14 +65,14 @@ struct VideoPlayerSettingsView: View {
|
||||
var body: some View {
|
||||
Form {
|
||||
|
||||
ChevronButton(title: L10n.gestures)
|
||||
ChevronButton(L10n.gestures)
|
||||
.onSelect {
|
||||
router.route(to: \.gestureSettings)
|
||||
}
|
||||
|
||||
CaseIterablePicker(title: L10n.jumpBackwardLength, selection: $jumpBackwardLength)
|
||||
CaseIterablePicker(L10n.jumpBackwardLength, selection: $jumpBackwardLength)
|
||||
|
||||
CaseIterablePicker(title: L10n.jumpForwardLength, selection: $jumpForwardLength)
|
||||
CaseIterablePicker(L10n.jumpForwardLength, selection: $jumpForwardLength)
|
||||
|
||||
Section {
|
||||
|
||||
@ -91,7 +91,7 @@ struct VideoPlayerSettingsView: View {
|
||||
|
||||
Section(L10n.buttons) {
|
||||
|
||||
CaseIterablePicker(title: L10n.playbackButtons, selection: $playbackButtonType)
|
||||
CaseIterablePicker(L10n.playbackButtons, selection: $playbackButtonType)
|
||||
|
||||
Toggle(isOn: $showJumpButtons) {
|
||||
HStack {
|
||||
@ -100,12 +100,12 @@ struct VideoPlayerSettingsView: View {
|
||||
}
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.barButtons)
|
||||
ChevronButton(L10n.barButtons)
|
||||
.onSelect {
|
||||
router.route(to: \.actionButtonSelector, $barActionButtons)
|
||||
}
|
||||
|
||||
ChevronButton(title: L10n.menuButtons)
|
||||
ChevronButton(L10n.menuButtons)
|
||||
.onSelect {
|
||||
router.route(to: \.actionButtonSelector, $menuActionButtons)
|
||||
}
|
||||
@ -119,12 +119,12 @@ struct VideoPlayerSettingsView: View {
|
||||
Text(L10n.sliderColor)
|
||||
}
|
||||
|
||||
CaseIterablePicker(title: L10n.sliderType, selection: $sliderType)
|
||||
CaseIterablePicker(L10n.sliderType, selection: $sliderType)
|
||||
}
|
||||
|
||||
Section {
|
||||
|
||||
ChevronButton(title: L10n.subtitleFont, subtitle: subtitleFontName)
|
||||
ChevronButton(L10n.subtitleFont, subtitle: subtitleFontName)
|
||||
.onSelect {
|
||||
router.route(to: \.fontPicker, $subtitleFontName)
|
||||
}
|
||||
@ -150,9 +150,9 @@ struct VideoPlayerSettingsView: View {
|
||||
|
||||
Toggle(L10n.scrubCurrentTime, isOn: $showCurrentTimeWhileScrubbing)
|
||||
|
||||
CaseIterablePicker(title: L10n.timestampType, selection: $timestampType)
|
||||
CaseIterablePicker(L10n.timestampType, selection: $timestampType)
|
||||
|
||||
CaseIterablePicker(title: L10n.trailingValue, selection: $trailingTimestampType)
|
||||
CaseIterablePicker(L10n.trailingValue, selection: $trailingTimestampType)
|
||||
}
|
||||
|
||||
Section(L10n.transition) {
|
||||
|
@ -43,7 +43,7 @@ extension UserSignInView {
|
||||
List {
|
||||
|
||||
Section {
|
||||
CaseIterablePicker(title: "Security", selection: $updateSignInPolicy)
|
||||
CaseIterablePicker("Security", selection: $updateSignInPolicy)
|
||||
} footer: {
|
||||
// TODO: descriptions of each section
|
||||
|
||||
|
@ -34,7 +34,7 @@ struct PlaybackSettingsView: View {
|
||||
Form {
|
||||
Section {
|
||||
|
||||
ChevronButton(title: L10n.videoPlayer)
|
||||
ChevronButton(L10n.videoPlayer)
|
||||
.onSelect {
|
||||
router.route(to: \.videoPlayerSettings)
|
||||
}
|
||||
@ -67,7 +67,7 @@ struct PlaybackSettingsView: View {
|
||||
if viewModel.videoStreams.isNotEmpty {
|
||||
Section(L10n.video) {
|
||||
ForEach(viewModel.videoStreams, id: \.displayTitle) { mediaStream in
|
||||
ChevronButton(title: mediaStream.displayTitle ?? .emptyDash)
|
||||
ChevronButton(mediaStream.displayTitle ?? .emptyDash)
|
||||
.onSelect {
|
||||
router.route(to: \.mediaStreamInfo, mediaStream)
|
||||
}
|
||||
@ -78,7 +78,7 @@ struct PlaybackSettingsView: View {
|
||||
if viewModel.audioStreams.isNotEmpty {
|
||||
Section(L10n.audio) {
|
||||
ForEach(viewModel.audioStreams, id: \.displayTitle) { mediaStream in
|
||||
ChevronButton(title: mediaStream.displayTitle ?? .emptyDash)
|
||||
ChevronButton(mediaStream.displayTitle ?? .emptyDash)
|
||||
.onSelect {
|
||||
router.route(to: \.mediaStreamInfo, mediaStream)
|
||||
}
|
||||
@ -89,7 +89,7 @@ struct PlaybackSettingsView: View {
|
||||
if viewModel.subtitleStreams.isNotEmpty {
|
||||
Section(L10n.subtitle) {
|
||||
ForEach(viewModel.subtitleStreams, id: \.displayTitle) { mediaStream in
|
||||
ChevronButton(title: mediaStream.displayTitle ?? .emptyDash)
|
||||
ChevronButton(mediaStream.displayTitle ?? .emptyDash)
|
||||
.onSelect {
|
||||
router.route(to: \.mediaStreamInfo, mediaStream)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user