Replace sheets with navigation destinations on tvOS
This commit is contained in:
@@ -61,20 +61,53 @@ import SwiftUI
|
||||
#if os(iOS) || os(tvOS)
|
||||
.toolbar {
|
||||
toolbar
|
||||
}.sheet(isPresented: $showGroups) {
|
||||
}
|
||||
#if os(tvOS)
|
||||
.navigationDestination(isPresented: $showGroups) {
|
||||
GroupListView()
|
||||
.navigationTitle("Groups")
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
BackButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationDestination(isPresented: $showConnections) {
|
||||
ConnectionListView()
|
||||
.navigationTitle("Connections")
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
BackButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationDestination(isPresented: $showCardManagement) {
|
||||
CardManagementView(onDisappear: {
|
||||
cardConfigurationVersion += 1
|
||||
})
|
||||
.navigationTitle("Dashboard Items")
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
BackButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
.sheet(isPresented: $showGroups) {
|
||||
groupsSheetContent
|
||||
}.sheet(isPresented: $showConnections) {
|
||||
connectionsSheetContent
|
||||
}.sheet(isPresented: $showCardManagement, onDismiss: {
|
||||
cardConfigurationVersion += 1
|
||||
}, content: {
|
||||
if #available(iOS 16.0, tvOS 17.0, *) {
|
||||
if #available(iOS 16.0, *) {
|
||||
CardManagementSheet().presentationDetents([.large]).presentationDragIndicator(.visible)
|
||||
} else {
|
||||
CardManagementSheet()
|
||||
}
|
||||
})
|
||||
#endif
|
||||
#endif
|
||||
.onAppear {
|
||||
if ApplicationLibrary.inPreview {
|
||||
environments.commandClient.connect()
|
||||
|
||||
@@ -97,6 +97,55 @@ import SwiftUI
|
||||
}
|
||||
}
|
||||
|
||||
#if os(tvOS)
|
||||
@MainActor public struct CardManagementView: View {
|
||||
@StateObject private var configuration = DashboardCardConfiguration()
|
||||
private let onDisappear: (() -> Void)?
|
||||
|
||||
public init(onDisappear: (() -> Void)? = nil) {
|
||||
self.onDisappear = onDisappear
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
Group {
|
||||
if configuration.isLoading {
|
||||
ProgressView()
|
||||
} else {
|
||||
List {
|
||||
ForEach(configuration.cardOrder) { card in
|
||||
CardRow(
|
||||
card: card,
|
||||
isEnabled: configuration.isEnabled(card),
|
||||
onToggle: {
|
||||
configuration.toggleCard(card)
|
||||
}
|
||||
)
|
||||
}
|
||||
.onMove { source, destination in
|
||||
Task {
|
||||
await configuration.moveCard(from: source, to: destination)
|
||||
}
|
||||
}
|
||||
}
|
||||
.applyContentMargins()
|
||||
}
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button("Reset", role: .destructive) {
|
||||
Task {
|
||||
await configuration.resetToDefault()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
onDisappear?()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private struct CardRow: View {
|
||||
let card: DashboardCard
|
||||
let isEnabled: Bool
|
||||
|
||||
@@ -32,6 +32,44 @@ public struct ProfileCard: View {
|
||||
}
|
||||
}
|
||||
.disabled(viewModel.isUpdating)
|
||||
#if os(tvOS)
|
||||
.navigationDestination(isPresented: $viewModel.showNewProfile) {
|
||||
NewProfileContentView(onDisappear: {
|
||||
environments.profileUpdate.send()
|
||||
})
|
||||
.environmentObject(environments)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
BackButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationDestination(isPresented: $viewModel.showManageProfiles) {
|
||||
ManageProfilesView()
|
||||
.environmentObject(environments)
|
||||
.navigationTitle("Manage profiles")
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
BackButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationDestination(item: $viewModel.profileToEdit) { profile in
|
||||
EditProfileView()
|
||||
.environmentObject(profile)
|
||||
.environmentObject(environments)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
BackButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $viewModel.showQRCode) {
|
||||
if let profile = selectedProfile, let remoteURL = profile.remoteURL {
|
||||
QRCodeSheet(profileName: profile.name, remoteURL: remoteURL)
|
||||
}
|
||||
}
|
||||
#else
|
||||
.sheet(isPresented: $viewModel.showNewProfile, onDismiss: {
|
||||
environments.profileUpdate.send()
|
||||
}, content: {
|
||||
@@ -44,13 +82,14 @@ public struct ProfileCard: View {
|
||||
.sheet(item: $viewModel.profileToEdit) { profile in
|
||||
editProfileSheet(for: profile)
|
||||
}
|
||||
#if os(iOS) || os(tvOS)
|
||||
#if os(iOS)
|
||||
.sheet(isPresented: $viewModel.showQRCode) {
|
||||
if let profile = selectedProfile, let remoteURL = profile.remoteURL {
|
||||
QRCodeSheet(profileName: profile.name, remoteURL: remoteURL)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
.alert($viewModel.alert)
|
||||
}
|
||||
|
||||
@@ -326,6 +365,41 @@ extension ProfileCard {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - NewProfileContentView (tvOS)
|
||||
|
||||
#if os(tvOS)
|
||||
extension ProfileCard {
|
||||
@MainActor
|
||||
struct NewProfileContentView: View {
|
||||
@EnvironmentObject private var environments: ExtensionEnvironments
|
||||
@State private var createdProfile: Profile?
|
||||
private let onDisappear: (() -> Void)?
|
||||
|
||||
init(onDisappear: (() -> Void)? = nil) {
|
||||
self.onDisappear = onDisappear
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let profile = createdProfile {
|
||||
EditProfileView()
|
||||
.environmentObject(profile)
|
||||
.environmentObject(environments)
|
||||
} else {
|
||||
NewProfileView { profile in
|
||||
createdProfile = profile
|
||||
}
|
||||
.environmentObject(environments)
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
onDisappear?()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: - ManageProfilesView
|
||||
|
||||
extension ProfileCard {
|
||||
|
||||
@@ -35,9 +35,24 @@ public struct DashboardView: View {
|
||||
.onChangeCompat(of: importRemoteProfile.wrappedValue) { _ in
|
||||
handleImportRemoteProfile()
|
||||
}
|
||||
#if os(tvOS)
|
||||
.navigationDestination(item: $importRemoteProfileRequest) { request in
|
||||
NewProfileView(request)
|
||||
.environmentObject(environments)
|
||||
.onDisappear {
|
||||
environments.profileUpdate.send()
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
BackButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
.sheet(item: $importRemoteProfileRequest) { request in
|
||||
importRemoteProfileSheet(for: request)
|
||||
}
|
||||
#endif
|
||||
#if os(macOS)
|
||||
.onChangeCompat(of: controlActiveState) { state in
|
||||
guard state != .inactive, Variant.useSystemExtension, !coordinator.isLoading else { return }
|
||||
|
||||
Reference in New Issue
Block a user