From 22de256d1330ce743ba5be19a1b2ea64225fdabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Thu, 27 Nov 2025 18:55:10 +0800 Subject: [PATCH] Fix for tvOS --- .../Views/Abstract/FormItem.swift | 1 - .../Abstract/NavigationButtonsView.swift | 83 +++++++--- .../Views/Dashboard/ActiveDashboardView.swift | 155 ++++++++++-------- .../Components/StartStopButton.swift | 20 ++- 4 files changed, 155 insertions(+), 104 deletions(-) diff --git a/ApplicationLibrary/Views/Abstract/FormItem.swift b/ApplicationLibrary/Views/Abstract/FormItem.swift index 08da31f..73d8974 100644 --- a/ApplicationLibrary/Views/Abstract/FormItem.swift +++ b/ApplicationLibrary/Views/Abstract/FormItem.swift @@ -128,7 +128,6 @@ public func FormNavigationLink(@ViewBuilder destination: () -> some View, @ViewB .toolbar { ToolbarItemGroup(placement: .topBarLeading) { BackButton() - .tint(.accentColor) } } }, label: label) diff --git a/ApplicationLibrary/Views/Abstract/NavigationButtonsView.swift b/ApplicationLibrary/Views/Abstract/NavigationButtonsView.swift index 9ec2edd..f8b348a 100644 --- a/ApplicationLibrary/Views/Abstract/NavigationButtonsView.swift +++ b/ApplicationLibrary/Views/Abstract/NavigationButtonsView.swift @@ -26,35 +26,64 @@ public struct NavigationButtonsView: View { } public var body: some View { - HStack(spacing: 12) { - if showConnectionsButton { - Divider() - Text(verbatim: "\(connectionsCount)") - .font(.subheadline) - .foregroundStyle(.secondary) - .fixedSize() - Button { - onConnectionsTap() - } label: { - Label("Connections", systemImage: "list.bullet.rectangle.portrait.fill") + #if os(tvOS) + tvOSBody + #else + iOSBody + #endif + } + + #if os(tvOS) + private var tvOSBody: some View { + viewBuilder { + if showConnectionsButton { + Button { + onConnectionsTap() + } label: { + Image(systemName: "list.bullet.rectangle.portrait.fill") + } } - .labelStyle(.iconOnly) - .foregroundStyle(.primary) - } - if showGroupsButton { - Divider() - Text(verbatim: "\(groupsCount)") - .font(.subheadline) - .foregroundStyle(.secondary) - .fixedSize() - Button { - onGroupsTap() - } label: { - Label("Groups", systemImage: "rectangle.3.group.fill") + if showGroupsButton { + Button { + onGroupsTap() + } label: { + Image(systemName: "rectangle.3.group.fill") + } } - .labelStyle(.iconOnly) - .foregroundStyle(.primary) } } - } + #else + private var iOSBody: some View { + HStack(spacing: 12) { + if showConnectionsButton { + Divider() + Text(verbatim: "\(connectionsCount)") + .font(.subheadline) + .foregroundStyle(.secondary) + .fixedSize() + Button { + onConnectionsTap() + } label: { + Label("Connections", systemImage: "list.bullet.rectangle.portrait.fill") + } + .labelStyle(.iconOnly) + .foregroundStyle(.primary) + } + if showGroupsButton { + Divider() + Text(verbatim: "\(groupsCount)") + .font(.subheadline) + .foregroundStyle(.secondary) + .fixedSize() + Button { + onGroupsTap() + } label: { + Label("Groups", systemImage: "rectangle.3.group.fill") + } + .labelStyle(.iconOnly) + .foregroundStyle(.primary) + } + } + } + #endif } diff --git a/ApplicationLibrary/Views/Dashboard/ActiveDashboardView.swift b/ApplicationLibrary/Views/Dashboard/ActiveDashboardView.swift index 8df3e7e..0a54644 100644 --- a/ApplicationLibrary/Views/Dashboard/ActiveDashboardView.swift +++ b/ApplicationLibrary/Views/Dashboard/ActiveDashboardView.swift @@ -3,8 +3,7 @@ import Libbox import Library import SwiftUI -@MainActor -public struct ActiveDashboardView: View { +@MainActor public struct ActiveDashboardView: View { @Environment(\.scenePhase) private var scenePhase @EnvironmentObject private var environments: ExtensionEnvironments @EnvironmentObject private var profile: ExtensionProfile @@ -25,35 +24,48 @@ public struct ActiveDashboardView: View { public var body: some View { if coordinator.isLoading { - ProgressView() - .onAppear { - coordinator.onEmptyProfilesChange = { environments.emptyProfiles = $0 } - Task { await coordinator.reload() } + ProgressView().onAppear { + coordinator.onEmptyProfilesChange = { + environments.emptyProfiles = $0 } + Task { + await coordinator.reload() + } + } } else { - content - .onAppear { - guard !ApplicationLibrary.inPreview else { return } - Task { await coordinator.reloadSystemProxy() } + content.onAppear { + guard !ApplicationLibrary.inPreview else { + return } - .onChangeCompat(of: profile.status) { status in - guard !ApplicationLibrary.inPreview, status == .connected else { return } - Task { await coordinator.reloadSystemProxy() } + Task { + await coordinator.reloadSystemProxy() } + }.onChangeCompat(of: profile.status) { + status in + guard !ApplicationLibrary.inPreview, status == .connected else { + return + } + Task { + await coordinator.reloadSystemProxy() + } + } } } - @ViewBuilder - private var content: some View { + @ViewBuilder private var content: some View { overviewPage #if os(iOS) || os(tvOS) - .toolbar { toolbar } - .sheet(isPresented: $showGroups) { + .toolbar { + toolbar + }.sheet(isPresented: $showGroups) { groupsSheetContent - } - .sheet(isPresented: $showConnections) { + }.sheet(isPresented: $showConnections) { connectionsSheetContent - } + }.sheet(isPresented: $showCardManagement, onDismiss: { + cardConfigurationVersion += 1 + }, content: { + CardManagementSheet().presentationDetents([.large]).presentationDragIndicator(.visible) + }) #endif .onAppear { if ApplicationLibrary.inPreview { @@ -61,19 +73,25 @@ public struct ActiveDashboardView: View { } else { environments.connect() } - } - .onChangeCompat(of: scenePhase) { phase in - guard phase == .active else { return } + }.onChangeCompat(of: scenePhase) { + phase in + guard phase == .active else { + return + } environments.connect() - } - .onChangeCompat(of: profile.status) { status in - guard status.isConnected else { return } + }.onChangeCompat(of: profile.status) { + status in + guard status.isConnected else { + return + } environments.connect() - } - .onReceive(environments.profileUpdate) { _ in - Task { await coordinator.reload() } - } - .onReceive(environments.selectedProfileUpdate) { _ in + }.onReceive(environments.profileUpdate) { + _ in + Task { + await coordinator.reload() + } + }.onReceive(environments.selectedProfileUpdate) { + _ in Task { await coordinator.updateSelectedProfile() if profile.status.isConnected { @@ -82,24 +100,23 @@ public struct ActiveDashboardView: View { } } #if os(iOS) || os(tvOS) - .onReceive(environments.commandClient.$groups) { _ in + .onReceive(environments.commandClient.$groups) { + _ in updateButtonVisibility() - } - .onReceive(environments.commandClient.$connections) { _ in + }.onReceive(environments.commandClient.$connections) { + _ in updateButtonVisibility() - } - .onReceive(profile.$status) { _ in + }.onReceive(profile.$status) { + _ in updateButtonVisibility() - } - .onAppear { + }.onAppear { updateButtonVisibility() } #endif .alertBinding($coordinator.alert) } - @ViewBuilder - private var overviewPage: some View { + @ViewBuilder private var overviewPage: some View { OverviewView( $coordinator.profileList, $coordinator.selectedProfileID, @@ -123,28 +140,21 @@ public struct ActiveDashboardView: View { } #endif - @ToolbarContentBuilder - private var toolbar: some ToolbarContent { + @ToolbarContentBuilder private var toolbar: some ToolbarContent { #if os(tvOS) ToolbarItem(placement: .topBarLeading) { navigationButtons } #endif - ToolbarItem(placement: .topBarTrailing) { + ToolbarItemGroup(placement: .topBarTrailing) { if #available(iOS 16.0, tvOS 17.0, *) { cardManagementButton } - } - ToolbarItem(placement: .topBarTrailing) { - #if os(iOS) - if #available(iOS 26.0, *), !Variant.debugNoIOS26 { - EmptyView() - } else { - StartStopButton() - } + #if os(tvOS) + StartStopButton() #else - HStack(spacing: 12) { - Divider() + if #available(iOS 26.0, *), !Variant.debugNoIOS26 { + } else { StartStopButton() } #endif @@ -158,8 +168,12 @@ public struct ActiveDashboardView: View { showConnectionsButton: buttonState.showConnectionsButton, groupsCount: buttonState.groupsCount, connectionsCount: buttonState.connectionsCount, - onGroupsTap: { showGroups = true }, - onConnectionsTap: { showConnections = true } + onGroupsTap: { + showGroups = true + }, + onConnectionsTap: { + showConnections = true + } ) } #endif @@ -174,11 +188,9 @@ public struct ActiveDashboardView: View { ConnectionsSheetContent() } - @available(iOS 16.0, tvOS 17.0, *) - @ViewBuilder - private var cardManagementButton: some View { - Menu { - #if os(iOS) + @available(iOS 16.0, *) @ViewBuilder private var cardManagementButton: some View { + #if os(iOS) + Menu { if !isTabViewBottomAccessoryAvailable { if buttonState.showGroupsButton { Button { @@ -198,22 +210,21 @@ public struct ActiveDashboardView: View { Divider() } } - #endif + Button { + showCardManagement = true + } label: { + Label("Dashboard Items", systemImage: "square.grid.2x2") + } + } label: { + Label("Others", systemImage: "line.3.horizontal.circle") + } + #elseif os(tvOS) Button { showCardManagement = true } label: { - Label("Dashboard Items", systemImage: "square.grid.2x2") + Image(systemName: "line.3.horizontal.circle") } - } label: { - Label("Others", systemImage: "line.3.horizontal.circle") - } - .sheet(isPresented: $showCardManagement, onDismiss: { - cardConfigurationVersion += 1 - }, content: { - CardManagementSheet() - .presentationDetents([.large]) - .presentationDragIndicator(.visible) - }) + #endif } #endif } diff --git a/ApplicationLibrary/Views/Dashboard/Components/StartStopButton.swift b/ApplicationLibrary/Views/Dashboard/Components/StartStopButton.swift index 71b551f..2030626 100644 --- a/ApplicationLibrary/Views/Dashboard/Components/StartStopButton.swift +++ b/ApplicationLibrary/Views/Dashboard/Components/StartStopButton.swift @@ -12,14 +12,22 @@ public struct StartStopButton: View { viewBuilder { if ApplicationLibrary.inPreview { Button {} label: { - Label("Stop", systemImage: "stop.fill") + #if os(tvOS) + Image(systemName: "stop.fill") + #else + Label("Stop", systemImage: "stop.fill") + #endif } .labelStyle(.iconOnly) } else if let profile = environments.extensionProfile { ToggleConnectionButton().environmentObject(profile) } else { Button {} label: { - Label("Start", systemImage: "play.fill") + #if os(tvOS) + Image(systemName: "play.fill") + #else + Label("Start", systemImage: "play.fill") + #endif } .labelStyle(.iconOnly) .disabled(true) @@ -63,6 +71,12 @@ public struct StartStopButton: View { } } .animation(.spring(response: 0.35, dampingFraction: 0.75), value: profile.status.isConnectedStrict) + #elseif os(tvOS) + if !profile.status.isConnected { + Image(systemName: "play.fill") + } else { + Image(systemName: "stop.fill") + } #else HStack(spacing: 8) { if profile.status.isConnectedStrict, let duration = runtimeDuration { @@ -89,8 +103,6 @@ public struct StartStopButton: View { .labelStyle(.iconOnly) #if os(iOS) .modifier(PrimaryTintModifier()) - #else - .tint(.primary) #endif .disabled(!profile.status.isEnabled) .alertBinding($alert)