From cfc0105dc78ea21dda42a9b775acd81bc12c2ef4 Mon Sep 17 00:00:00 2001 From: Ethan Pippin Date: Mon, 7 Apr 2025 09:08:54 -0400 Subject: [PATCH] cleanup (#1484) --- Shared/Components/ChevronAlertButton.swift | 96 ---- Shared/Components/ChevronButton.swift | 496 +++++++++++++----- Shared/Extensions/URL.swift | 2 +- .../AppSettingsView/AppSettingsView.swift | 7 +- .../Components/SignOutIntervalSection.swift | 3 +- .../Components/Sections/HomeSection.swift | 2 +- .../Components/Sections/ItemSection.swift | 7 +- .../Components/Sections/LibrarySection.swift | 3 +- .../CustomizeViewsSettings.swift | 7 +- .../PlaybackQualitySettingsView.swift | 7 +- .../Views/SettingsView/SettingsView.swift | 31 +- .../UserLocalSecurityView.swift | 2 +- .../UserProfileSettingsView.swift | 7 +- .../VideoPlayerSettingsView.swift | 10 +- Swiftfin.xcodeproj/project.pbxproj | 9 - Swiftfin/Views/AboutAppView.swift | 11 +- .../AdminDashboardView.swift | 42 +- .../Components/IntervalRow.swift | 2 +- .../Components/TimeLimitSection.swift | 2 +- .../ServerUserDetailsView.swift | 58 +- .../Sections/ExternalAccessSection.swift | 2 +- .../Components/Sections/SessionsSection.swift | 4 +- .../AppSettingsView/AppSettingsView.swift | 21 +- .../Views/ItemEditorView/ItemEditorView.swift | 49 +- .../ItemImageDetailsDetailsSection.swift | 3 +- .../Components/Sections/EpisodeSection.swift | 4 +- .../Components/Sections/ReviewsSection.swift | 4 +- .../Components/Sections/SeriesSection.swift | 2 +- Swiftfin/Views/MediaSourceInfoView.swift | 21 +- .../Components/Sections/HomeSection.swift | 2 +- .../Components/Sections/ItemSection.swift | 7 +- .../CustomizeViewsSettings.swift | 21 +- .../PlaybackQualitySettingsView.swift | 7 +- .../SettingsView/SettingsView.swift | 52 +- .../UserProfileSettingsView.swift | 21 +- .../Components/Sections/ButtonSection.swift | 14 +- .../Components/Sections/SubtitleSection.swift | 7 +- .../VideoPlayerSettingsView.swift | 7 +- .../Components/PlaybackSettingsView.swift | 28 +- 39 files changed, 563 insertions(+), 517 deletions(-) delete mode 100644 Shared/Components/ChevronAlertButton.swift diff --git a/Shared/Components/ChevronAlertButton.swift b/Shared/Components/ChevronAlertButton.swift deleted file mode 100644 index dd157b7f..00000000 --- a/Shared/Components/ChevronAlertButton.swift +++ /dev/null @@ -1,96 +0,0 @@ -// -// 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) 2025 Jellyfin & Jellyfin Contributors -// - -import SwiftUI - -// TODO: find better name - -struct ChevronAlertButton: View where Content: View { - - @State - private var isSelected = false - - private let content: () -> Content - private let description: String? - private let onCancel: (() -> Void)? - private let onSave: (() -> Void)? - private let subtitle: Text? - private let title: String - - // MARK: - Body - - var body: some View { - ChevronButton(title, subtitle: subtitle) - .onSelect { - isSelected = true - } - .alert(title, isPresented: $isSelected) { - - content() - - if let onSave { - Button(L10n.save) { - onSave() - isSelected = false - } - } - - if let onCancel { - Button(L10n.cancel, role: .cancel) { - onCancel() - isSelected = false - } - } - } message: { - if let description { - Text(description) - } - } - } -} - -extension ChevronAlertButton { - - init( - _ title: String, - subtitle: String?, - description: String? = nil, - @ViewBuilder content: @escaping () -> Content, - onSave: (() -> Void)? = nil, - onCancel: (() -> Void)? = nil - ) { - self.init( - content: content, - description: description, - onCancel: onCancel, - onSave: onSave, - subtitle: subtitle != nil ? Text(subtitle!) : nil, - title: title - ) - } - - // MARK: - Initializer: Text Inputs with Save/Cancel Actions - - init( - _ title: String, - subtitle: Text?, - description: String? = nil, - @ViewBuilder content: @escaping () -> Content, - onSave: (() -> Void)? = nil, - onCancel: (() -> Void)? = nil - ) { - self.init( - content: content, - description: description, - onCancel: onCancel, - onSave: onSave, - subtitle: subtitle, - title: title - ) - } -} diff --git a/Shared/Components/ChevronButton.swift b/Shared/Components/ChevronButton.swift index c5fb3d3a..31d8e003 100644 --- a/Shared/Components/ChevronButton.swift +++ b/Shared/Components/ChevronButton.swift @@ -8,154 +8,374 @@ import SwiftUI -struct ChevronButton: View { +struct ChevronButton: View { private let icon: Icon private let isExternal: Bool private let title: Text - private let subtitle: Text? - private var onSelect: () -> Void + private let subtitle: Subtitle + + private let innerContent: (AnyView) -> any View + + @ViewBuilder + private var label: some View { + HStack { + + icon + .font(.body.weight(.bold)) + + title + + Spacer() + + subtitle + .foregroundStyle(.secondary) + + Image(systemName: isExternal ? "arrow.up.forward" : "chevron.right") + .font(.body.weight(.regular)) + .foregroundStyle(.secondary) + } + } var body: some View { - Button(action: onSelect) { - HStack { - - icon - .font(.body.weight(.bold)) - - title - - Spacer() - - if let subtitle { - subtitle - .foregroundStyle(.secondary) - } - - Image(systemName: isExternal ? "arrow.up.forward" : "chevron.right") - .font(.body.weight(.regular)) - .foregroundStyle(.secondary) - } - } - .foregroundStyle(.primary, .secondary) - } -} - -extension ChevronButton where Icon == EmptyView { - - init( - _ title: String, - subtitle: String? = nil, - external: Bool = false - ) { - self.init( - icon: EmptyView(), - isExternal: external, - title: Text(title), - subtitle: { - if let subtitle { - Text(subtitle) - } else { - nil - } - }(), - onSelect: {} - ) - } - - init( - _ title: String, - subtitle: Text?, - external: Bool = false - ) { - self.init( - icon: EmptyView(), - isExternal: external, - title: Text(title), - subtitle: subtitle, - onSelect: {} - ) - } -} - -extension ChevronButton where Icon == Image { - - init( - _ title: String, - subtitle: String? = nil, - systemName: String, - external: Bool = false - ) { - self.init( - icon: Image(systemName: systemName), - isExternal: external, - title: Text(title), - subtitle: { - if let subtitle { - Text(subtitle) - } else { - nil - } - }(), - onSelect: {} - ) - } - - init( - _ title: String, - subtitle: Text?, - systemName: String, - external: Bool = false - ) { - self.init( - icon: Image(systemName: systemName), - isExternal: external, - title: Text(title), - subtitle: subtitle, - onSelect: {} - ) - } - - init( - _ title: String, - subtitle: String? = nil, - image: Image, - external: Bool = false - ) { - self.init( - icon: image, - isExternal: external, - title: Text(title), - subtitle: { - if let subtitle { - Text(subtitle) - } else { - nil - } - }(), - onSelect: {} - ) - } - - init( - _ title: String, - subtitle: Text?, - image: Image, - external: Bool = false - ) { - self.init( - icon: image, - isExternal: external, - title: Text(title), - subtitle: subtitle, - onSelect: {} - ) + innerContent(label.eraseToAnyView()) + .eraseToAnyView() } } extension ChevronButton { - func onSelect(perform action: @escaping () -> Void) -> Self { - copy(modifying: \.onSelect, with: action) + private struct AlertContentView: View { + + @State + private var isPresented: Bool = false + + let alertTitle: String + let content: () -> Content + let description: String? + let label: Label + let onCancel: (() -> Void)? + let onSave: (() -> Void)? + + var body: some View { + Button { + isPresented = true + } label: { + label + } + .foregroundStyle(.primary, .secondary) + .alert(alertTitle, isPresented: $isPresented) { + + content() + + if let onSave { + Button(L10n.save) { + onSave() + isPresented = false + } + } + + if let onCancel { + Button(L10n.cancel, role: .cancel) { + onCancel() + isPresented = false + } + } + } message: { + if let description { + Text(description) + } + } + } + } + + private struct ButtonContentView: View { + + let label: Label + let action: () -> Void + + var body: some View { + Button(action: action) { + label + } + .foregroundStyle(.primary, .secondary) + } + } +} + +extension ChevronButton { + + init( + _ title: String, + external: Bool = false, + action: @escaping () -> Void, + @ViewBuilder icon: @escaping () -> Icon, + @ViewBuilder subtitle: @escaping () -> Subtitle + ) { + self.icon = icon() + self.isExternal = external + self.title = Text(title) + self.subtitle = subtitle() + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } + + init( + _ title: Text, + external: Bool = false, + action: @escaping () -> Void, + @ViewBuilder icon: @escaping () -> Icon, + @ViewBuilder subtitle: @escaping () -> Subtitle + ) { + self.icon = icon() + self.isExternal = external + self.title = title + self.subtitle = subtitle() + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } +} + +extension ChevronButton where Icon == EmptyView, Subtitle == Text { + + init( + _ title: String, + subtitle: String, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = EmptyView() + self.isExternal = external + self.title = Text(title) + self.subtitle = Text(subtitle) + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } + + init( + _ title: String, + subtitle: Text, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = EmptyView() + self.isExternal = external + self.title = Text(title) + self.subtitle = subtitle + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } +} + +extension ChevronButton where Icon == EmptyView, Subtitle == EmptyView { + + init( + _ title: String, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = EmptyView() + self.isExternal = external + self.title = Text(title) + self.subtitle = EmptyView() + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } +} + +extension ChevronButton where Icon == Image, Subtitle == Text { + + // systemName + + init( + _ title: String, + subtitle: String, + systemName: String, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = Image(systemName: systemName) + self.isExternal = external + self.title = Text(title) + self.subtitle = Text(subtitle) + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } + + init( + _ title: String, + subtitle: Text, + systemName: String, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = Image(systemName: systemName) + self.isExternal = external + self.title = Text(title) + self.subtitle = subtitle + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } + + // ImageResource + + init( + _ title: String, + subtitle: String, + image: ImageResource, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = Image(image) + self.isExternal = external + self.title = Text(title) + self.subtitle = Text(subtitle) + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } + + init( + _ title: String, + subtitle: Text, + image: ImageResource, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = Image(image) + self.isExternal = external + self.title = Text(title) + self.subtitle = subtitle + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } +} + +extension ChevronButton where Icon == Image, Subtitle == EmptyView { + + // systemName + + init( + _ title: String, + systemName: String, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = Image(systemName: systemName) + self.isExternal = external + self.title = Text(title) + self.subtitle = EmptyView() + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } + + // ImageResource + + init( + _ title: String, + image: ImageResource, + external: Bool = false, + action: @escaping () -> Void + ) { + self.icon = Image(image) + self.isExternal = external + self.title = Text(title) + self.subtitle = EmptyView() + self.innerContent = { label in + ButtonContentView( + label: label, + action: action + ) + } + } +} + +extension ChevronButton where Icon == EmptyView, Subtitle == Text { + + init( + _ title: String, + subtitle: String? = nil, + description: String? = nil, + @ViewBuilder content: @escaping () -> Content, + onSave: (() -> Void)? = nil, + onCancel: (() -> Void)? = nil + ) { + self.icon = EmptyView() + self.isExternal = false + self.title = Text(title) + self.subtitle = Text(subtitle ?? "") + self.innerContent = { label in + AlertContentView( + alertTitle: title, + content: content, + description: description, + label: label, + onCancel: onCancel, + onSave: onSave + ) + } + } + + init( + _ title: String, + subtitle: Text? = nil, + description: String? = nil, + @ViewBuilder content: @escaping () -> Content, + onSave: (() -> Void)? = nil, + onCancel: (() -> Void)? = nil + ) { + self.icon = EmptyView() + self.isExternal = false + self.title = Text(title) + self.subtitle = subtitle ?? Text("") + self.innerContent = { label in + AlertContentView( + alertTitle: title, + content: content, + description: description, + label: label, + onCancel: onCancel, + onSave: onSave + ) + } } } diff --git a/Shared/Extensions/URL.swift b/Shared/Extensions/URL.swift index cffe9748..92cfca05 100644 --- a/Shared/Extensions/URL.swift +++ b/Shared/Extensions/URL.swift @@ -8,7 +8,7 @@ import Foundation -extension URL: Identifiable { +extension URL: @retroactive Identifiable { public var id: String { absoluteString diff --git a/Swiftfin tvOS/Views/AppSettingsView/AppSettingsView.swift b/Swiftfin tvOS/Views/AppSettingsView/AppSettingsView.swift index 4352db85..c43f4c5a 100644 --- a/Swiftfin tvOS/Views/AppSettingsView/AppSettingsView.swift +++ b/Swiftfin tvOS/Views/AppSettingsView/AppSettingsView.swift @@ -87,10 +87,9 @@ struct AppSettingsView: View { SignOutIntervalSection() - ChevronButton(L10n.logs) - .onSelect { - router.route(to: \.log) - } + ChevronButton(L10n.logs) { + router.route(to: \.log) + } } .navigationTitle(L10n.advanced) } diff --git a/Swiftfin tvOS/Views/AppSettingsView/Components/SignOutIntervalSection.swift b/Swiftfin tvOS/Views/AppSettingsView/Components/SignOutIntervalSection.swift index 794725e0..f18321ee 100644 --- a/Swiftfin tvOS/Views/AppSettingsView/Components/SignOutIntervalSection.swift +++ b/Swiftfin tvOS/Views/AppSettingsView/Components/SignOutIntervalSection.swift @@ -40,8 +40,7 @@ extension AppSettingsView { ChevronButton( L10n.duration, subtitle: Text(backgroundSignOutInterval, format: .hourMinute) - ) - .onSelect { + ) { router.route(to: \.hourPicker) } } diff --git a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/HomeSection.swift b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/HomeSection.swift index c29a8067..9dd76876 100644 --- a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/HomeSection.swift +++ b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/HomeSection.swift @@ -30,7 +30,7 @@ extension CustomizeViewsSettings { Toggle(L10n.nextUpRewatch, isOn: $resumeNextUp) - ChevronAlertButton( + ChevronButton( L10n.nextUpDays, subtitle: { if maxNextUp > 0 { diff --git a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/ItemSection.swift b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/ItemSection.swift index fd71a756..f2937091 100644 --- a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/ItemSection.swift +++ b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/ItemSection.swift @@ -35,10 +35,9 @@ extension CustomizeViewsSettings { var body: some View { Section(L10n.items) { - ChevronButton(L10n.mediaAttributes) - .onSelect { - router.route(to: \.itemViewAttributes, $itemViewAttributes) - } + ChevronButton(L10n.mediaAttributes) { + router.route(to: \.itemViewAttributes, $itemViewAttributes) + } ListRowMenu(L10n.enabledTrailers, selection: $enabledTrailers) diff --git a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/LibrarySection.swift b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/LibrarySection.swift index 5ddfe8ad..be7ab843 100644 --- a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/LibrarySection.swift +++ b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/Components/Sections/LibrarySection.swift @@ -57,8 +57,7 @@ extension CustomizeViewsSettings { ChevronButton( L10n.columns, subtitle: listColumnCount.description - ) - .onSelect { + ) { router.route(to: \.listColumnSettings, $listColumnCount) } } diff --git a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/CustomizeViewsSettings.swift b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/CustomizeViewsSettings.swift index ddde6926..84f8398a 100644 --- a/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/CustomizeViewsSettings.swift +++ b/Swiftfin tvOS/Views/SettingsView/CustomizeViewsSettings/CustomizeViewsSettings.swift @@ -53,10 +53,9 @@ struct CustomizeViewsSettings: View { Section(L10n.posters) { - ChevronButton(L10n.indicators) - .onSelect { - router.route(to: \.indicatorSettings) - } + ChevronButton(L10n.indicators) { + router.route(to: \.indicatorSettings) + } Toggle(L10n.showPosterLabels, isOn: $showPosterLabels) diff --git a/Swiftfin tvOS/Views/SettingsView/PlaybackQualitySettingsView.swift b/Swiftfin tvOS/Views/SettingsView/PlaybackQualitySettingsView.swift index 69f4bb0c..1312e4a7 100644 --- a/Swiftfin tvOS/Views/SettingsView/PlaybackQualitySettingsView.swift +++ b/Swiftfin tvOS/Views/SettingsView/PlaybackQualitySettingsView.swift @@ -61,10 +61,9 @@ struct PlaybackQualitySettingsView: View { .focused($focusedItem, equals: .compatibility) if compatibilityMode == .custom { - ChevronButton(L10n.profiles) - .onSelect { - router.route(to: \.customDeviceProfileSettings) - } + ChevronButton(L10n.profiles) { + router.route(to: \.customDeviceProfileSettings) + } } } header: { L10n.deviceProfile.text diff --git a/Swiftfin tvOS/Views/SettingsView/SettingsView.swift b/Swiftfin tvOS/Views/SettingsView/SettingsView.swift index caa8751e..2dd6cd38 100644 --- a/Swiftfin tvOS/Views/SettingsView/SettingsView.swift +++ b/Swiftfin tvOS/Views/SettingsView/SettingsView.swift @@ -40,8 +40,7 @@ struct SettingsView: View { ChevronButton( L10n.server, subtitle: viewModel.userSession.server.name - ) - .onSelect { + ) { router.route(to: \.serverDetail, viewModel.userSession.server) } } @@ -58,23 +57,20 @@ struct SettingsView: View { ListRowMenu(L10n.videoPlayerType, selection: $videoPlayerType) - ChevronButton(L10n.videoPlayer) - .onSelect { - router.route(to: \.videoPlayerSettings) - } + ChevronButton(L10n.videoPlayer) { + router.route(to: \.videoPlayerSettings) + } - ChevronButton(L10n.playbackQuality) - .onSelect { - router.route(to: \.playbackQualitySettings) - } + ChevronButton(L10n.playbackQuality) { + router.route(to: \.playbackQualitySettings) + } } Section(L10n.accessibility) { - ChevronButton(L10n.customize) - .onSelect { - router.route(to: \.customizeViewsSettings) - } + ChevronButton(L10n.customize) { + router.route(to: \.customizeViewsSettings) + } // // ChevronButton(L10n.experimental) // .onSelect { @@ -84,10 +80,9 @@ struct SettingsView: View { Section { - ChevronButton(L10n.logs) - .onSelect { - router.route(to: \.log) - } + ChevronButton(L10n.logs) { + router.route(to: \.log) + } } } } diff --git a/Swiftfin tvOS/Views/SettingsView/UserProfileSettingsView/UserLocalSecurityView.swift b/Swiftfin tvOS/Views/SettingsView/UserProfileSettingsView/UserLocalSecurityView.swift index 55c1f971..93c95e09 100644 --- a/Swiftfin tvOS/Views/SettingsView/UserProfileSettingsView/UserLocalSecurityView.swift +++ b/Swiftfin tvOS/Views/SettingsView/UserProfileSettingsView/UserLocalSecurityView.swift @@ -145,7 +145,7 @@ struct UserLocalSecurityView: View { if signInPolicy == .requirePin { Section { - ChevronAlertButton( + ChevronButton( L10n.hint, subtitle: pinHint, description: L10n.setPinHintDescription diff --git a/Swiftfin tvOS/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift b/Swiftfin tvOS/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift index 9d0c1116..c669762a 100644 --- a/Swiftfin tvOS/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift +++ b/Swiftfin tvOS/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift @@ -53,10 +53,9 @@ struct UserProfileSettingsView: View { // } Section { - ChevronButton(L10n.security) - .onSelect { - router.route(to: \.localSecurity) - } + ChevronButton(L10n.security) { + router.route(to: \.localSecurity) + } } // TODO: Do we want this option on tvOS? diff --git a/Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift b/Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift index d144d2d0..129d540d 100644 --- a/Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift +++ b/Swiftfin tvOS/Views/SettingsView/VideoPlayerSettingsView.swift @@ -47,8 +47,7 @@ struct VideoPlayerSettingsView: View { ChevronButton( L10n.offset, subtitle: resumeOffset.secondLabel - ) - .onSelect { + ) { isPresentingResumeOffsetStepper = true } } header: { @@ -59,10 +58,9 @@ struct VideoPlayerSettingsView: View { Section { - ChevronButton(L10n.subtitleFont, subtitle: subtitleFontName) - .onSelect { - router.route(to: \.fontPicker, $subtitleFontName) - } + ChevronButton(L10n.subtitleFont, subtitle: subtitleFontName) { + router.route(to: \.fontPicker, $subtitleFontName) + } } header: { L10n.subtitles.text } footer: { diff --git a/Swiftfin.xcodeproj/project.pbxproj b/Swiftfin.xcodeproj/project.pbxproj index e763d2a9..852e59e4 100644 --- a/Swiftfin.xcodeproj/project.pbxproj +++ b/Swiftfin.xcodeproj/project.pbxproj @@ -93,7 +93,6 @@ 4E49DEE32CE55FB900352DCD /* SyncPlayUserAccessType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E49DEE22CE55FB500352DCD /* SyncPlayUserAccessType.swift */; }; 4E49DEE42CE55FB900352DCD /* SyncPlayUserAccessType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E49DEE22CE55FB500352DCD /* SyncPlayUserAccessType.swift */; }; 4E49DEE62CE5616800352DCD /* UserProfileImagePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E49DEE52CE5616800352DCD /* UserProfileImagePickerView.swift */; }; - 4E4A53222CBE0A1C003BD24D /* ChevronAlertButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB7B33A2CBDE63F004A342E /* ChevronAlertButton.swift */; }; 4E4DAC372D11EE5E00E13FF9 /* SplitLoginWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E4DAC362D11EE4F00E13FF9 /* SplitLoginWindowView.swift */; }; 4E4DAC3D2D11F94400E13FF9 /* LocalServerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E4DAC3C2D11F94000E13FF9 /* LocalServerButton.swift */; }; 4E4E9C672CFEBF2A00A6946F /* StudioEditorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E4E9C662CFEBF2500A6946F /* StudioEditorViewModel.swift */; }; @@ -203,15 +202,12 @@ 4EB3F0372D8CD33300EBEDAA /* ActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB3F0362D8CD33100EBEDAA /* ActionButton.swift */; }; 4EB3F0392D8CD5CF00EBEDAA /* TrailerMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB3F0382D8CD5CC00EBEDAA /* TrailerMenu.swift */; }; 4EB3F03B2D8CD6A900EBEDAA /* VersionMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB3F03A2D8CD6A700EBEDAA /* VersionMenu.swift */; }; - 4EB4ECE32CBEFC4D002FF2FC /* SessionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB4ECE22CBEFC49002FF2FC /* SessionInfo.swift */; }; - 4EB4ECE42CBEFC4D002FF2FC /* SessionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB4ECE22CBEFC49002FF2FC /* SessionInfo.swift */; }; 4EB538B52CE3C77200EB72D5 /* ServerUserPermissionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB538B42CE3C76D00EB72D5 /* ServerUserPermissionsView.swift */; }; 4EB538BD2CE3CCD100EB72D5 /* MediaPlaybackSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB538BC2CE3CCCF00EB72D5 /* MediaPlaybackSection.swift */; }; 4EB538C12CE3CF0F00EB72D5 /* ManagementSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB538C02CE3CF0E00EB72D5 /* ManagementSection.swift */; }; 4EB538C32CE3E21800EB72D5 /* SyncPlaySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB538C22CE3E21500EB72D5 /* SyncPlaySection.swift */; }; 4EB538C52CE3E25700EB72D5 /* ExternalAccessSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB538C42CE3E25500EB72D5 /* ExternalAccessSection.swift */; }; 4EB538C82CE3E8A600EB72D5 /* RemoteControlSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB538C72CE3E8A100EB72D5 /* RemoteControlSection.swift */; }; - 4EB7B33B2CBDE645004A342E /* ChevronAlertButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB7B33A2CBDE63F004A342E /* ChevronAlertButton.swift */; }; 4EB7C8D52CCED6E7000CC011 /* AddServerUserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB7C8D42CCED6E1000CC011 /* AddServerUserView.swift */; }; 4EBE06462C7E9509004A6C03 /* PlaybackCompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EBE06452C7E9509004A6C03 /* PlaybackCompatibility.swift */; }; 4EBE06472C7E9509004A6C03 /* PlaybackCompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EBE06452C7E9509004A6C03 /* PlaybackCompatibility.swift */; }; @@ -1440,14 +1436,12 @@ 4EB3F0362D8CD33100EBEDAA /* ActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionButton.swift; sourceTree = ""; }; 4EB3F0382D8CD5CC00EBEDAA /* TrailerMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrailerMenu.swift; sourceTree = ""; }; 4EB3F03A2D8CD6A700EBEDAA /* VersionMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionMenu.swift; sourceTree = ""; }; - 4EB4ECE22CBEFC49002FF2FC /* SessionInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionInfo.swift; sourceTree = ""; }; 4EB538B42CE3C76D00EB72D5 /* ServerUserPermissionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerUserPermissionsView.swift; sourceTree = ""; }; 4EB538BC2CE3CCCF00EB72D5 /* MediaPlaybackSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlaybackSection.swift; sourceTree = ""; }; 4EB538C02CE3CF0E00EB72D5 /* ManagementSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagementSection.swift; sourceTree = ""; }; 4EB538C22CE3E21500EB72D5 /* SyncPlaySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncPlaySection.swift; sourceTree = ""; }; 4EB538C42CE3E25500EB72D5 /* ExternalAccessSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalAccessSection.swift; sourceTree = ""; }; 4EB538C72CE3E8A100EB72D5 /* RemoteControlSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteControlSection.swift; sourceTree = ""; }; - 4EB7B33A2CBDE63F004A342E /* ChevronAlertButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChevronAlertButton.swift; sourceTree = ""; }; 4EB7C8D42CCED6E1000CC011 /* AddServerUserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddServerUserView.swift; sourceTree = ""; }; 4EBE06452C7E9509004A6C03 /* PlaybackCompatibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackCompatibility.swift; sourceTree = ""; }; 4EBE064C2C7EB6D3004A6C03 /* VideoPlayerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerType.swift; sourceTree = ""; }; @@ -5136,7 +5130,6 @@ E18E0203288749200022598C /* BlurView.swift */, E145EB212BDCCA43003BF6F3 /* BulletedList.swift */, E11982B92DA04F9B0008FC3F /* CenteredLazyVGrid.swift */, - 4EB7B33A2CBDE63F004A342E /* ChevronAlertButton.swift */, E1A1528728FD229500600579 /* ChevronButton.swift */, E11982D62DA0E8240008FC3F /* ConditionalMenu.swift */, E1153DCB2BBB633B00424D36 /* FastSVGView.swift */, @@ -6195,7 +6188,6 @@ E1763A722BF3F67C004DF6AB /* SwiftfinStore+Mappings.swift in Sources */, E1937A3C288E54AD00CB80AA /* BaseItemDto+Images.swift in Sources */, E18A17F0298C68B700C22F62 /* Overlay.swift in Sources */, - 4E4A53222CBE0A1C003BD24D /* ChevronAlertButton.swift in Sources */, 4E7315752D1485C900EA2A95 /* UserProfileImage.swift in Sources */, E1A42E4A28CA6CCD00A14DCB /* CinematicItemSelector.swift in Sources */, 4E2AC4CF2C6C4A0600DD600D /* PlaybackQualitySettingsCoordinator.swift in Sources */, @@ -6918,7 +6910,6 @@ BD3957792C113EC40078CEF8 /* SubtitleSection.swift in Sources */, 091B5A8A2683142E00D78B61 /* ServerDiscovery.swift in Sources */, E1721FAE28FB801C00762992 /* SmallPlaybackButtons.swift in Sources */, - 4EB7B33B2CBDE645004A342E /* ChevronAlertButton.swift in Sources */, E1E750682A33E9B400B2C1EE /* OverviewCard.swift in Sources */, E1CCF13128AC07EC006CAC9E /* PosterHStack.swift in Sources */, 4E2AC4C22C6C491200DD600D /* AudoCodec.swift in Sources */, diff --git a/Swiftfin/Views/AboutAppView.swift b/Swiftfin/Views/AboutAppView.swift index fa9b1c2a..4e39e814 100644 --- a/Swiftfin/Views/AboutAppView.swift +++ b/Swiftfin/Views/AboutAppView.swift @@ -40,10 +40,9 @@ struct AboutAppView: View { ChevronButton( L10n.sourceCode, - image: Image(.logoGithub), + image: .logoGithub, external: true - ) - .onSelect { + ) { UIApplication.shared.open(.swiftfinGithub) } @@ -51,8 +50,7 @@ struct AboutAppView: View { L10n.bugsAndFeatures, systemName: "plus.circle.fill", external: true - ) - .onSelect { + ) { UIApplication.shared.open(.swiftfinGithubIssues) } .symbolRenderingMode(.monochrome) @@ -61,8 +59,7 @@ struct AboutAppView: View { L10n.settings, systemName: "gearshape.fill", external: true - ) - .onSelect { + ) { guard let url = URL(string: UIApplication.openSettingsURLString) else { return } UIApplication.shared.open(url) } diff --git a/Swiftfin/Views/AdminDashboardView/AdminDashboardView.swift b/Swiftfin/Views/AdminDashboardView/AdminDashboardView.swift index 61a9b409..265de567 100644 --- a/Swiftfin/Views/AdminDashboardView/AdminDashboardView.swift +++ b/Swiftfin/Views/AdminDashboardView/AdminDashboardView.swift @@ -23,38 +23,32 @@ struct AdminDashboardView: View { description: L10n.dashboardDescription ) - ChevronButton(L10n.sessions) - .onSelect { - router.route(to: \.activeSessions) - } + ChevronButton(L10n.sessions) { + router.route(to: \.activeSessions) + } Section(L10n.activity) { - ChevronButton(L10n.devices) - .onSelect { - router.route(to: \.devices) - } - ChevronButton(L10n.users) - .onSelect { - router.route(to: \.users) - } + ChevronButton(L10n.devices) { + router.route(to: \.devices) + } + ChevronButton(L10n.users) { + router.route(to: \.users) + } } Section(L10n.advanced) { - ChevronButton(L10n.apiKeys) - .onSelect { - router.route(to: \.apiKeys) - } + ChevronButton(L10n.apiKeys) { + router.route(to: \.apiKeys) + } - ChevronButton(L10n.logs) - .onSelect { - router.route(to: \.serverLogs) - } + ChevronButton(L10n.logs) { + router.route(to: \.serverLogs) + } - ChevronButton(L10n.tasks) - .onSelect { - router.route(to: \.tasks) - } + ChevronButton(L10n.tasks) { + router.route(to: \.tasks) + } } } .navigationTitle(L10n.dashboard) diff --git a/Swiftfin/Views/AdminDashboardView/ServerTasks/AddTaskTriggerView/Components/IntervalRow.swift b/Swiftfin/Views/AdminDashboardView/ServerTasks/AddTaskTriggerView/Components/IntervalRow.swift index b1d11169..2464ba46 100644 --- a/Swiftfin/Views/AdminDashboardView/ServerTasks/AddTaskTriggerView/Components/IntervalRow.swift +++ b/Swiftfin/Views/AdminDashboardView/ServerTasks/AddTaskTriggerView/Components/IntervalRow.swift @@ -29,7 +29,7 @@ extension AddTaskTriggerView { // MARK: - Body var body: some View { - ChevronAlertButton( + ChevronButton( L10n.every, subtitle: ServerTicks( taskTriggerInfo.intervalTicks diff --git a/Swiftfin/Views/AdminDashboardView/ServerTasks/AddTaskTriggerView/Components/TimeLimitSection.swift b/Swiftfin/Views/AdminDashboardView/ServerTasks/AddTaskTriggerView/Components/TimeLimitSection.swift index 63073ef9..83bad0a0 100644 --- a/Swiftfin/Views/AdminDashboardView/ServerTasks/AddTaskTriggerView/Components/TimeLimitSection.swift +++ b/Swiftfin/Views/AdminDashboardView/ServerTasks/AddTaskTriggerView/Components/TimeLimitSection.swift @@ -30,7 +30,7 @@ extension AddTaskTriggerView { var body: some View { Section { - ChevronAlertButton( + ChevronButton( L10n.timeLimit, subtitle: subtitleString, description: L10n.taskTriggerTimeLimit diff --git a/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserDetailsView/ServerUserDetailsView.swift b/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserDetailsView/ServerUserDetailsView.swift index dff381c6..7072b256 100644 --- a/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserDetailsView/ServerUserDetailsView.swift +++ b/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserDetailsView/ServerUserDetailsView.swift @@ -65,7 +65,7 @@ struct ServerUserDetailsView: View { } Section { - ChevronAlertButton( + ChevronButton( L10n.username, subtitle: viewModel.user.name ) { @@ -82,45 +82,37 @@ struct ServerUserDetailsView: View { } } if let userId = viewModel.user.id { - ChevronButton(L10n.password) - .onSelect { - router.route(to: \.resetUserPassword, userId) - } - } - ChevronButton(L10n.permissions) - .onSelect { - router.route(to: \.userPermissions, viewModel) + ChevronButton(L10n.password) { + router.route(to: \.resetUserPassword, userId) } + } + ChevronButton(L10n.permissions) { + router.route(to: \.userPermissions, viewModel) + } } Section(L10n.access) { - ChevronButton(L10n.devices) - .onSelect { - router.route(to: \.userDeviceAccess, viewModel) - } - ChevronButton(L10n.liveTV) - .onSelect { - router.route(to: \.userLiveTVAccess, viewModel) - } - ChevronButton(L10n.media) - .onSelect { - router.route(to: \.userMediaAccess, viewModel) - } + ChevronButton(L10n.devices) { + router.route(to: \.userDeviceAccess, viewModel) + } + ChevronButton(L10n.liveTV) { + router.route(to: \.userLiveTVAccess, viewModel) + } + ChevronButton(L10n.media) { + router.route(to: \.userMediaAccess, viewModel) + } } Section(L10n.parentalControls) { - ChevronButton(L10n.ratings) - .onSelect { - router.route(to: \.userParentalRatings, viewModel) - } - ChevronButton(L10n.accessSchedules) - .onSelect { - router.route(to: \.userEditAccessSchedules, viewModel) - } - ChevronButton(L10n.accessTags) - .onSelect { - router.route(to: \.userEditAccessTags, viewModel) - } + ChevronButton(L10n.ratings) { + router.route(to: \.userParentalRatings, viewModel) + } + ChevronButton(L10n.accessSchedules) { + router.route(to: \.userEditAccessSchedules, viewModel) + } + ChevronButton(L10n.accessTags) { + router.route(to: \.userEditAccessTags, viewModel) + } } } .navigationTitle(L10n.user) diff --git a/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/ExternalAccessSection.swift b/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/ExternalAccessSection.swift index 2a3aef51..0634783b 100644 --- a/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/ExternalAccessSection.swift +++ b/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/ExternalAccessSection.swift @@ -35,7 +35,7 @@ extension ServerUserPermissionsView { ) if policy.remoteClientBitrateLimit != MaxBitratePolicy.unlimited.rawValue { - ChevronAlertButton( + ChevronButton( L10n.customBitrate, subtitle: Text(policy.remoteClientBitrateLimit ?? 0, format: .bitRate), description: L10n.enterCustomBitrate diff --git a/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/SessionsSection.swift b/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/SessionsSection.swift index cc32d79d..51542b4e 100644 --- a/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/SessionsSection.swift +++ b/Swiftfin/Views/AdminDashboardView/ServerUsers/ServerUserSettings/ServerUserPermissionsView/Components/Sections/SessionsSection.swift @@ -74,7 +74,7 @@ extension ServerUserPermissionsView { @ViewBuilder private func MaxFailedLoginsButton() -> some View { - ChevronAlertButton( + ChevronButton( L10n.customFailedLogins, subtitle: Text(policy.loginAttemptsBeforeLockout ?? 1, format: .number), description: L10n.enterCustomFailedLogins @@ -127,7 +127,7 @@ extension ServerUserPermissionsView { @ViewBuilder private func MaxSessionsButton() -> some View { - ChevronAlertButton( + ChevronButton( L10n.customSessions, subtitle: Text(policy.maxActiveSessions ?? 1, format: .number), description: L10n.enterCustomMaxSessions diff --git a/Swiftfin/Views/AppSettingsView/AppSettingsView.swift b/Swiftfin/Views/AppSettingsView/AppSettingsView.swift index a23656b4..aa40a724 100644 --- a/Swiftfin/Views/AppSettingsView/AppSettingsView.swift +++ b/Swiftfin/Views/AppSettingsView/AppSettingsView.swift @@ -37,17 +37,15 @@ struct AppSettingsView: View { var body: some View { Form { - ChevronButton(L10n.about) - .onSelect { - router.route(to: \.about, viewModel) - } + ChevronButton(L10n.about) { + router.route(to: \.about, viewModel) + } Section(L10n.accessibility) { - ChevronButton(L10n.appIcon) - .onSelect { - router.route(to: \.appIconSelector, viewModel) - } + ChevronButton(L10n.appIcon) { + router.route(to: \.appIconSelector, viewModel) + } if !selectUserUseSplashscreen { CaseIterablePicker( @@ -85,10 +83,9 @@ struct AppSettingsView: View { SignOutIntervalSection() - ChevronButton(L10n.logs) - .onSelect { - router.route(to: \.log) - } + ChevronButton(L10n.logs) { + router.route(to: \.log) + } } .animation(.linear, value: selectUserUseSplashscreen) .navigationTitle(L10n.advanced) diff --git a/Swiftfin/Views/ItemEditorView/ItemEditorView.swift b/Swiftfin/Views/ItemEditorView/ItemEditorView.swift index b5e4d5f7..27403120 100644 --- a/Swiftfin/Views/ItemEditorView/ItemEditorView.swift +++ b/Swiftfin/Views/ItemEditorView/ItemEditorView.swift @@ -99,38 +99,31 @@ struct ItemEditorView: View { private var editView: some View { Section(L10n.edit) { if [.boxSet, .movie, .person, .series].contains(viewModel.item.type) { - ChevronButton(L10n.identify) - .onSelect { - router.route(to: \.identifyItem, viewModel.item) - } + ChevronButton(L10n.identify) { + router.route(to: \.identifyItem, viewModel.item) + } + } + ChevronButton(L10n.images) { + router.route(to: \.editImages, ItemImagesViewModel(item: viewModel.item)) + } + ChevronButton(L10n.metadata) { + router.route(to: \.editMetadata, viewModel.item) } - ChevronButton(L10n.images) - .onSelect { - router.route(to: \.editImages, ItemImagesViewModel(item: viewModel.item)) - } - ChevronButton(L10n.metadata) - .onSelect { - router.route(to: \.editMetadata, viewModel.item) - } } Section { - ChevronButton(L10n.genres) - .onSelect { - router.route(to: \.editGenres, viewModel.item) - } - ChevronButton(L10n.people) - .onSelect { - router.route(to: \.editPeople, viewModel.item) - } - ChevronButton(L10n.tags) - .onSelect { - router.route(to: \.editTags, viewModel.item) - } - ChevronButton(L10n.studios) - .onSelect { - router.route(to: \.editStudios, viewModel.item) - } + ChevronButton(L10n.genres) { + router.route(to: \.editGenres, viewModel.item) + } + ChevronButton(L10n.people) { + router.route(to: \.editPeople, viewModel.item) + } + ChevronButton(L10n.tags) { + router.route(to: \.editTags, viewModel.item) + } + ChevronButton(L10n.studios) { + router.route(to: \.editStudios, viewModel.item) + } } } } diff --git a/Swiftfin/Views/ItemEditorView/ItemImages/ItemImageDetailsView/Components/ItemImageDetailsDetailsSection.swift b/Swiftfin/Views/ItemEditorView/ItemImages/ItemImageDetailsView/Components/ItemImageDetailsDetailsSection.swift index 7ea72a52..c5302a68 100644 --- a/Swiftfin/Views/ItemEditorView/ItemImages/ItemImageDetailsView/Components/ItemImageDetailsDetailsSection.swift +++ b/Swiftfin/Views/ItemEditorView/ItemImages/ItemImageDetailsView/Components/ItemImageDetailsDetailsSection.swift @@ -92,8 +92,7 @@ extension ItemImageDetailsView { ChevronButton( L10n.imageSource, external: true - ) - .onSelect { + ) { UIApplication.shared.open(url) } } diff --git a/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/EpisodeSection.swift b/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/EpisodeSection.swift index ac73d0be..73c6b5f5 100644 --- a/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/EpisodeSection.swift +++ b/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/EpisodeSection.swift @@ -24,7 +24,7 @@ extension EditMetadataView { // MARK: - Season Number - ChevronAlertButton( + ChevronButton( L10n.season, subtitle: item.parentIndexNumber?.description, description: L10n.enterSeasonNumber @@ -39,7 +39,7 @@ extension EditMetadataView { // MARK: - Episode Number - ChevronAlertButton( + ChevronButton( L10n.episode, subtitle: item.indexNumber?.description, description: L10n.enterEpisodeNumber diff --git a/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/ReviewsSection.swift b/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/ReviewsSection.swift index 8dbefa43..ea98554e 100644 --- a/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/ReviewsSection.swift +++ b/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/ReviewsSection.swift @@ -24,7 +24,7 @@ extension EditMetadataView { // MARK: - Critics Rating - ChevronAlertButton( + ChevronButton( L10n.critics, subtitle: item.criticRating.map { "\($0)" } ?? .emptyDash, description: L10n.ratingDescription(L10n.critics) @@ -44,7 +44,7 @@ extension EditMetadataView { // MARK: - Community Rating - ChevronAlertButton( + ChevronButton( L10n.community, subtitle: item.communityRating.map { "\($0)" } ?? .emptyDash, description: L10n.ratingDescription(L10n.community) diff --git a/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/SeriesSection.swift b/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/SeriesSection.swift index 2789ee25..9a516287 100644 --- a/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/SeriesSection.swift +++ b/Swiftfin/Views/ItemEditorView/ItemMetadata/EditMetadataView/Components/Sections/SeriesSection.swift @@ -99,7 +99,7 @@ extension EditMetadataView { @ViewBuilder private var runTimeView: some View { - ChevronAlertButton( + ChevronButton( L10n.runtime, subtitle: ServerTicks(item.runTimeTicks ?? 0) .seconds.formatted(.hourMinute), diff --git a/Swiftfin/Views/MediaSourceInfoView.swift b/Swiftfin/Views/MediaSourceInfoView.swift index 6f753b68..13f4969c 100644 --- a/Swiftfin/Views/MediaSourceInfoView.swift +++ b/Swiftfin/Views/MediaSourceInfoView.swift @@ -24,10 +24,9 @@ struct MediaSourceInfoView: View { { Section(L10n.video) { ForEach(videoStreams, id: \.self) { stream in - ChevronButton(stream.displayTitle ?? .emptyDash) - .onSelect { - router.route(to: \.mediaStreamInfo, stream) - } + ChevronButton(stream.displayTitle ?? .emptyDash) { + router.route(to: \.mediaStreamInfo, stream) + } } } } @@ -37,10 +36,9 @@ struct MediaSourceInfoView: View { { Section(L10n.audio) { ForEach(audioStreams, id: \.self) { stream in - ChevronButton(stream.displayTitle ?? .emptyDash) - .onSelect { - router.route(to: \.mediaStreamInfo, stream) - } + ChevronButton(stream.displayTitle ?? .emptyDash) { + router.route(to: \.mediaStreamInfo, stream) + } } } } @@ -50,10 +48,9 @@ struct MediaSourceInfoView: View { { Section(L10n.subtitle) { ForEach(subtitleStreams, id: \.self) { stream in - ChevronButton(stream.displayTitle ?? .emptyDash) - .onSelect { - router.route(to: \.mediaStreamInfo, stream) - } + ChevronButton(stream.displayTitle ?? .emptyDash) { + router.route(to: \.mediaStreamInfo, stream) + } } } } diff --git a/Swiftfin/Views/SettingsView/CustomizeViewsSettings/Components/Sections/HomeSection.swift b/Swiftfin/Views/SettingsView/CustomizeViewsSettings/Components/Sections/HomeSection.swift index bc66cbb1..01abdeb9 100644 --- a/Swiftfin/Views/SettingsView/CustomizeViewsSettings/Components/Sections/HomeSection.swift +++ b/Swiftfin/Views/SettingsView/CustomizeViewsSettings/Components/Sections/HomeSection.swift @@ -27,7 +27,7 @@ extension CustomizeViewsSettings { Toggle(L10n.nextUpRewatch, isOn: $resumeNextUp) - ChevronAlertButton( + ChevronButton( L10n.nextUpDays, subtitle: { if maxNextUp > 0 { diff --git a/Swiftfin/Views/SettingsView/CustomizeViewsSettings/Components/Sections/ItemSection.swift b/Swiftfin/Views/SettingsView/CustomizeViewsSettings/Components/Sections/ItemSection.swift index 82165237..dc960895 100644 --- a/Swiftfin/Views/SettingsView/CustomizeViewsSettings/Components/Sections/ItemSection.swift +++ b/Swiftfin/Views/SettingsView/CustomizeViewsSettings/Components/Sections/ItemSection.swift @@ -35,10 +35,9 @@ extension CustomizeViewsSettings { var body: some View { Section(L10n.items) { - ChevronButton(L10n.mediaAttributes) - .onSelect { - router.route(to: \.itemViewAttributes, $itemViewAttributes) - } + ChevronButton(L10n.mediaAttributes) { + router.route(to: \.itemViewAttributes, $itemViewAttributes) + } CaseIterablePicker( L10n.enabledTrailers, diff --git a/Swiftfin/Views/SettingsView/CustomizeViewsSettings/CustomizeViewsSettings.swift b/Swiftfin/Views/SettingsView/CustomizeViewsSettings/CustomizeViewsSettings.swift index 26ccb35d..7c79ef08 100644 --- a/Swiftfin/Views/SettingsView/CustomizeViewsSettings/CustomizeViewsSettings.swift +++ b/Swiftfin/Views/SettingsView/CustomizeViewsSettings/CustomizeViewsSettings.swift @@ -104,15 +104,13 @@ struct CustomizeViewsSettings: View { ) } - ChevronButton(L10n.library) - .onSelect { - router.route(to: \.itemFilterDrawerSelector, $libraryEnabledDrawerFilters) - } + ChevronButton(L10n.library) { + router.route(to: \.itemFilterDrawerSelector, $libraryEnabledDrawerFilters) + } - ChevronButton(L10n.search) - .onSelect { - router.route(to: \.itemFilterDrawerSelector, $searchEnabledDrawerFilters) - } + ChevronButton(L10n.search) { + router.route(to: \.itemFilterDrawerSelector, $searchEnabledDrawerFilters) + } } header: { L10n.filters.text @@ -127,10 +125,9 @@ struct CustomizeViewsSettings: View { Section(L10n.posters) { - ChevronButton(L10n.indicators) - .onSelect { - router.route(to: \.indicatorSettings) - } + ChevronButton(L10n.indicators) { + router.route(to: \.indicatorSettings) + } Toggle(L10n.showPosterLabels, isOn: $showPosterLabels) diff --git a/Swiftfin/Views/SettingsView/PlaybackQualitySettingsView.swift b/Swiftfin/Views/SettingsView/PlaybackQualitySettingsView.swift index 3beaed2d..5ffcbc8b 100644 --- a/Swiftfin/Views/SettingsView/PlaybackQualitySettingsView.swift +++ b/Swiftfin/Views/SettingsView/PlaybackQualitySettingsView.swift @@ -70,10 +70,9 @@ struct PlaybackQualitySettingsView: View { .animation(.none, value: compatibilityMode) if compatibilityMode == .custom { - ChevronButton(L10n.profiles) - .onSelect { - router.route(to: \.customDeviceProfileSettings) - } + ChevronButton(L10n.profiles) { + router.route(to: \.customDeviceProfileSettings) + } } } header: { Text(L10n.deviceProfile) diff --git a/Swiftfin/Views/SettingsView/SettingsView/SettingsView.swift b/Swiftfin/Views/SettingsView/SettingsView/SettingsView.swift index d87d0b8e..1e4ed3f4 100644 --- a/Swiftfin/Views/SettingsView/SettingsView/SettingsView.swift +++ b/Swiftfin/Views/SettingsView/SettingsView/SettingsView.swift @@ -38,16 +38,14 @@ struct SettingsView: View { ChevronButton( L10n.server, subtitle: viewModel.userSession.server.name - ) - .onSelect { + ) { router.route(to: \.serverConnection, viewModel.userSession.server) } if viewModel.userSession.user.permissions.isAdministrator { - ChevronButton(L10n.dashboard) - .onSelect { - router.route(to: \.adminDashboard) - } + ChevronButton(L10n.dashboard) { + router.route(to: \.adminDashboard) + } } } @@ -66,29 +64,25 @@ struct SettingsView: View { selection: $videoPlayerType ) - ChevronButton(L10n.nativePlayer) - .onSelect { - router.route(to: \.nativePlayerSettings) - } + ChevronButton(L10n.nativePlayer) { + router.route(to: \.nativePlayerSettings) + } - ChevronButton(L10n.videoPlayer) - .onSelect { - router.route(to: \.videoPlayerSettings) - } + ChevronButton(L10n.videoPlayer) { + router.route(to: \.videoPlayerSettings) + } - ChevronButton(L10n.playbackQuality) - .onSelect { - router.route(to: \.playbackQualitySettings) - } + ChevronButton(L10n.playbackQuality) { + router.route(to: \.playbackQualitySettings) + } } Section(L10n.accessibility) { CaseIterablePicker(L10n.appearance, selection: $appearance) - ChevronButton(L10n.customize) - .onSelect { - router.route(to: \.customizeViewsSettings) - } + ChevronButton(L10n.customize) { + router.route(to: \.customizeViewsSettings) + } // Note: uncomment if there are current // experimental settings @@ -105,17 +99,15 @@ struct SettingsView: View { Text(L10n.viewsMayRequireRestart) } - ChevronButton(L10n.logs) - .onSelect { - router.route(to: \.log) - } + ChevronButton(L10n.logs) { + router.route(to: \.log) + } #if DEBUG - ChevronButton("Debug") - .onSelect { - router.route(to: \.debugSettings) - } + ChevronButton("Debug") { + router.route(to: \.debugSettings) + } #endif } diff --git a/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift b/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift index f7bf18b9..245c57df 100644 --- a/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift +++ b/Swiftfin/Views/SettingsView/UserProfileSettingsView/UserProfileSettingsView.swift @@ -44,22 +44,19 @@ struct UserProfileSettingsView: View { } Section { - ChevronButton(L10n.quickConnect) - .onSelect { - router.route(to: \.quickConnect) - } + ChevronButton(L10n.quickConnect) { + router.route(to: \.quickConnect) + } - ChevronButton(L10n.password) - .onSelect { - router.route(to: \.resetUserPassword, viewModel.userSession.user.id) - } + ChevronButton(L10n.password) { + router.route(to: \.resetUserPassword, viewModel.userSession.user.id) + } } Section { - ChevronButton(L10n.security) - .onSelect { - router.route(to: \.localSecurity) - } + ChevronButton(L10n.security) { + router.route(to: \.localSecurity) + } } Section { diff --git a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/ButtonSection.swift b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/ButtonSection.swift index 31dcb191..20118b2a 100644 --- a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/ButtonSection.swift +++ b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/ButtonSection.swift @@ -42,15 +42,13 @@ extension VideoPlayerSettingsView { } } - ChevronButton(L10n.barButtons) - .onSelect { - router.route(to: \.actionButtonSelector, $barActionButtons) - } + ChevronButton(L10n.barButtons) { + router.route(to: \.actionButtonSelector, $barActionButtons) + } - ChevronButton(L10n.menuButtons) - .onSelect { - router.route(to: \.actionButtonSelector, $menuActionButtons) - } + ChevronButton(L10n.menuButtons) { + router.route(to: \.actionButtonSelector, $menuActionButtons) + } } .onChange(of: barActionButtons) { newValue in autoPlayEnabled = newValue.contains(.autoPlay) || menuActionButtons.contains(.autoPlay) diff --git a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/SubtitleSection.swift b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/SubtitleSection.swift index 2239aa18..ff585745 100644 --- a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/SubtitleSection.swift +++ b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/Components/Sections/SubtitleSection.swift @@ -23,10 +23,9 @@ extension VideoPlayerSettingsView { var body: some View { Section { - ChevronButton(L10n.subtitleFont, subtitle: subtitleFontName) - .onSelect { - router.route(to: \.fontPicker, $subtitleFontName) - } + ChevronButton(L10n.subtitleFont, subtitle: subtitleFontName) { + router.route(to: \.fontPicker, $subtitleFontName) + } BasicStepper( title: L10n.subtitleSize, diff --git a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift index 2ab19805..62fa39d6 100644 --- a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift +++ b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift @@ -24,10 +24,9 @@ struct VideoPlayerSettingsView: View { var body: some View { Form { - ChevronButton(L10n.gestures) - .onSelect { - router.route(to: \.gestureSettings) - } + ChevronButton(L10n.gestures) { + router.route(to: \.gestureSettings) + } CaseIterablePicker(L10n.jumpBackwardLength, selection: $jumpBackwardLength) diff --git a/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift b/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift index 89194f41..7a5d073b 100644 --- a/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift +++ b/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift @@ -34,10 +34,9 @@ struct PlaybackSettingsView: View { Form { Section { - ChevronButton(L10n.videoPlayer) - .onSelect { - router.route(to: \.videoPlayerSettings) - } + ChevronButton(L10n.videoPlayer) { + router.route(to: \.videoPlayerSettings) + } // TODO: playback information } header: { @@ -67,10 +66,9 @@ struct PlaybackSettingsView: View { if viewModel.videoStreams.isNotEmpty { Section(L10n.video) { ForEach(viewModel.videoStreams, id: \.displayTitle) { mediaStream in - ChevronButton(mediaStream.displayTitle ?? .emptyDash) - .onSelect { - router.route(to: \.mediaStreamInfo, mediaStream) - } + ChevronButton(mediaStream.displayTitle ?? .emptyDash) { + router.route(to: \.mediaStreamInfo, mediaStream) + } } } } @@ -78,10 +76,9 @@ struct PlaybackSettingsView: View { if viewModel.audioStreams.isNotEmpty { Section(L10n.audio) { ForEach(viewModel.audioStreams, id: \.displayTitle) { mediaStream in - ChevronButton(mediaStream.displayTitle ?? .emptyDash) - .onSelect { - router.route(to: \.mediaStreamInfo, mediaStream) - } + ChevronButton(mediaStream.displayTitle ?? .emptyDash) { + router.route(to: \.mediaStreamInfo, mediaStream) + } } } } @@ -89,10 +86,9 @@ struct PlaybackSettingsView: View { if viewModel.subtitleStreams.isNotEmpty { Section(L10n.subtitle) { ForEach(viewModel.subtitleStreams, id: \.displayTitle) { mediaStream in - ChevronButton(mediaStream.displayTitle ?? .emptyDash) - .onSelect { - router.route(to: \.mediaStreamInfo, mediaStream) - } + ChevronButton(mediaStream.displayTitle ?? .emptyDash) { + router.route(to: \.mediaStreamInfo, mediaStream) + } } } }