gitbay/ContentView.swift
152 lines · 5093 bytes
1import SwiftUI
2
3struct ContentView: View {
4
5 @Environment(SessionStore.self) private var session
6
7 var body: some View {
8 if let client = session.client, let account = session.current {
9 TabView {
10 Tab("Dashboard", systemImage: "square.grid.2x2") {
11 NavigationStack {
12 DashboardView(client: client)
13 .navigationDestinations(client: client)
14 }
15 }
16 Tab("Feed", systemImage: "bolt") {
17 NavigationStack {
18 FeedView(client: client)
19 .navigationDestinations(client: client)
20 }
21 }
22 Tab("Repositories", systemImage: "books.vertical") {
23 NavigationStack {
24 RepoListView(client: client)
25 .navigationDestinations(client: client)
26 }
27 }
28 }
29 .id(account.id) // fresh screens on account switch
30 } else {
31 NavigationStack {
32 SignInView()
33 }
34 }
35 }
36
37}
38
39/// Every value-routed screen, attachable to any stack root.
40private struct RouteDestinations: ViewModifier {
41
42 let client: GitbayClient
43
44 func body(content: Content) -> some View {
45 content
46 .navigationDestination(for: RepoRoute.self) { route in
47 destination(route, client: client)
48 }
49 .navigationDestination(for: MRRoute.self) { route in
50 destination(route, client: client)
51 }
52 .navigationDestination(for: IssueRoute.self) { route in
53 destination(route, client: client)
54 }
55 .navigationDestination(for: BuildRoute.self) { route in
56 destination(route, client: client)
57 }
58 .navigationDestination(for: ReleaseRoute.self) { route in
59 destination(route, client: client)
60 }
61 .navigationDestination(for: OrgRoute.self) { route in
62 destination(route, client: client)
63 }
64 }
65
66 @ViewBuilder
67 private func destination(_ route: RepoRoute, client: GitbayClient) -> some View {
68 switch route {
69 case .repo(let path):
70 RepoView(client: client, path: path)
71 case .tree(let repo, let directory, let ref):
72 TreeView(client: client, repo: repo, directory: directory, ref: ref)
73 case .file(let repo, let path, let ref):
74 FileView(client: client, repo: repo, path: path, ref: ref)
75 case .log(let repo):
76 LogView(client: client, repo: repo)
77 case .settings(let repo):
78 RepoSettingsView(client: client, repo: repo)
79 case .grep(let repo):
80 GrepView(client: client, repo: repo)
81 case .profile(let name):
82 ProfileView(client: client, name: name)
83 case .account:
84 AccountView(client: client)
85 case .addAccount:
86 SignInView()
87 }
88 }
89
90 @ViewBuilder
91 private func destination(_ route: MRRoute, client: GitbayClient) -> some View {
92 switch route {
93 case .list(let repo):
94 MRListView(client: client, repo: repo)
95 case .mr(let repo, let number):
96 MRView(client: client, repo: repo, number: number)
97 case .diff(let repo, let number):
98 DiffView(client: client, repo: repo, number: number)
99 }
100 }
101
102 @ViewBuilder
103 private func destination(_ route: IssueRoute, client: GitbayClient) -> some View {
104 switch route {
105 case .list(let repo):
106 IssueListView(client: client, repo: repo)
107 case .issue(let repo, let number):
108 IssueView(client: client, repo: repo, number: number)
109 }
110 }
111
112 @ViewBuilder
113 private func destination(_ route: OrgRoute, client: GitbayClient) -> some View {
114 switch route {
115 case .org(let name):
116 OrgView(client: client, org: name)
117 case .team(let org, let team):
118 TeamView(client: client, org: org, team: team)
119 }
120 }
121
122 @ViewBuilder
123 private func destination(_ route: ReleaseRoute, client: GitbayClient) -> some View {
124 switch route {
125 case .list(let repo):
126 ReleaseListView(client: client, repo: repo)
127 case .release(let repo, let tag):
128 ReleaseView(client: client, repo: repo, tag: tag)
129 }
130 }
131
132 @ViewBuilder
133 private func destination(_ route: BuildRoute, client: GitbayClient) -> some View {
134 switch route {
135 case .list(let repo):
136 BuildListView(client: client, repo: repo)
137 case .log(let repo, let number):
138 BuildLogView(client: client, repo: repo, number: number)
139 }
140 }
141}
142
143extension View {
144 func navigationDestinations(client: GitbayClient) -> some View {
145 modifier(RouteDestinations(client: client))
146 }
147}
148
149#Preview {
150 ContentView()
151 .environment(SessionStore())
152}