diff --git a/Yattee/Views/Components/TVSidebarDetailContainer.swift b/Yattee/Views/Components/TVSidebarDetailContainer.swift index 593ac97b..8bf0cf6b 100644 --- a/Yattee/Views/Components/TVSidebarDetailContainer.swift +++ b/Yattee/Views/Components/TVSidebarDetailContainer.swift @@ -9,22 +9,24 @@ #if os(tvOS) import SwiftUI -struct TVSidebarDetailContainer: View { +struct TVSidebarDetailContainer: View { let content: Content - let bottomAction: BottomAction var systemImage: String? var title: String? + var showsDismissButton: Bool + + @Environment(\.dismiss) private var dismiss init( systemImage: String? = nil, title: String? = nil, - @ViewBuilder bottomAction: () -> BottomAction = { EmptyView() }, + showsDismissButton: Bool = false, @ViewBuilder content: () -> Content ) { self.content = content() - self.bottomAction = bottomAction() self.systemImage = systemImage self.title = title + self.showsDismissButton = showsDismissButton } var body: some View { @@ -32,30 +34,19 @@ struct TVSidebarDetailContainer: View { .focusSection() .safeAreaInset(edge: .leading) { if let systemImage { - VStack(spacing: 0) { - Spacer() - VStack(spacing: 16) { - Image(systemName: systemImage) - .font(.system(size: 80)) + VStack(spacing: 16) { + Image(systemName: systemImage) + .font(.system(size: 80)) + .foregroundStyle(.secondary) + if let title { + Text(title) + .font(.title3) + .fontWeight(.semibold) .foregroundStyle(.secondary) - if let title { - Text(title) - .font(.title3) - .fontWeight(.semibold) - .foregroundStyle(.secondary) - .multilineTextAlignment(.center) - } + .multilineTextAlignment(.center) } - .allowsHitTesting(false) - - if BottomAction.self != EmptyView.self { - bottomAction - .padding(.top, 40) - .focusSection() - } - - Spacer() } + .allowsHitTesting(false) .frame(width: 400) } else { Spacer() @@ -63,22 +54,17 @@ struct TVSidebarDetailContainer: View { .allowsHitTesting(false) } } - } -} - -struct TVDismissBottomButton: View { - var title: String = String(localized: "common.done") - var systemImage: String = "chevron.backward" - - @Environment(\.dismiss) private var dismiss - - var body: some View { - Button { - dismiss() - } label: { - Label(title, systemImage: systemImage) - } - .buttonStyle(TVSettingsButtonStyle()) + .toolbar { + if showsDismissButton { + ToolbarItem(placement: .cancellationAction) { + Button { + dismiss() + } label: { + Label(String(localized: "common.done"), systemImage: "chevron.backward") + } + } + } + } } } #endif diff --git a/Yattee/Views/Settings/AboutView.swift b/Yattee/Views/Settings/AboutView.swift index f128d39c..3f800c6f 100644 --- a/Yattee/Views/Settings/AboutView.swift +++ b/Yattee/Views/Settings/AboutView.swift @@ -23,19 +23,34 @@ struct AboutView: View { SettingsFormSection { #if os(tvOS) NavigationLink { - ContributorsView() + TVSidebarDetailContainer( + systemImage: "person.3", + title: String(localized: "settings.contributors.title") + ) { + ContributorsView() + } } label: { Label(String(localized: "settings.contributors.title"), systemImage: "person.3") } NavigationLink { - TranslationContributorsView() + TVSidebarDetailContainer( + systemImage: "globe", + title: String(localized: "settings.translators.title") + ) { + TranslationContributorsView() + } } label: { Label(String(localized: "settings.translators.title"), systemImage: "globe") } NavigationLink { - AcknowledgementsView() + TVSidebarDetailContainer( + systemImage: "heart.text.square", + title: String(localized: "settings.acknowledgements.title") + ) { + AcknowledgementsView() + } } label: { Label(String(localized: "settings.acknowledgements.title"), systemImage: "heart.text.square") } @@ -58,7 +73,13 @@ struct AboutView: View { SettingsFormSection { #if os(tvOS) NavigationLink { - DeviceCapabilitiesView() + TVSidebarDetailContainer( + systemImage: "cpu", + title: String(localized: "settings.advanced.deviceCapabilities"), + showsDismissButton: true + ) { + DeviceCapabilitiesView() + } } label: { Label(String(localized: "settings.advanced.deviceCapabilities"), systemImage: "cpu") } diff --git a/Yattee/Views/Settings/AcknowledgementsView.swift b/Yattee/Views/Settings/AcknowledgementsView.swift index de988cea..5ed9105f 100644 --- a/Yattee/Views/Settings/AcknowledgementsView.swift +++ b/Yattee/Views/Settings/AcknowledgementsView.swift @@ -26,9 +26,6 @@ struct AcknowledgementsView: View { @ViewBuilder private func dependencyLink(_ name: String, url: String) -> some View { - #if os(tvOS) - Text(name) - #else Button { if let url = URL(string: url) { openURL(url) @@ -37,15 +34,16 @@ struct AcknowledgementsView: View { HStack { Text(name) Spacer() + #if !os(tvOS) Image(systemName: "arrow.up.right") .foregroundStyle(.secondary) + #endif } .contentShape(Rectangle()) } #if os(macOS) .buttonStyle(.plain) #endif - #endif } } diff --git a/Yattee/Views/Settings/EditSourceView.swift b/Yattee/Views/Settings/EditSourceView.swift index b48f2b26..fa42d25f 100644 --- a/Yattee/Views/Settings/EditSourceView.swift +++ b/Yattee/Views/Settings/EditSourceView.swift @@ -242,7 +242,8 @@ private struct EditRemoteServerContent: View { #if os(tvOS) TVSidebarDetailContainer( systemImage: "person.2", - title: String(localized: "sources.import.subscriptions") + title: String(localized: "sources.import.subscriptions"), + showsDismissButton: true ) { ImportSubscriptionsView(instance: instance) } @@ -258,7 +259,8 @@ private struct EditRemoteServerContent: View { #if os(tvOS) TVSidebarDetailContainer( systemImage: "list.bullet.rectangle", - title: String(localized: "sources.import.playlists") + title: String(localized: "sources.import.playlists"), + showsDismissButton: true ) { ImportPlaylistsView(instance: instance) } diff --git a/Yattee/Views/Settings/ImportPlaylistsView.swift b/Yattee/Views/Settings/ImportPlaylistsView.swift index cc0af712..d6bca809 100644 --- a/Yattee/Views/Settings/ImportPlaylistsView.swift +++ b/Yattee/Views/Settings/ImportPlaylistsView.swift @@ -11,7 +11,6 @@ struct ImportPlaylistsView: View { let instance: Instance @Environment(\.appEnvironment) private var appEnvironment - @Environment(\.dismiss) private var dismiss @State private var playlists: [Playlist] = [] @State private var importedPlaylistIDs: Set = [] @@ -60,15 +59,6 @@ struct ImportPlaylistsView: View { .navigationBarTitleDisplayMode(.inline) #endif .toolbar { - #if os(tvOS) - ToolbarItem(placement: .cancellationAction) { - Button { - dismiss() - } label: { - Label(String(localized: "common.done"), systemImage: "chevron.backward") - } - } - #endif if !unimportedPlaylists.isEmpty && importingPlaylistID == nil { ToolbarItem(placement: .primaryAction) { Button { diff --git a/Yattee/Views/Settings/ImportSubscriptionsView.swift b/Yattee/Views/Settings/ImportSubscriptionsView.swift index ee12263f..6b81de1c 100644 --- a/Yattee/Views/Settings/ImportSubscriptionsView.swift +++ b/Yattee/Views/Settings/ImportSubscriptionsView.swift @@ -11,7 +11,6 @@ struct ImportSubscriptionsView: View { let instance: Instance @Environment(\.appEnvironment) private var appEnvironment - @Environment(\.dismiss) private var dismiss @State private var channels: [Channel] = [] @State private var subscribedChannelIDs: Set = [] @@ -51,15 +50,6 @@ struct ImportSubscriptionsView: View { .navigationBarTitleDisplayMode(.inline) #endif .toolbar { - #if os(tvOS) - ToolbarItem(placement: .cancellationAction) { - Button { - dismiss() - } label: { - Label(String(localized: "common.done"), systemImage: "chevron.backward") - } - } - #endif if !unsubscribedChannels.isEmpty { ToolbarItem(placement: .primaryAction) { Button { diff --git a/Yattee/Views/Settings/TranslationContributorsView.swift b/Yattee/Views/Settings/TranslationContributorsView.swift index b4b2f730..bcab52a8 100644 --- a/Yattee/Views/Settings/TranslationContributorsView.swift +++ b/Yattee/Views/Settings/TranslationContributorsView.swift @@ -47,6 +47,16 @@ struct TranslationContributorsView: View { } private func contributorRow(_ contributor: TranslationContributor) -> some View { + #if os(tvOS) + Button {} label: { + contributorRowContent(contributor) + } + #else + contributorRowContent(contributor) + #endif + } + + private func contributorRowContent(_ contributor: TranslationContributor) -> some View { HStack(spacing: 12) { // Avatar LazyImage(url: contributor.gravatarURL) { state in