From a660591e8d8e0c213b216f0dfdc5d4d2fe4aa14c Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Fri, 17 Apr 2026 04:12:39 +0200 Subject: [PATCH] Add Playlists entry to sidebar main navigation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a toggleable "Playlists" item that opens PlaylistsListView, mirroring the Channels → ManageChannelsView pattern. --- Yattee/Localizable.xcstrings | 11 ++++++ Yattee/Models/Navigation/SidebarItem.swift | 9 +++++ .../Models/Navigation/SidebarMainItem.swift | 11 ++++-- Yattee/Views/Navigation/UnifiedTabView.swift | 34 +++++++++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/Yattee/Localizable.xcstrings b/Yattee/Localizable.xcstrings index 302f793f..0d43aca1 100644 --- a/Yattee/Localizable.xcstrings +++ b/Yattee/Localizable.xcstrings @@ -14212,6 +14212,17 @@ } } }, + "sidebar.mainItem.playlists" : { + "comment" : "Sidebar main navigation item for playlists", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Playlists" + } + } + } + }, "sidebar.mainItem.downloads" : { "comment" : "Sidebar main navigation item for downloads", "localizations" : { diff --git a/Yattee/Models/Navigation/SidebarItem.swift b/Yattee/Models/Navigation/SidebarItem.swift index 9568cf25..3ebd9764 100644 --- a/Yattee/Models/Navigation/SidebarItem.swift +++ b/Yattee/Models/Navigation/SidebarItem.swift @@ -36,6 +36,7 @@ enum SidebarItem: Hashable, Identifiable { case downloads case subscriptionsFeed case manageChannels + case playlistsList // MARK: - Identifiable @@ -73,6 +74,8 @@ enum SidebarItem: Hashable, Identifiable { return "subscriptions-feed" case .manageChannels: return "manage-channels" + case .playlistsList: + return "playlists-list" } } @@ -112,6 +115,8 @@ enum SidebarItem: Hashable, Identifiable { return String(localized: "home.subscriptions.title") case .manageChannels: return String(localized: "sidebar.manageChannels") + case .playlistsList: + return String(localized: "home.playlists.title") } } @@ -149,6 +154,8 @@ enum SidebarItem: Hashable, Identifiable { return "play.square.stack.fill" case .manageChannels: return "person.2" + case .playlistsList: + return "list.bullet.rectangle" } } @@ -180,6 +187,8 @@ enum SidebarItem: Hashable, Identifiable { return .subscriptionsFeed case .manageChannels: return .manageChannels + case .playlistsList: + return .playlists } } diff --git a/Yattee/Models/Navigation/SidebarMainItem.swift b/Yattee/Models/Navigation/SidebarMainItem.swift index 7fc1d4e6..5784d329 100644 --- a/Yattee/Models/Navigation/SidebarMainItem.swift +++ b/Yattee/Models/Navigation/SidebarMainItem.swift @@ -16,6 +16,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { case history case downloads case channels + case playlists case sources case settings case openURL @@ -25,7 +26,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { /// Default order for sidebar main items. static var defaultOrder: [SidebarMainItem] { - [.search, .home, .subscriptions, .bookmarks, .history, .channels, .sources, .openURL, .remoteControl, .downloads, .settings] + [.search, .home, .subscriptions, .bookmarks, .history, .channels, .playlists, .sources, .openURL, .remoteControl, .downloads, .settings] } /// Default visibility (all visible except subscriptions and channels). @@ -39,6 +40,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { .history: false, .downloads: true, .channels: false, + .playlists: false, .sources: true, .settings: true, .openURL: false, @@ -53,6 +55,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { .history: false, .downloads: true, .channels: false, + .playlists: false, .sources: true, .settings: true, .openURL: false, @@ -71,6 +74,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { case .history: "clock" case .downloads: "arrow.down.circle" case .channels: "person.2" + case .playlists: "list.bullet.rectangle" case .sources: "server.rack" case .settings: "gear" case .openURL: "link" @@ -88,6 +92,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { case .history: String(localized: "sidebar.mainItem.history") case .downloads: String(localized: "sidebar.mainItem.downloads") case .channels: String(localized: "sidebar.mainItem.channels") + case .playlists: String(localized: "sidebar.mainItem.playlists") case .sources: String(localized: "sidebar.mainItem.sources") case .settings: String(localized: "sidebar.mainItem.settings") case .openURL: String(localized: "sidebar.mainItem.openURL") @@ -132,6 +137,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { case .history: return TabBarItem.history.rawValue case .downloads: return TabBarItem.downloads.rawValue case .channels: return TabBarItem.channels.rawValue + case .playlists: return TabBarItem.playlists.rawValue case .sources: return TabBarItem.sources.rawValue case .settings: return TabBarItem.settings.rawValue case .openURL: return "open-url" @@ -149,6 +155,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { case .history: return .history case .downloads: return .downloads case .channels: return .manageChannels + case .playlists: return .playlistsList case .sources: return .sources case .settings: return .settings case .openURL: return .openURL @@ -162,7 +169,7 @@ enum SidebarMainItem: String, CaseIterable, Codable, Identifiable, Sendable { case .subscriptions: self = .subscriptions case .channels: self = .channels case .bookmarks: self = .bookmarks - case .playlists: return nil // No direct mapping - playlists isn't a SidebarMainItem + case .playlists: self = .playlists case .history: self = .history case .downloads: self = .downloads case .sources: self = .sources diff --git a/Yattee/Views/Navigation/UnifiedTabView.swift b/Yattee/Views/Navigation/UnifiedTabView.swift index 2e982afa..4d7134f5 100644 --- a/Yattee/Views/Navigation/UnifiedTabView.swift +++ b/Yattee/Views/Navigation/UnifiedTabView.swift @@ -33,6 +33,7 @@ struct UnifiedTabView: View { @State private var downloadsPath = NavigationPath() @State private var subscriptionsFeedPath = NavigationPath() @State private var manageChannelsPath = NavigationPath() + @State private var playlistsListPath = NavigationPath() @State private var sourcesPath = NavigationPath() @State private var settingsPath = NavigationPath() @State private var openURLPath = NavigationPath() @@ -182,6 +183,16 @@ struct UnifiedTabView: View { Label(SidebarItem.manageChannels.title, systemImage: SidebarItem.manageChannels.systemImage) } + case .playlists: + Tab(value: SidebarItem.playlistsList) { + NavigationStack(path: $playlistsListPath) { + PlaylistsListView() + .withNavigationDestinations() + } + } label: { + Label(SidebarItem.playlistsList.title, systemImage: SidebarItem.playlistsList.systemImage) + } + case .sources: Tab(value: SidebarItem.sources) { NavigationStack(path: $sourcesPath) { @@ -340,6 +351,7 @@ struct UnifiedTabView: View { @State private var downloadsPath = NavigationPath() @State private var subscriptionsFeedPath = NavigationPath() @State private var manageChannelsPath = NavigationPath() + @State private var playlistsListPath = NavigationPath() @State private var sourcesPath = NavigationPath() @State private var settingsPath = NavigationPath() @State private var openURLPath = NavigationPath() @@ -471,6 +483,15 @@ struct UnifiedTabView: View { Label(SidebarItem.manageChannels.title, systemImage: SidebarItem.manageChannels.systemImage) } + case .playlists: + Tab(value: SidebarItem.playlistsList) { + NavigationStack(path: $playlistsListPath) { + PlaylistsListView().withNavigationDestinations() + } + } label: { + Label(SidebarItem.playlistsList.title, systemImage: SidebarItem.playlistsList.systemImage) + } + case .sources: Tab(value: SidebarItem.sources) { NavigationStack(path: $sourcesPath) { @@ -582,6 +603,7 @@ struct UnifiedTabView: View { @State private var historyPath = NavigationPath() @State private var subscriptionsFeedPath = NavigationPath() @State private var manageChannelsPath = NavigationPath() + @State private var playlistsListPath = NavigationPath() @State private var sourcesPath = NavigationPath() @State private var settingsPath = NavigationPath() @State private var openURLPath = NavigationPath() @@ -730,6 +752,16 @@ struct UnifiedTabView: View { Label(SidebarItem.manageChannels.title, systemImage: SidebarItem.manageChannels.systemImage) } + case .playlists: + Tab(value: SidebarItem.playlistsList) { + NavigationStack(path: $playlistsListPath) { + PlaylistsListView() + .withNavigationDestinations() + } + } label: { + Label(SidebarItem.playlistsList.title, systemImage: SidebarItem.playlistsList.systemImage) + } + case .sources: Tab(value: SidebarItem.sources) { NavigationStack(path: $sourcesPath) { @@ -886,6 +918,8 @@ extension UnifiedTabView { subscriptionsFeedPath.append(destination) case .manageChannels: manageChannelsPath.append(destination) + case .playlistsList: + playlistsListPath.append(destination) case .sources: sourcesPath.append(destination) case .settings: