Adds a toggleable honeycomb hexagonal grid overlay (matching the website pattern) that can be enabled independently of any theme via the Appearance screen. Uses a cached tiled UIImage approach consistent with the existing grain texture system. Replaces the destructive refreshID-based theme switching (which destroyed all NavigationStacks and dismissed sheets) with @Observable AppThemeSource. Color resolution now happens through Swift's Observation framework, so all views using Color.appPrimary etc. automatically re-render when the theme changes — no view identity reset needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
126 lines
4.6 KiB
Swift
126 lines
4.6 KiB
Swift
import SwiftUI
|
|
|
|
struct MainTabView: View {
|
|
enum Tab: Hashable {
|
|
case residences
|
|
case tasks
|
|
case contractors
|
|
case documents
|
|
}
|
|
|
|
@EnvironmentObject private var themeManager: ThemeManager
|
|
@State private var selectedTab: Tab = .residences
|
|
@State private var residencesPath = NavigationPath()
|
|
@State private var tasksPath = NavigationPath()
|
|
@State private var contractorsPath = NavigationPath()
|
|
@State private var documentsPath = NavigationPath()
|
|
@ObservedObject private var authManager = AuthenticationManager.shared
|
|
@ObservedObject private var pushManager = PushNotificationManager.shared
|
|
var refreshID: UUID
|
|
|
|
var body: some View {
|
|
TabView(selection: $selectedTab) {
|
|
NavigationStack(path: $residencesPath) {
|
|
ResidencesListView()
|
|
}
|
|
.id(refreshID)
|
|
.tabItem {
|
|
Label("Residences", image: "tab_view")
|
|
}
|
|
.tag(Tab.residences)
|
|
.accessibilityIdentifier(AccessibilityIdentifiers.Navigation.residencesTab)
|
|
|
|
NavigationStack(path: $tasksPath) {
|
|
AllTasksView()
|
|
}
|
|
.id(refreshID)
|
|
.tabItem {
|
|
Label("Tasks", systemImage: "checklist")
|
|
}
|
|
.tag(Tab.tasks)
|
|
.accessibilityIdentifier(AccessibilityIdentifiers.Navigation.tasksTab)
|
|
|
|
NavigationStack(path: $contractorsPath) {
|
|
ContractorsListView()
|
|
}
|
|
.id(refreshID)
|
|
.tabItem {
|
|
Label("Contractors", systemImage: "wrench.and.screwdriver.fill")
|
|
}
|
|
.tag(Tab.contractors)
|
|
.accessibilityIdentifier(AccessibilityIdentifiers.Navigation.contractorsTab)
|
|
|
|
NavigationStack(path: $documentsPath) {
|
|
DocumentsWarrantiesView(residenceId: nil)
|
|
}
|
|
.id(refreshID)
|
|
.tabItem {
|
|
Label("Docs", systemImage: "doc.text.fill")
|
|
}
|
|
.tag(Tab.documents)
|
|
.accessibilityIdentifier(AccessibilityIdentifiers.Navigation.documentsTab)
|
|
}
|
|
.tabViewStyle(.sidebarAdaptable)
|
|
.tint(Color.appPrimary)
|
|
.onChange(of: authManager.isAuthenticated) { _, _ in
|
|
selectedTab = .residences
|
|
}
|
|
.onChange(of: themeManager.currentTheme) { _, _ in
|
|
updateTabBarAppearance()
|
|
}
|
|
.onAppear {
|
|
updateTabBarAppearance()
|
|
|
|
// Handle pending navigation from push notification
|
|
if pushManager.pendingNavigationTaskId != nil {
|
|
selectedTab = .tasks
|
|
} else if pushManager.pendingNavigationDocumentId != nil {
|
|
selectedTab = .documents
|
|
} else if pushManager.pendingNavigationResidenceId != nil {
|
|
selectedTab = .residences
|
|
}
|
|
}
|
|
.onReceive(NotificationCenter.default.publisher(for: .navigateToTask)) { _ in
|
|
selectedTab = .tasks
|
|
}
|
|
.onReceive(NotificationCenter.default.publisher(for: .navigateToEditTask)) { _ in
|
|
selectedTab = .tasks
|
|
}
|
|
.onReceive(NotificationCenter.default.publisher(for: .navigateToResidence)) { _ in
|
|
selectedTab = .residences
|
|
}
|
|
.onReceive(NotificationCenter.default.publisher(for: .navigateToDocument)) { _ in
|
|
selectedTab = .documents
|
|
}
|
|
.onReceive(NotificationCenter.default.publisher(for: .navigateToHome)) { _ in
|
|
selectedTab = .residences
|
|
}
|
|
}
|
|
|
|
private func updateTabBarAppearance() {
|
|
let appearance = UITabBarAppearance()
|
|
appearance.configureWithOpaqueBackground()
|
|
appearance.backgroundColor = UIColor(Color.appBackgroundSecondary)
|
|
|
|
appearance.stackedLayoutAppearance.selected.iconColor = UIColor(Color.appPrimary)
|
|
appearance.stackedLayoutAppearance.selected.titleTextAttributes = [
|
|
.foregroundColor: UIColor(Color.appPrimary),
|
|
.font: UIFont.preferredFont(forTextStyle: .caption2)
|
|
]
|
|
|
|
appearance.stackedLayoutAppearance.normal.iconColor = UIColor(Color.appTextSecondary)
|
|
appearance.stackedLayoutAppearance.normal.titleTextAttributes = [
|
|
.foregroundColor: UIColor(Color.appTextSecondary),
|
|
.font: UIFont.preferredFont(forTextStyle: .caption2)
|
|
]
|
|
|
|
UITabBar.appearance().standardAppearance = appearance
|
|
UITabBar.appearance().scrollEdgeAppearance = appearance
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
MainTabView(refreshID: UUID())
|
|
.environmentObject(ThemeManager.shared)
|
|
}
|