jellyflood/Shared/Coordinators/Tabs/TabCoordinator.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
}
}