gitbay/ContentView.swift
184 lines · 6679 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 }
79
80 @ViewBuilder
81 private func destination(_ route: RepoRoute, client: GitbayClient) -> some View {
82 switch route {
83 case .repo(let path):
84 RepoView(client: client, path: path)
85 case .tree(let repo, let directory, let ref):
86 TreeView(client: client, repo: repo, directory: directory, ref: ref)
87 case .file(let repo, let path, let ref):
88 FileView(client: client, repo: repo, path: path, ref: ref)
89 case .log(let repo, let ref, let path):
90 LogView(client: client, repo: repo, ref: ref, path: path)
91 case .settings(let repo):
92 RepoSettingsView(client: client, repo: repo)
93 case .grep(let repo):
94 GrepView(client: client, repo: repo)
95 case .blame(let repo, let path, let ref):
96 BlameView(client: client, repo: repo, path: path, ref: ref)
97 case .refs(let repo):
98 RefsView(client: client, repo: repo)
99 case .compare(let repo, let defaultBranch):
100 CompareView(client: client, repo: repo, defaultBranch: defaultBranch)
101 case .milestones(let repo):
102 MilestoneListView(client: client, repo: repo)
103 case .labels(let repo):
104 LabelListView(client: client, repo: repo)
105 case .wiki(let repo):
106 WikiView(client: client, repo: repo)
107 case .wikiPage(let repo, let page):
108 WikiPageView(client: client, repo: repo, page: page)
109 case .commit(let repo, let sha):
110 CommitView(client: client, repo: repo, sha: sha)
111 case .profile(let name):
112 ProfileView(client: client, name: name)
113 case .account:
114 AccountView(client: client)
115 case .addAccount:
116 SignInView()
117 case .notifications:
118 NotificationsView(client: client)
119 }
120 }
121
122 @ViewBuilder
123 private func destination(_ route: MRRoute, client: GitbayClient) -> some View {
124 switch route {
125 case .list(let repo):
126 MRListView(client: client, repo: repo)
127 case .mr(let repo, let number):
128 MRView(client: client, repo: repo, number: number)
129 case .diff(let repo, let number):
130 DiffView(client: client, repo: repo, number: number)
131 }
132 }
133
134 @ViewBuilder
135 private func destination(_ route: IssueRoute, client: GitbayClient) -> some View {
136 switch route {
137 case .list(let repo):
138 IssueListView(client: client, repo: repo)
139 case .issue(let repo, let number):
140 IssueView(client: client, repo: repo, number: number)
141 }
142 }
143
144 @ViewBuilder
145 private func destination(_ route: OrgRoute, client: GitbayClient) -> some View {
146 switch route {
147 case .org(let name):
148 OrgView(client: client, org: name)
149 case .team(let org, let team):
150 TeamView(client: client, org: org, team: team)
151 }
152 }
153
154 @ViewBuilder
155 private func destination(_ route: ReleaseRoute, client: GitbayClient) -> some View {
156 switch route {
157 case .list(let repo):
158 ReleaseListView(client: client, repo: repo)
159 case .release(let repo, let tag):
160 ReleaseView(client: client, repo: repo, tag: tag)
161 }
162 }
163
164 @ViewBuilder
165 private func destination(_ route: BuildRoute, client: GitbayClient) -> some View {
166 switch route {
167 case .list(let repo):
168 BuildListView(client: client, repo: repo)
169 case .detail(let repo, let number):
170 BuildDetailView(client: client, repo: repo, number: number)
171 }
172 }
173}
174
175extension View {
176 func navigationDestinations(client: GitbayClient) -> some View {
177 modifier(RouteDestinations(client: client))
178 }
179}
180
181#Preview {
182 ContentView()
183 .environment(SessionStore())
184}