diff --git a/Shared/Objects/CaseIterablePicker.swift b/Shared/Objects/CaseIterablePicker.swift index 2c47479c..538cfd72 100644 --- a/Shared/Objects/CaseIterablePicker.swift +++ b/Shared/Objects/CaseIterablePicker.swift @@ -65,7 +65,7 @@ struct CaseIterablePicker: View extension CaseIterablePicker { - init(title: String, selection: Binding) { + init(_ title: String, selection: Binding) { self.init( selection: selection, label: { Text($0.displayTitle) }, @@ -75,7 +75,7 @@ extension CaseIterablePicker { ) } - init(title: String, selection: Binding) { + init(_ title: String, selection: Binding) { let binding = Binding { selection.wrappedValue } set: { newValue, _ in diff --git a/Shared/Services/SwiftfinDefaults.swift b/Shared/Services/SwiftfinDefaults.swift index ec15a00d..304cd4af 100644 --- a/Shared/Services/SwiftfinDefaults.swift +++ b/Shared/Services/SwiftfinDefaults.swift @@ -140,9 +140,9 @@ extension Defaults.Keys { enum Library { - static let cinematicBackground: Key = UserKey("Customization.Library.cinematicBackground", default: true) + static let cinematicBackground: Key = UserKey("libraryCinematicBackground", default: true) static let enabledDrawerFilters: Key<[ItemFilterType]> = UserKey( - "Library.enabledDrawerFilters", + "libraryEnabledDrawerFilters", default: ItemFilterType.allCases ) static let displayType: Key = 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 ) } diff --git a/Shared/SwiftfinStore/StoredValue/StoredValue.swift b/Shared/SwiftfinStore/StoredValue/StoredValue.swift index 2debae8f..6dd29cb8 100644 --- a/Shared/SwiftfinStore/StoredValue/StoredValue.swift +++ b/Shared/SwiftfinStore/StoredValue/StoredValue.swift @@ -11,8 +11,6 @@ import CoreStore import Foundation import SwiftUI -// TODO: observation - /// A property wrapper for a stored `AnyData` object. @propertyWrapper struct StoredValue: 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(), diff --git a/Shared/SwiftfinStore/StoredValue/StoredValues+Temp.swift b/Shared/SwiftfinStore/StoredValue/StoredValues+Temp.swift index ee2df5a4..41cbf039 100644 --- a/Shared/SwiftfinStore/StoredValue/StoredValues+Temp.swift +++ b/Shared/SwiftfinStore/StoredValue/StoredValues+Temp.swift @@ -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 { diff --git a/Shared/SwiftfinStore/StoredValue/StoredValues+User.swift b/Shared/SwiftfinStore/StoredValue/StoredValues+User.swift index 58a7121c..5f440363 100644 --- a/Shared/SwiftfinStore/StoredValue/StoredValues+User.swift +++ b/Shared/SwiftfinStore/StoredValue/StoredValues+User.swift @@ -92,7 +92,7 @@ extension StoredValues.Keys { static func libraryDisplayType(parentID: String?) -> Key { 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 { 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 { 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 { CurrentUserKey( parentID, - domain: "libraryFilters", + domain: "setting-libraryFilters", default: ItemFilterCollection.default ) } diff --git a/Shared/SwiftfinStore/SwiftinStore+UserState.swift b/Shared/SwiftfinStore/SwiftinStore+UserState.swift index c89dd70f..f4b18227 100644 --- a/Shared/SwiftfinStore/SwiftinStore+UserState.swift +++ b/Shared/SwiftfinStore/SwiftinStore+UserState.swift @@ -115,7 +115,7 @@ extension UserState { try SwiftfinStore.dataStack.perform { transaction in let userData = try transaction.fetchAll( From() - .where(\.$ownerID == id) + .where(combineByAnd: Where(\.$ownerID == id), Where("%K BEGINSWITH %@", "domain", "setting")) ) transaction.delete(userData) diff --git a/Swiftfin tvOS/Components/ChevronButton.swift b/Swiftfin tvOS/Components/ChevronButton.swift index 419f19a5..88d1c33e 100644 --- a/Swiftfin tvOS/Components/ChevronButton.swift +++ b/Swiftfin tvOS/Components/ChevronButton.swift @@ -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, diff --git a/Swiftfin tvOS/Views/BasicAppSettingsView.swift b/Swiftfin tvOS/Views/BasicAppSettingsView.swift index 145467f6..2ea0642a 100644 --- a/Swiftfin tvOS/Views/BasicAppSettingsView.swift +++ b/Swiftfin tvOS/Views/BasicAppSettingsView.swift @@ -51,7 +51,7 @@ struct AppSettingsView: View { // ) // } // -// ChevronButton(title: "Logs") +// ChevronButton("Logs") // .onSelect { // router.route(to: \.log) // } diff --git a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings.swift b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings.swift index d9220c6e..ca181847 100644 --- a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings.swift +++ b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings.swift @@ -62,7 +62,7 @@ struct CustomizeViewsSettings: View { Section { - ChevronButton(title: "Indicators") + ChevronButton("Indicators") .onSelect { router.route(to: \.indicatorSettings) } diff --git a/Swiftfin tvOS/Views/SettingsView/SettingsView.swift b/Swiftfin tvOS/Views/SettingsView/SettingsView.swift index d4f8a243..086eea3d 100644 --- a/Swiftfin tvOS/Views/SettingsView/SettingsView.swift +++ b/Swiftfin tvOS/Views/SettingsView/SettingsView.swift @@ -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) } diff --git a/Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift b/Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift index 019424d7..c4039b4e 100644 --- a/Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift +++ b/Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift @@ -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) } diff --git a/Swiftfin.xcodeproj/project.pbxproj b/Swiftfin.xcodeproj/project.pbxproj index e1059db3..b86b74b2 100644 --- a/Swiftfin.xcodeproj/project.pbxproj +++ b/Swiftfin.xcodeproj/project.pbxproj @@ -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 */, diff --git a/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 57454d59..ac76b012 100644 --- a/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -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" } }, { diff --git a/Swiftfin/Components/ChevronButton.swift b/Swiftfin/Components/ChevronButton.swift index 419f19a5..88d1c33e 100644 --- a/Swiftfin/Components/ChevronButton.swift +++ b/Swiftfin/Components/ChevronButton.swift @@ -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, diff --git a/Swiftfin/Views/AboutAppView.swift b/Swiftfin/Views/AboutAppView.swift index 85d9010a..94c1c683 100644 --- a/Swiftfin/Views/AboutAppView.swift +++ b/Swiftfin/Views/AboutAppView.swift @@ -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() diff --git a/Swiftfin/Views/AppSettingsView/AppSettingsView.swift b/Swiftfin/Views/AppSettingsView/AppSettingsView.swift index e0f98da7..c3ddc31a 100644 --- a/Swiftfin/Views/AppSettingsView/AppSettingsView.swift +++ b/Swiftfin/Views/AppSettingsView/AppSettingsView.swift @@ -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) } diff --git a/Swiftfin/Views/MediaSourceInfoView.swift b/Swiftfin/Views/MediaSourceInfoView.swift index 6b3ba834..d3fd17b0 100644 --- a/Swiftfin/Views/MediaSourceInfoView.swift +++ b/Swiftfin/Views/MediaSourceInfoView.swift @@ -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) } diff --git a/Swiftfin/Views/SettingsView/CustomizeViewsSettings.swift b/Swiftfin/Views/SettingsView/CustomizeViewsSettings.swift index 31835e83..ea40feba 100644 --- a/Swiftfin/Views/SettingsView/CustomizeViewsSettings.swift +++ b/Swiftfin/Views/SettingsView/CustomizeViewsSettings.swift @@ -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( diff --git a/Swiftfin/Views/SettingsView/GestureSettingsView.swift b/Swiftfin/Views/SettingsView/GestureSettingsView.swift index f793ae66..c062ef81 100644 --- a/Swiftfin/Views/SettingsView/GestureSettingsView.swift +++ b/Swiftfin/Views/SettingsView/GestureSettingsView.swift @@ -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") diff --git a/Swiftfin/Views/SettingsView/SettingsView/SettingsView.swift b/Swiftfin/Views/SettingsView/SettingsView/SettingsView.swift index f5db7412..a137b82c 100644 --- a/Swiftfin/Views/SettingsView/SettingsView/SettingsView.swift +++ b/Swiftfin/Views/SettingsView/SettingsView/SettingsView.swift @@ -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) } diff --git a/Swiftfin/Views/SettingsView/UserProfileSettingsView/ResetUserPasswordView.swift b/Swiftfin/Views/SettingsView/UserProfileSettingsView/ResetUserPasswordView.swift index 741db8db..25ef2ffc 100644 --- a/Swiftfin/Views/SettingsView/UserProfileSettingsView/ResetUserPasswordView.swift +++ b/Swiftfin/Views/SettingsView/UserProfileSettingsView/ResetUserPasswordView.swift @@ -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)) } diff --git a/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserLocalSecurityView.swift b/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserLocalSecurityView.swift index a15b4f35..835d9019 100644 --- a/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserLocalSecurityView.swift +++ b/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserLocalSecurityView.swift @@ -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( diff --git a/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift b/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift index 1b4a115b..f7a92a85 100644 --- a/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift +++ b/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift @@ -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?") } } } diff --git a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift index 132c995a..1b6411e3 100644 --- a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift +++ b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift @@ -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) { diff --git a/Swiftfin/Views/UserSignInView/Components/UserSignInSecurityView.swift b/Swiftfin/Views/UserSignInView/Components/UserSignInSecurityView.swift index 797c061c..9f43e1b4 100644 --- a/Swiftfin/Views/UserSignInView/Components/UserSignInSecurityView.swift +++ b/Swiftfin/Views/UserSignInView/Components/UserSignInSecurityView.swift @@ -43,7 +43,7 @@ extension UserSignInView { List { Section { - CaseIterablePicker(title: "Security", selection: $updateSignInPolicy) + CaseIterablePicker("Security", selection: $updateSignInPolicy) } footer: { // TODO: descriptions of each section diff --git a/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift b/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift index 4bfb82db..33ad6e9f 100644 --- a/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift +++ b/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift @@ -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) }