Add Continue Watching toggle to sidebar settings

Exposes ContinueWatchingView as an opt-in main sidebar item,
hidden by default.
This commit is contained in:
Arkadiusz Fal
2026-04-17 21:22:25 +02:00
parent 2761fcbcfb
commit c0184712a9
4 changed files with 65 additions and 3 deletions

View File

@@ -14311,6 +14311,17 @@
} }
} }
}, },
"sidebar.mainItem.continueWatching" : {
"comment" : "Sidebar main navigation item for continue watching",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Continue Watching"
}
}
}
},
"sidebar.mainItem.channels" : { "sidebar.mainItem.channels" : {
"comment" : "Sidebar main navigation item for channels", "comment" : "Sidebar main navigation item for channels",
"localizations" : { "localizations" : {

View File

@@ -37,6 +37,7 @@ enum SidebarItem: Hashable, Identifiable {
case subscriptionsFeed case subscriptionsFeed
case manageChannels case manageChannels
case playlistsList case playlistsList
case continueWatching
// MARK: - Identifiable // MARK: - Identifiable
@@ -76,6 +77,8 @@ enum SidebarItem: Hashable, Identifiable {
return "manage-channels" return "manage-channels"
case .playlistsList: case .playlistsList:
return "playlists-list" return "playlists-list"
case .continueWatching:
return "continue-watching"
} }
} }
@@ -117,6 +120,8 @@ enum SidebarItem: Hashable, Identifiable {
return String(localized: "sidebar.manageChannels") return String(localized: "sidebar.manageChannels")
case .playlistsList: case .playlistsList:
return String(localized: "home.playlists.title") return String(localized: "home.playlists.title")
case .continueWatching:
return String(localized: "home.continueWatching.title")
} }
} }
@@ -156,6 +161,8 @@ enum SidebarItem: Hashable, Identifiable {
return "person.2" return "person.2"
case .playlistsList: case .playlistsList:
return "list.bullet.rectangle" return "list.bullet.rectangle"
case .continueWatching:
return "play.circle"
} }
} }
@@ -189,6 +196,8 @@ enum SidebarItem: Hashable, Identifiable {
return .manageChannels return .manageChannels
case .playlistsList: case .playlistsList:
return .playlists return .playlists
case .continueWatching:
return .continueWatching
} }
} }

View File

@@ -21,12 +21,13 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable {
case settings case settings
case openURL case openURL
case remoteControl case remoteControl
case continueWatching
var id: String { rawValue } var id: String { rawValue }
/// Default order for sidebar main items. /// Default order for sidebar main items.
static var defaultOrder: [SidebarMainItem] { static var defaultOrder: [SidebarMainItem] {
[.search, .home, .subscriptions, .bookmarks, .history, .channels, .playlists, .sources, .openURL, .remoteControl, .downloads, .settings] [.search, .home, .subscriptions, .bookmarks, .history, .channels, .playlists, .sources, .openURL, .remoteControl, .downloads, .continueWatching, .settings]
} }
/// Default visibility (all visible except subscriptions and channels). /// Default visibility (all visible except subscriptions and channels).
@@ -44,7 +45,8 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable {
.sources: true, .sources: true,
.settings: true, .settings: true,
.openURL: false, .openURL: false,
.remoteControl: true .remoteControl: true,
.continueWatching: false
] ]
#else #else
[ [
@@ -59,7 +61,8 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable {
.sources: true, .sources: true,
.settings: true, .settings: true,
.openURL: false, .openURL: false,
.remoteControl: false .remoteControl: false,
.continueWatching: false
] ]
#endif #endif
} }
@@ -79,6 +82,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable {
case .settings: "gear" case .settings: "gear"
case .openURL: "link" case .openURL: "link"
case .remoteControl: "antenna.radiowaves.left.and.right" case .remoteControl: "antenna.radiowaves.left.and.right"
case .continueWatching: "play.circle"
} }
} }
@@ -97,6 +101,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable {
case .settings: String(localized: "sidebar.mainItem.settings") case .settings: String(localized: "sidebar.mainItem.settings")
case .openURL: String(localized: "sidebar.mainItem.openURL") case .openURL: String(localized: "sidebar.mainItem.openURL")
case .remoteControl: String(localized: "sidebar.mainItem.remoteControl") case .remoteControl: String(localized: "sidebar.mainItem.remoteControl")
case .continueWatching: String(localized: "sidebar.mainItem.continueWatching")
} }
} }
@@ -142,6 +147,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable {
case .settings: return TabBarItem.settings.rawValue case .settings: return TabBarItem.settings.rawValue
case .openURL: return "open-url" case .openURL: return "open-url"
case .remoteControl: return "remote-control" case .remoteControl: return "remote-control"
case .continueWatching: return "continue-watching"
} }
} }
@@ -160,6 +166,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable {
case .settings: return .settings case .settings: return .settings
case .openURL: return .openURL case .openURL: return .openURL
case .remoteControl: return .remoteControl case .remoteControl: return .remoteControl
case .continueWatching: return .continueWatching
} }
} }

View File

@@ -38,6 +38,7 @@ struct UnifiedTabView: View {
@State private var settingsPath = NavigationPath() @State private var settingsPath = NavigationPath()
@State private var openURLPath = NavigationPath() @State private var openURLPath = NavigationPath()
@State private var remoteControlPath = NavigationPath() @State private var remoteControlPath = NavigationPath()
@State private var continueWatchingPath = NavigationPath()
// Current selection - initial value is a placeholder; actual startup tab is applied in onAppear // Current selection - initial value is a placeholder; actual startup tab is applied in onAppear
@State private var selection: SidebarItem = .home @State private var selection: SidebarItem = .home
@@ -233,6 +234,16 @@ struct UnifiedTabView: View {
} label: { } label: {
Label(SidebarItem.remoteControl.title, systemImage: SidebarItem.remoteControl.systemImage) Label(SidebarItem.remoteControl.title, systemImage: SidebarItem.remoteControl.systemImage)
} }
case .continueWatching:
Tab(value: SidebarItem.continueWatching) {
NavigationStack(path: $continueWatchingPath) {
ContinueWatchingView()
.withNavigationDestinations()
}
} label: {
Label(SidebarItem.continueWatching.title, systemImage: SidebarItem.continueWatching.systemImage)
}
} }
} }
@@ -356,6 +367,7 @@ struct UnifiedTabView: View {
@State private var settingsPath = NavigationPath() @State private var settingsPath = NavigationPath()
@State private var openURLPath = NavigationPath() @State private var openURLPath = NavigationPath()
@State private var remoteControlPath = NavigationPath() @State private var remoteControlPath = NavigationPath()
@State private var continueWatchingPath = NavigationPath()
// Current selection - initial value is a placeholder; actual startup tab is applied in onAppear // Current selection - initial value is a placeholder; actual startup tab is applied in onAppear
@State private var selection: SidebarItem = .home @State private var selection: SidebarItem = .home
@@ -529,6 +541,16 @@ struct UnifiedTabView: View {
} label: { } label: {
Label(SidebarItem.remoteControl.title, systemImage: SidebarItem.remoteControl.systemImage) Label(SidebarItem.remoteControl.title, systemImage: SidebarItem.remoteControl.systemImage)
} }
case .continueWatching:
Tab(value: SidebarItem.continueWatching) {
NavigationStack(path: $continueWatchingPath) {
ContinueWatchingView()
.withNavigationDestinations()
}
} label: {
Label(SidebarItem.continueWatching.title, systemImage: SidebarItem.continueWatching.systemImage)
}
} }
} }
@@ -608,6 +630,7 @@ struct UnifiedTabView: View {
@State private var settingsPath = NavigationPath() @State private var settingsPath = NavigationPath()
@State private var openURLPath = NavigationPath() @State private var openURLPath = NavigationPath()
@State private var remoteControlPath = NavigationPath() @State private var remoteControlPath = NavigationPath()
@State private var continueWatchingPath = NavigationPath()
// Current selection - initial value is a placeholder; actual startup tab is applied in onAppear // Current selection - initial value is a placeholder; actual startup tab is applied in onAppear
@State private var selection: SidebarItem = .home @State private var selection: SidebarItem = .home
@@ -811,6 +834,16 @@ struct UnifiedTabView: View {
} label: { } label: {
Label(SidebarItem.remoteControl.title, systemImage: SidebarItem.remoteControl.systemImage) Label(SidebarItem.remoteControl.title, systemImage: SidebarItem.remoteControl.systemImage)
} }
case .continueWatching:
Tab(value: SidebarItem.continueWatching) {
NavigationStack(path: $continueWatchingPath) {
ContinueWatchingView()
.withNavigationDestinations()
}
} label: {
Label(SidebarItem.continueWatching.title, systemImage: SidebarItem.continueWatching.systemImage)
}
} }
} }
@@ -928,6 +961,8 @@ extension UnifiedTabView {
openURLPath.append(destination) openURLPath.append(destination)
case .remoteControl: case .remoteControl:
remoteControlPath.append(destination) remoteControlPath.append(destination)
case .continueWatching:
continueWatchingPath.append(destination)
} }
navigationCoordinator?.clearPendingNavigation() navigationCoordinator?.clearPendingNavigation()
} }