From adf4e5c75c42b3e6834d08be1ad20a9a2612c45a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Tue, 2 Dec 2025 12:31:26 +0800 Subject: [PATCH] Fix action button style on tvOS --- .../Views/Abstract/ViewModifiers.swift | 21 +++++++- .../Views/Dashboard/Cards/ProfileCard.swift | 50 +++++++++++++------ 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/ApplicationLibrary/Views/Abstract/ViewModifiers.swift b/ApplicationLibrary/Views/Abstract/ViewModifiers.swift index 09391b0..076b1c2 100644 --- a/ApplicationLibrary/Views/Abstract/ViewModifiers.swift +++ b/ApplicationLibrary/Views/Abstract/ViewModifiers.swift @@ -27,7 +27,10 @@ public extension View { @ViewBuilder func actionButtonStyle() -> some View { - if #available(iOS 26.0, macOS 26.0, tvOS 26.0, *) { + #if os(tvOS) + ActionButtonWrapper { self } + #else + if #available(iOS 26.0, macOS 26.0, *) { self.frame(width: 36, height: 36) .glassEffect(.regular.interactive(), in: .circle) } else { @@ -35,5 +38,21 @@ public extension View { .background(Color.secondary.opacity(0.1)) .clipShape(Circle()) } + #endif } } + +#if os(tvOS) +private struct ActionButtonWrapper: View { + @Environment(\.isFocused) private var isFocused + let content: () -> Content + + var body: some View { + content() + .frame(width: 36, height: 36) + .background(isFocused ? Color.secondary.opacity(0.3) : Color.secondary.opacity(0.1)) + .clipShape(Circle()) + .focusEffectDisabled() + } +} +#endif diff --git a/ApplicationLibrary/Views/Dashboard/Cards/ProfileCard.swift b/ApplicationLibrary/Views/Dashboard/Cards/ProfileCard.swift index eb100da..230f37f 100644 --- a/ApplicationLibrary/Views/Dashboard/Cards/ProfileCard.swift +++ b/ApplicationLibrary/Views/Dashboard/Cards/ProfileCard.swift @@ -101,24 +101,26 @@ public struct ProfileCard: View { Spacer() - Button { - viewModel.showNewProfile = true - } label: { - Image(systemName: "plus") - .font(.system(size: 16)) - } - .buttonStyle(.plain) - .actionButtonStyle() - - if !profileList.isEmpty { + HStack(spacing: actionButtonSpacing) { Button { - viewModel.showManageProfiles = true + viewModel.showNewProfile = true } label: { - Image(systemName: "line.3.horizontal") + Image(systemName: "plus") .font(.system(size: 16)) } .buttonStyle(.plain) .actionButtonStyle() + + if !profileList.isEmpty { + Button { + viewModel.showManageProfiles = true + } label: { + Image(systemName: "line.3.horizontal") + .font(.system(size: 16)) + } + .buttonStyle(.plain) + .actionButtonStyle() + } } } } @@ -146,9 +148,17 @@ public struct ProfileCard: View { } } + private var actionButtonSpacing: CGFloat { + #if os(tvOS) + 24 + #else + 12 + #endif + } + @ViewBuilder private func actionButtonsRow(for profile: ProfilePreview) -> some View { - HStack(spacing: 12) { + HStack(spacing: actionButtonSpacing) { editButton(for: profile) if profile.type == .remote { @@ -156,12 +166,14 @@ public struct ProfileCard: View { qrCodeButton(for: profile) } + #if !os(tvOS) ProfileShareButton($viewModel.alert, profile.origin) { Image(systemName: "square.and.arrow.up") .font(.system(size: 16)) } .buttonStyle(.plain) .actionButtonStyle() + #endif } } @@ -472,6 +484,14 @@ extension ProfileCard { _profile = State(initialValue: profile) } + private var actionButtonSpacing: CGFloat { + #if os(tvOS) + 24 + #else + 8 + #endif + } + var body: some View { HStack { Image(systemName: "line.3.horizontal") @@ -489,7 +509,7 @@ extension ProfileCard { Spacer() - HStack(spacing: 8) { + HStack(spacing: actionButtonSpacing) { if profile.type == .remote { Button { isUpdating = true @@ -532,6 +552,7 @@ extension ProfileCard { #endif } + #if !os(tvOS) ShareButtonCompat($viewModel.alert) { Image(systemName: "square.and.arrow.up") .font(.system(size: 16)) @@ -539,6 +560,7 @@ extension ProfileCard { try profile.origin.toContent().generateShareFile() } .actionButtonStyle() + #endif Button { Task {