import SwiftUI struct MainView: View { private enum MainSidebarSection: Int, CaseIterable, Hashable { case posts = 0 case bookmarks = 1 case favorites = 2 var title: String { switch self { case .posts: "Posts" case .bookmarks: "Bookmarks" case .favorites: "Favorites" } } var systemImage: String { switch self { case .posts: "rectangle.stack" case .bookmarks: "bookmark" case .favorites: "heart" } } } @EnvironmentObject var settings: SettingsManager @State private var selectedTab: Int = 0 @State private var selectedSidebarSection: MainSidebarSection? = .posts @State private var manager = BooruManager(.yandere) var body: some View { platformSpecificContent .environmentObject(settings) .environmentObject(manager) .onChange(of: settings.preferredBooru) { _, newState in updateManager(newState) } .onChange(of: manager.historyIndex) { _, _ in if manager.isNavigatingHistory { manager.selectedPost = nil } } .onAppear(perform: initializeManager) .onChange(of: settings.providerCredentials) { updateManager(settings.preferredBooru) } .onChange(of: settings.showHeldMoebooruPosts) { updateManager(settings.preferredBooru) } .onChange(of: settings.sendBooruUserAgent) { updateManager(settings.preferredBooru) } .onChange(of: settings.customBooruUserAgent) { updateManager(settings.preferredBooru) } #if os(macOS) .onChange(of: selectedSidebarSection) { _, newValue in guard let newValue else { return } selectedTab = newValue.rawValue if newValue == .posts { Task(priority: .userInitiated) { await manager.fetchPosts() } } } .onChange(of: selectedTab) { _, newValue in selectedSidebarSection = MainSidebarSection(rawValue: newValue) ?? .posts } #endif } @ViewBuilder private var tabViewContent: some View { if #available(iOS 26, macOS 15.0, *) { TabView(selection: $selectedTab) { Tab("Posts", systemImage: "rectangle.stack", value: 0) { ContentView(selectedTab: $selectedTab) } Tab("Bookmarks", systemImage: "bookmark", value: 1) { NavigationStack { BookmarksView(selectedTab: $selectedTab) } } Tab("Favorites", systemImage: "heart", value: 2) { NavigationStack { FavoritesView(selectedTab: $selectedTab, isPresented: .constant(false)) } } } } else { TabView(selection: $selectedTab) { ContentView(selectedTab: $selectedTab) .tabItem { Label("Posts", systemImage: "rectangle.stack") } .tag(0) NavigationStack { BookmarksView(selectedTab: $selectedTab) } .tabItem { Label("Bookmarks", systemImage: "bookmark") } .tag(1) NavigationStack { FavoritesView(selectedTab: $selectedTab, isPresented: .constant(false)) } .tabItem { Label("Favorites", systemImage: "heart") } .tag(2) } } } #if os(macOS) @ViewBuilder private var sidebarContent: some View { List(selection: $selectedSidebarSection) { ForEach(MainSidebarSection.allCases, id: \.self) { section in Label(section.title, systemImage: section.systemImage) .tag(section) } } .navigationTitle("Sora") } @ViewBuilder private var sidebarDetailContent: some View { switch selectedSidebarSection ?? .posts { case .posts: ContentView(selectedTab: $selectedTab) case .bookmarks: NavigationStack { BookmarksView(selectedTab: $selectedTab) } case .favorites: NavigationStack { FavoritesView(selectedTab: $selectedTab, isPresented: .constant(false)) } } } #endif @ViewBuilder private var platformSpecificContent: some View { #if os(macOS) NavigationSplitView { sidebarContent } detail: { sidebarDetailContent } #else if #available(iOS 26, *) { tabViewContent .tabBarMinimizeBehavior(.onScrollDown) } else { tabViewContent } #endif } private func updateManager(_ provider: BooruProvider) { let previousSearchText = manager.searchText manager = BooruManager( provider, credentials: settings.providerCredentials .first { $0.provider == settings.preferredBooru }, sendUserAgent: settings.sendBooruUserAgent, customUserAgent: settings.customBooruUserAgent, showHeldMoebooruPosts: settings.showHeldMoebooruPosts ) manager.searchText = previousSearchText Task(priority: .userInitiated) { if manager.searchText.isEmpty { await manager.fetchPosts() } else { await manager.performSearch(settings: settings) } } } private func initializeManager() { manager = BooruManager( settings.preferredBooru, credentials: settings.providerCredentials .first { $0.provider == settings.preferredBooru }, sendUserAgent: settings.sendBooruUserAgent, customUserAgent: settings.customBooruUserAgent, showHeldMoebooruPosts: settings.showHeldMoebooruPosts ) Task(priority: .userInitiated) { if manager.posts.isEmpty { await manager.fetchPosts() } } } } #Preview { #if os(macOS) let screenSize = NSScreen.main?.frame.size ?? CGSize(width: 1_920, height: 1_080) let heightCoefficient = screenSize.height / 1_080 let widthCoefficient = screenSize.width / 1_440 #endif MainView() .environmentObject(SettingsManager()) #if os(macOS) .frame( width: screenSize.width / widthCoefficient, height: screenSize.height / heightCoefficient ) #endif }