Fix for tvOS

This commit is contained in:
世界
2025-11-27 18:55:10 +08:00
parent 0bfb6d2516
commit 22de256d13
4 changed files with 155 additions and 104 deletions
@@ -128,7 +128,6 @@ public func FormNavigationLink(@ViewBuilder destination: () -> some View, @ViewB
.toolbar { .toolbar {
ToolbarItemGroup(placement: .topBarLeading) { ToolbarItemGroup(placement: .topBarLeading) {
BackButton() BackButton()
.tint(.accentColor)
} }
} }
}, label: label) }, label: label)
@@ -26,6 +26,34 @@ public struct NavigationButtonsView: View {
} }
public var body: some View { public var body: some View {
#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")
}
}
if showGroupsButton {
Button {
onGroupsTap()
} label: {
Image(systemName: "rectangle.3.group.fill")
}
}
}
}
#else
private var iOSBody: some View {
HStack(spacing: 12) { HStack(spacing: 12) {
if showConnectionsButton { if showConnectionsButton {
Divider() Divider()
@@ -57,4 +85,5 @@ public struct NavigationButtonsView: View {
} }
} }
} }
#endif
} }
@@ -3,8 +3,7 @@ import Libbox
import Library import Library
import SwiftUI import SwiftUI
@MainActor @MainActor public struct ActiveDashboardView: View {
public struct ActiveDashboardView: View {
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
@EnvironmentObject private var environments: ExtensionEnvironments @EnvironmentObject private var environments: ExtensionEnvironments
@EnvironmentObject private var profile: ExtensionProfile @EnvironmentObject private var profile: ExtensionProfile
@@ -25,35 +24,48 @@ public struct ActiveDashboardView: View {
public var body: some View { public var body: some View {
if coordinator.isLoading { if coordinator.isLoading {
ProgressView() ProgressView().onAppear {
.onAppear { coordinator.onEmptyProfilesChange = {
coordinator.onEmptyProfilesChange = { environments.emptyProfiles = $0 } environments.emptyProfiles = $0
Task { await coordinator.reload() } }
Task {
await coordinator.reload()
}
} }
} else { } else {
content content.onAppear {
.onAppear { guard !ApplicationLibrary.inPreview else {
guard !ApplicationLibrary.inPreview else { return } 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()
} }
.onChangeCompat(of: profile.status) { status in
guard !ApplicationLibrary.inPreview, status == .connected else { return }
Task { await coordinator.reloadSystemProxy() }
} }
} }
} }
@ViewBuilder @ViewBuilder private var content: some View {
private var content: some View {
overviewPage overviewPage
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS)
.toolbar { toolbar } .toolbar {
.sheet(isPresented: $showGroups) { toolbar
}.sheet(isPresented: $showGroups) {
groupsSheetContent groupsSheetContent
} }.sheet(isPresented: $showConnections) {
.sheet(isPresented: $showConnections) {
connectionsSheetContent connectionsSheetContent
} }.sheet(isPresented: $showCardManagement, onDismiss: {
cardConfigurationVersion += 1
}, content: {
CardManagementSheet().presentationDetents([.large]).presentationDragIndicator(.visible)
})
#endif #endif
.onAppear { .onAppear {
if ApplicationLibrary.inPreview { if ApplicationLibrary.inPreview {
@@ -61,19 +73,25 @@ public struct ActiveDashboardView: View {
} else { } else {
environments.connect() environments.connect()
} }
}.onChangeCompat(of: scenePhase) {
phase in
guard phase == .active else {
return
} }
.onChangeCompat(of: scenePhase) { phase in
guard phase == .active else { return }
environments.connect() 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() environments.connect()
}.onReceive(environments.profileUpdate) {
_ in
Task {
await coordinator.reload()
} }
.onReceive(environments.profileUpdate) { _ in }.onReceive(environments.selectedProfileUpdate) {
Task { await coordinator.reload() } _ in
}
.onReceive(environments.selectedProfileUpdate) { _ in
Task { Task {
await coordinator.updateSelectedProfile() await coordinator.updateSelectedProfile()
if profile.status.isConnected { if profile.status.isConnected {
@@ -82,24 +100,23 @@ public struct ActiveDashboardView: View {
} }
} }
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS)
.onReceive(environments.commandClient.$groups) { _ in .onReceive(environments.commandClient.$groups) {
_ in
updateButtonVisibility() updateButtonVisibility()
} }.onReceive(environments.commandClient.$connections) {
.onReceive(environments.commandClient.$connections) { _ in _ in
updateButtonVisibility() updateButtonVisibility()
} }.onReceive(profile.$status) {
.onReceive(profile.$status) { _ in _ in
updateButtonVisibility() updateButtonVisibility()
} }.onAppear {
.onAppear {
updateButtonVisibility() updateButtonVisibility()
} }
#endif #endif
.alertBinding($coordinator.alert) .alertBinding($coordinator.alert)
} }
@ViewBuilder @ViewBuilder private var overviewPage: some View {
private var overviewPage: some View {
OverviewView( OverviewView(
$coordinator.profileList, $coordinator.profileList,
$coordinator.selectedProfileID, $coordinator.selectedProfileID,
@@ -123,28 +140,21 @@ public struct ActiveDashboardView: View {
} }
#endif #endif
@ToolbarContentBuilder @ToolbarContentBuilder private var toolbar: some ToolbarContent {
private var toolbar: some ToolbarContent {
#if os(tvOS) #if os(tvOS)
ToolbarItem(placement: .topBarLeading) { ToolbarItem(placement: .topBarLeading) {
navigationButtons navigationButtons
} }
#endif #endif
ToolbarItem(placement: .topBarTrailing) { ToolbarItemGroup(placement: .topBarTrailing) {
if #available(iOS 16.0, tvOS 17.0, *) { if #available(iOS 16.0, tvOS 17.0, *) {
cardManagementButton cardManagementButton
} }
} #if os(tvOS)
ToolbarItem(placement: .topBarTrailing) {
#if os(iOS)
if #available(iOS 26.0, *), !Variant.debugNoIOS26 {
EmptyView()
} else {
StartStopButton() StartStopButton()
}
#else #else
HStack(spacing: 12) { if #available(iOS 26.0, *), !Variant.debugNoIOS26 {
Divider() } else {
StartStopButton() StartStopButton()
} }
#endif #endif
@@ -158,8 +168,12 @@ public struct ActiveDashboardView: View {
showConnectionsButton: buttonState.showConnectionsButton, showConnectionsButton: buttonState.showConnectionsButton,
groupsCount: buttonState.groupsCount, groupsCount: buttonState.groupsCount,
connectionsCount: buttonState.connectionsCount, connectionsCount: buttonState.connectionsCount,
onGroupsTap: { showGroups = true }, onGroupsTap: {
onConnectionsTap: { showConnections = true } showGroups = true
},
onConnectionsTap: {
showConnections = true
}
) )
} }
#endif #endif
@@ -174,11 +188,9 @@ public struct ActiveDashboardView: View {
ConnectionsSheetContent() ConnectionsSheetContent()
} }
@available(iOS 16.0, tvOS 17.0, *) @available(iOS 16.0, *) @ViewBuilder private var cardManagementButton: some View {
@ViewBuilder
private var cardManagementButton: some View {
Menu {
#if os(iOS) #if os(iOS)
Menu {
if !isTabViewBottomAccessoryAvailable { if !isTabViewBottomAccessoryAvailable {
if buttonState.showGroupsButton { if buttonState.showGroupsButton {
Button { Button {
@@ -198,7 +210,6 @@ public struct ActiveDashboardView: View {
Divider() Divider()
} }
} }
#endif
Button { Button {
showCardManagement = true showCardManagement = true
} label: { } label: {
@@ -207,13 +218,13 @@ public struct ActiveDashboardView: View {
} label: { } label: {
Label("Others", systemImage: "line.3.horizontal.circle") Label("Others", systemImage: "line.3.horizontal.circle")
} }
.sheet(isPresented: $showCardManagement, onDismiss: { #elseif os(tvOS)
cardConfigurationVersion += 1 Button {
}, content: { showCardManagement = true
CardManagementSheet() } label: {
.presentationDetents([.large]) Image(systemName: "line.3.horizontal.circle")
.presentationDragIndicator(.visible) }
}) #endif
} }
#endif #endif
} }
@@ -12,14 +12,22 @@ public struct StartStopButton: View {
viewBuilder { viewBuilder {
if ApplicationLibrary.inPreview { if ApplicationLibrary.inPreview {
Button {} label: { Button {} label: {
#if os(tvOS)
Image(systemName: "stop.fill")
#else
Label("Stop", systemImage: "stop.fill") Label("Stop", systemImage: "stop.fill")
#endif
} }
.labelStyle(.iconOnly) .labelStyle(.iconOnly)
} else if let profile = environments.extensionProfile { } else if let profile = environments.extensionProfile {
ToggleConnectionButton().environmentObject(profile) ToggleConnectionButton().environmentObject(profile)
} else { } else {
Button {} label: { Button {} label: {
#if os(tvOS)
Image(systemName: "play.fill")
#else
Label("Start", systemImage: "play.fill") Label("Start", systemImage: "play.fill")
#endif
} }
.labelStyle(.iconOnly) .labelStyle(.iconOnly)
.disabled(true) .disabled(true)
@@ -63,6 +71,12 @@ public struct StartStopButton: View {
} }
} }
.animation(.spring(response: 0.35, dampingFraction: 0.75), value: profile.status.isConnectedStrict) .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 #else
HStack(spacing: 8) { HStack(spacing: 8) {
if profile.status.isConnectedStrict, let duration = runtimeDuration { if profile.status.isConnectedStrict, let duration = runtimeDuration {
@@ -89,8 +103,6 @@ public struct StartStopButton: View {
.labelStyle(.iconOnly) .labelStyle(.iconOnly)
#if os(iOS) #if os(iOS)
.modifier(PrimaryTintModifier()) .modifier(PrimaryTintModifier())
#else
.tint(.primary)
#endif #endif
.disabled(!profile.status.isEnabled) .disabled(!profile.status.isEnabled)
.alertBinding($alert) .alertBinding($alert)