gitbay/ContentView.swift
209 lines · 7738 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 Tab("Explore", systemImage: "safari") {
29 NavigationStack {
30 ExploreView(client: client)
31 .navigationDestinations(client: client)
32 }
33 }
34 Tab("My Profile", systemImage: "person.crop.circle") {
35 NavigationStack {
36 ProfileView(client: client, name: account.username,
37 title: "My Profile")
38 .toolbar { AccountMenu() }
39 .navigationDestinations(client: client)
40 }
41 }
42 }
43 .id(account.id) // fresh screens on account switch
44 } else {
45 NavigationStack {
46 SignInView()
47 }
48 }
49 }
50
51}
52
53/// Every value-routed screen, attachable to any stack root.
54private struct RouteDestinations: ViewModifier {
55
56 let client: GitbayClient
57
58 func body(content: Content) -> some View {
59 content
60 .navigationDestination(for: RepoRoute.self) { route in
61 destination(route, client: client)
62 }
63 .navigationDestination(for: MRRoute.self) { route in
64 destination(route, client: client)
65 }
66 .navigationDestination(for: IssueRoute.self) { route in
67 destination(route, client: client)
68 }
69 .navigationDestination(for: BuildRoute.self) { route in
70 destination(route, client: client)
71 }
72 .navigationDestination(for: ReleaseRoute.self) { route in
73 destination(route, client: client)
74 }
75 .navigationDestination(for: OrgRoute.self) { route in
76 destination(route, client: client)
77 }
78 .navigationDestination(for: SnippetRoute.self) { route in
79 destination(route, client: client)
80 }
81 }
82
83 @ViewBuilder
84 private func destination(_ route: RepoRoute, client: GitbayClient) -> some View {
85 switch route {
86 case .repo(let path):
87 RepoView(client: client, path: path)
88 case .tree(let repo, let directory, let ref):
89 TreeView(client: client, repo: repo, directory: directory, ref: ref)
90 case .file(let repo, let path, let ref):
91 FileView(client: client, repo: repo, path: path, ref: ref)
92 case .log(let repo, let ref, let path):
93 LogView(client: client, repo: repo, ref: ref, path: path)
94 case .settings(let repo):
95 RepoSettingsView(client: client, repo: repo)
96 case .grep(let repo):
97 GrepView(client: client, repo: repo)
98 case .blame(let repo, let path, let ref):
99 BlameView(client: client, repo: repo, path: path, ref: ref)
100 case .refs(let repo):
101 RefsView(client: client, repo: repo)
102 case .compare(let repo, let defaultBranch):
103 CompareView(client: client, repo: repo, defaultBranch: defaultBranch)
104 case .milestones(let repo):
105 MilestoneListView(client: client, repo: repo)
106 case .labels(let repo):
107 LabelListView(client: client, repo: repo)
108 case .bookmarks:
109 BookmarkListView(client: client)
110 case .webhooks(let repo):
111 WebhookListView(client: client, repo: repo)
112 case .webhookDeliveries(let repo):
113 WebhookDeliveriesView(client: client, repo: repo)
114 case .wiki(let repo):
115 WikiView(client: client, repo: repo)
116 case .wikiPage(let repo, let page):
117 WikiPageView(client: client, repo: repo, page: page)
118 case .commit(let repo, let sha):
119 CommitView(client: client, repo: repo, sha: sha)
120 case .profile(let name):
121 ProfileView(client: client, name: name)
122 case .account:
123 AccountView(client: client)
124 case .addAccount:
125 SignInView()
126 case .notifications:
127 NotificationsView(client: client)
128 }
129 }
130
131 @ViewBuilder
132 private func destination(_ route: MRRoute, client: GitbayClient) -> some View {
133 switch route {
134 case .list(let repo):
135 MRListView(client: client, repo: repo)
136 case .mr(let repo, let number):
137 MRView(client: client, repo: repo, number: number)
138 case .diff(let repo, let number):
139 DiffView(client: client, repo: repo, number: number)
140 case .rangeDiff(let repo, let number, let from, let to):
141 RangeDiffView(client: client, repo: repo, number: number, from: from, to: to)
142 }
143 }
144
145 @ViewBuilder
146 private func destination(_ route: IssueRoute, client: GitbayClient) -> some View {
147 switch route {
148 case .list(let repo):
149 IssueListView(client: client, repo: repo)
150 case .issue(let repo, let number):
151 IssueView(client: client, repo: repo, number: number)
152 }
153 }
154
155 @ViewBuilder
156 private func destination(_ route: OrgRoute, client: GitbayClient) -> some View {
157 switch route {
158 case .org(let name):
159 OrgView(client: client, org: name)
160 case .team(let org, let team):
161 TeamView(client: client, org: org, team: team)
162 case .labels(let org):
163 LabelListView(client: client, owner: .org(org))
164 case .milestones(let org):
165 MilestoneListView(client: client, owner: .org(org))
166 }
167 }
168
169 @ViewBuilder
170 private func destination(_ route: SnippetRoute, client: GitbayClient) -> some View {
171 switch route {
172 case .list(let owner):
173 SnippetListView(client: client, owner: owner)
174 case .snippet(let id):
175 SnippetView(client: client, id: id)
176 }
177 }
178
179 @ViewBuilder
180 private func destination(_ route: ReleaseRoute, client: GitbayClient) -> some View {
181 switch route {
182 case .list(let repo):
183 ReleaseListView(client: client, repo: repo)
184 case .release(let repo, let tag):
185 ReleaseView(client: client, repo: repo, tag: tag)
186 }
187 }
188
189 @ViewBuilder
190 private func destination(_ route: BuildRoute, client: GitbayClient) -> some View {
191 switch route {
192 case .list(let repo):
193 BuildListView(client: client, repo: repo)
194 case .detail(let repo, let number):
195 BuildDetailView(client: client, repo: repo, number: number)
196 }
197 }
198}
199
200extension View {
201 func navigationDestinations(client: GitbayClient) -> some View {
202 modifier(RouteDestinations(client: client))
203 }
204}
205
206#Preview {
207 ContentView()
208 .environment(SessionStore())
209}