112 lines
3.1 KiB
Swift
112 lines
3.1 KiB
Swift
//
|
|
// Swiftfin is subject to the terms of the Mozilla Public
|
|
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
//
|
|
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
@MainActor
|
|
final class TabCoordinator: ObservableObject {
|
|
|
|
struct SelectedEvent {
|
|
let isRoot: Bool
|
|
let isRepeat: Bool
|
|
}
|
|
|
|
typealias TabData = (
|
|
item: TabItem,
|
|
coordinator: NavigationCoordinator,
|
|
publisher: TabItemSelectedPublisher
|
|
)
|
|
|
|
@Published
|
|
var selectedTabID: String! = nil {
|
|
didSet {
|
|
guard let tab = tabs.first(property: \.item.id, equalTo: selectedTabID) else { return }
|
|
|
|
tab.publisher.send(
|
|
.init(
|
|
isRoot: tab.coordinator.path.isEmpty,
|
|
isRepeat: oldValue == selectedTabID
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
@Published
|
|
var tabs: [TabData] = []
|
|
|
|
private let sessionManager: SessionManager
|
|
|
|
init(sessionManager: SessionManager) {
|
|
self.sessionManager = sessionManager
|
|
refreshTabs()
|
|
}
|
|
|
|
func refreshTabs() {
|
|
let newTabs = buildTabs()
|
|
|
|
// Preserve navigation coordinators for existing tabs
|
|
let preservedTabs = newTabs.map { newTab in
|
|
if let existingTab = tabs.first(where: { $0.item.id == newTab.id }) {
|
|
return (newTab, existingTab.coordinator, existingTab.publisher)
|
|
} else {
|
|
let coordinator = NavigationCoordinator()
|
|
let publisher = TabItemSelectedPublisher()
|
|
return (newTab, coordinator, publisher)
|
|
}
|
|
}
|
|
|
|
tabs = preservedTabs
|
|
|
|
// Reset selected tab if it no longer exists
|
|
if let selectedID = selectedTabID, !tabs.contains(where: { $0.item.id == selectedID }) {
|
|
selectedTabID = tabs.first?.item.id
|
|
}
|
|
}
|
|
|
|
private func buildTabs() -> [TabItem] {
|
|
var tabItems: [TabItem] = []
|
|
|
|
// Add Jellyfin tabs if JF session is active
|
|
if sessionManager.hasJellyfinProvider {
|
|
#if os(iOS)
|
|
tabItems.append(TabItem.home)
|
|
tabItems.append(TabItem.search)
|
|
tabItems.append(TabItem.media)
|
|
#else
|
|
tabItems.append(TabItem.home)
|
|
tabItems.append(TabItem.library(
|
|
title: L10n.tvShows,
|
|
systemName: "tv",
|
|
filters: .init(itemTypes: [.series])
|
|
))
|
|
tabItems.append(TabItem.library(
|
|
title: L10n.movies,
|
|
systemName: "film",
|
|
filters: .init(itemTypes: [.movie])
|
|
))
|
|
tabItems.append(TabItem.search)
|
|
tabItems.append(TabItem.media)
|
|
#endif
|
|
}
|
|
|
|
// Add Xtream tab if XC session is active
|
|
if sessionManager.hasXtreamProvider {
|
|
tabItems.append(TabItem.xtream)
|
|
}
|
|
|
|
// Always add settings on tvOS (if JF is active)
|
|
#if !os(iOS)
|
|
if sessionManager.hasJellyfinProvider {
|
|
tabItems.append(TabItem.settings)
|
|
}
|
|
#endif
|
|
|
|
return tabItems
|
|
}
|
|
}
|