mirror of
https://github.com/yattee/yattee.git
synced 2026-05-13 02:45:03 +00:00
Dismiss tvOS sidebar detail pages when sidebar selection changes
tvOS's sidebarAdaptable TabView leaves the previously-pushed detail view visible after the user picks another sidebar item, until they manually press Menu. Broadcast a notification on tab change so any pushed TVSidebarDetailContainer dismisses itself, and reset each tab's NavigationPath. Also drop a redundant inner NavigationStack in the tvOS SettingsView so subpages register on the tab's outer stack.
This commit is contained in:
@@ -9,6 +9,10 @@
|
||||
#if os(tvOS)
|
||||
import SwiftUI
|
||||
|
||||
extension Notification.Name {
|
||||
static let yatteeTVForcePopDetail = Notification.Name("yatteeTVForcePopDetail")
|
||||
}
|
||||
|
||||
struct TVSidebarDetailContainer<Content: View>: View {
|
||||
let content: Content
|
||||
var systemImage: String?
|
||||
@@ -65,6 +69,9 @@ struct TVSidebarDetailContainer<Content: View>: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.onReceive(NotificationCenter.default.publisher(for: .yatteeTVForcePopDetail)) { _ in
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -614,6 +614,55 @@ struct UnifiedTabView: View {
|
||||
selection = item
|
||||
navigationCoordinator?.selectedSidebarItem = nil
|
||||
}
|
||||
.onChange(of: selection) { oldValue, _ in
|
||||
resetPath(for: oldValue)
|
||||
// Force any pushed TVSidebarDetailContainer (used by Settings
|
||||
// sub-pages and similar detail screens) to dismiss. Without this,
|
||||
// tvOS's sidebarAdaptable TabView leaves the previously-pushed
|
||||
// detail visible until the user manually presses Menu.
|
||||
NotificationCenter.default.post(name: .yatteeTVForcePopDetail, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
/// Pops the previously-selected tab's NavigationStack to its root so its
|
||||
/// pushed views don't linger after the user picks another sidebar item.
|
||||
private func resetPath(for item: SidebarItem) {
|
||||
switch item {
|
||||
case .home:
|
||||
homePath = NavigationPath()
|
||||
case .search:
|
||||
searchPath = NavigationPath()
|
||||
case .subscriptionsFeed:
|
||||
subscriptionsFeedPath = NavigationPath()
|
||||
case .bookmarks:
|
||||
bookmarksPath = NavigationPath()
|
||||
case .history:
|
||||
historyPath = NavigationPath()
|
||||
case .manageChannels:
|
||||
manageChannelsPath = NavigationPath()
|
||||
case .playlistsList:
|
||||
playlistsListPath = NavigationPath()
|
||||
case .sources:
|
||||
sourcesPath = NavigationPath()
|
||||
case .settings:
|
||||
settingsPath = NavigationPath()
|
||||
case .openURL:
|
||||
openURLPath = NavigationPath()
|
||||
case .remoteControl:
|
||||
remoteControlPath = NavigationPath()
|
||||
case .continueWatching:
|
||||
continueWatchingPath = NavigationPath()
|
||||
case let .channel(channelID, _, _):
|
||||
channelPaths[channelID] = NavigationPath()
|
||||
case let .playlist(id, _):
|
||||
playlistPaths[id] = NavigationPath()
|
||||
case let .instance(id, _, _):
|
||||
instancePaths[id] = NavigationPath()
|
||||
case let .mediaSource(id, _, _):
|
||||
mediaSourcePaths[id] = NavigationPath()
|
||||
case .nowPlaying, .downloads:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the configured startup tab on first appearance.
|
||||
|
||||
@@ -107,7 +107,6 @@ struct SettingsView: View {
|
||||
|
||||
#if os(tvOS)
|
||||
private var tvOSSettings: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
if let appEnvironment {
|
||||
NavigationLink {
|
||||
@@ -202,7 +201,6 @@ struct SettingsView: View {
|
||||
}
|
||||
.accessibilityIdentifier("settings.view")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: - iOS Settings
|
||||
|
||||
Reference in New Issue
Block a user