import SwiftUI struct ContentView: View { @Environment(SessionStore.self) private var session var body: some View { if let client = session.client, let account = session.current { TabView { Tab("Dashboard", systemImage: "square.grid.2x2") { NavigationStack { DashboardView(client: client) .navigationDestinations(client: client) } } Tab("Feed", systemImage: "bolt") { NavigationStack { FeedView(client: client) .navigationDestinations(client: client) } } Tab("Repositories", systemImage: "books.vertical") { NavigationStack { RepoListView(client: client) .navigationDestinations(client: client) } } Tab("Explore", systemImage: "safari") { NavigationStack { ExploreView(client: client) .navigationDestinations(client: client) } } Tab("My Profile", systemImage: "person.crop.circle") { NavigationStack { ProfileView(client: client, name: account.username, title: "My Profile") .toolbar { AccountMenu() } .navigationDestinations(client: client) } } } .id(account.id) // fresh screens on account switch } else { NavigationStack { SignInView() } } } } /// Every value-routed screen, attachable to any stack root. private struct RouteDestinations: ViewModifier { let client: GitbayClient func body(content: Content) -> some View { content .navigationDestination(for: RepoRoute.self) { route in destination(route, client: client) } .navigationDestination(for: MRRoute.self) { route in destination(route, client: client) } .navigationDestination(for: IssueRoute.self) { route in destination(route, client: client) } .navigationDestination(for: BuildRoute.self) { route in destination(route, client: client) } .navigationDestination(for: ReleaseRoute.self) { route in destination(route, client: client) } .navigationDestination(for: OrgRoute.self) { route in destination(route, client: client) } } @ViewBuilder private func destination(_ route: RepoRoute, client: GitbayClient) -> some View { switch route { case .repo(let path): RepoView(client: client, path: path) case .tree(let repo, let directory, let ref): TreeView(client: client, repo: repo, directory: directory, ref: ref) case .file(let repo, let path, let ref): FileView(client: client, repo: repo, path: path, ref: ref) case .log(let repo, let ref, let path): LogView(client: client, repo: repo, ref: ref, path: path) case .settings(let repo): RepoSettingsView(client: client, repo: repo) case .grep(let repo): GrepView(client: client, repo: repo) case .blame(let repo, let path, let ref): BlameView(client: client, repo: repo, path: path, ref: ref) case .refs(let repo): RefsView(client: client, repo: repo) case .milestones(let repo): MilestoneListView(client: client, repo: repo) case .wiki(let repo): WikiView(client: client, repo: repo) case .wikiPage(let repo, let page): WikiPageView(client: client, repo: repo, page: page) case .commit(let repo, let sha): CommitView(client: client, repo: repo, sha: sha) case .profile(let name): ProfileView(client: client, name: name) case .account: AccountView(client: client) case .addAccount: SignInView() } } @ViewBuilder private func destination(_ route: MRRoute, client: GitbayClient) -> some View { switch route { case .list(let repo): MRListView(client: client, repo: repo) case .mr(let repo, let number): MRView(client: client, repo: repo, number: number) case .diff(let repo, let number): DiffView(client: client, repo: repo, number: number) } } @ViewBuilder private func destination(_ route: IssueRoute, client: GitbayClient) -> some View { switch route { case .list(let repo): IssueListView(client: client, repo: repo) case .issue(let repo, let number): IssueView(client: client, repo: repo, number: number) } } @ViewBuilder private func destination(_ route: OrgRoute, client: GitbayClient) -> some View { switch route { case .org(let name): OrgView(client: client, org: name) case .team(let org, let team): TeamView(client: client, org: org, team: team) } } @ViewBuilder private func destination(_ route: ReleaseRoute, client: GitbayClient) -> some View { switch route { case .list(let repo): ReleaseListView(client: client, repo: repo) case .release(let repo, let tag): ReleaseView(client: client, repo: repo, tag: tag) } } @ViewBuilder private func destination(_ route: BuildRoute, client: GitbayClient) -> some View { switch route { case .list(let repo): BuildListView(client: client, repo: repo) case .detail(let repo, let number): BuildDetailView(client: client, repo: repo, number: number) } } } extension View { func navigationDestinations(client: GitbayClient) -> some View { modifier(RouteDestinations(client: client)) } } #Preview { ContentView() .environment(SessionStore()) }