mirror of
https://github.com/yattee/yattee.git
synced 2026-05-12 18:35:05 +00:00
Fix tvOS soft-lock in import views when no rows are focusable
When all playlists/subscriptions were imported, every row collapsed to a non-focusable checkmark and the Add All toolbar item disappeared, leaving the view with no focusable element. The Menu button then closed the app instead of popping the navigation stack. Wrap the import destinations in TVSidebarDetailContainer for visual consistency and add a Done toolbar item (cancellationAction) that is always present on tvOS, reachable from any list row via swipe-up.
This commit is contained in:
@@ -65,4 +65,20 @@ struct TVSidebarDetailContainer<Content: View, BottomAction: View>: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -239,14 +239,32 @@ private struct EditRemoteServerContent: View {
|
||||
if isLoggedIn && (instance.type == .invidious || instance.type == .piped) {
|
||||
Section {
|
||||
NavigationLink {
|
||||
#if os(tvOS)
|
||||
TVSidebarDetailContainer(
|
||||
systemImage: "person.2",
|
||||
title: String(localized: "sources.import.subscriptions")
|
||||
) {
|
||||
ImportSubscriptionsView(instance: instance)
|
||||
}
|
||||
#else
|
||||
ImportSubscriptionsView(instance: instance)
|
||||
#endif
|
||||
} label: {
|
||||
Label(String(localized: "sources.import.subscriptions"), systemImage: "person.2")
|
||||
}
|
||||
.accessibilityIdentifier("sources.import.subscriptions")
|
||||
|
||||
NavigationLink {
|
||||
#if os(tvOS)
|
||||
TVSidebarDetailContainer(
|
||||
systemImage: "list.bullet.rectangle",
|
||||
title: String(localized: "sources.import.playlists")
|
||||
) {
|
||||
ImportPlaylistsView(instance: instance)
|
||||
}
|
||||
#else
|
||||
ImportPlaylistsView(instance: instance)
|
||||
#endif
|
||||
} label: {
|
||||
Label(String(localized: "sources.import.playlists"), systemImage: "list.bullet.rectangle")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ 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<String> = []
|
||||
@@ -51,12 +52,23 @@ struct ImportPlaylistsView: View {
|
||||
|
||||
var body: some View {
|
||||
content
|
||||
#if !os(tvOS)
|
||||
.navigationTitle(String(localized: "import.playlists.title"))
|
||||
#endif
|
||||
.accessibilityIdentifier(AccessibilityID.view)
|
||||
#if os(iOS)
|
||||
.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 {
|
||||
|
||||
@@ -11,6 +11,7 @@ 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<String> = []
|
||||
@@ -42,12 +43,23 @@ struct ImportSubscriptionsView: View {
|
||||
|
||||
var body: some View {
|
||||
content
|
||||
#if !os(tvOS)
|
||||
.navigationTitle(String(localized: "import.subscriptions.title"))
|
||||
#endif
|
||||
.accessibilityIdentifier(AccessibilityID.view)
|
||||
#if os(iOS)
|
||||
.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 {
|
||||
|
||||
Reference in New Issue
Block a user