gitbay/ContentView.swift
178 lines · 6384 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 .milestones(let repo):
100 MilestoneListView(client: client, repo: repo)
101 case .wiki(let repo):
102 WikiView(client: client, repo: repo)
103 case .wikiPage(let repo, let page):
104 WikiPageView(client: client, repo: repo, page: page)
105 case .commit(let repo, let sha):
106 CommitView(client: client, repo: repo, sha: sha)
107 case .profile(let name):
108 ProfileView(client: client, name: name)
109 case .account:
110 AccountView(client: client)
111 case .addAccount:
112 SignInView()
113 }
114 }
115
116 @ViewBuilder
117 private func destination(_ route: MRRoute, client: GitbayClient) -> some View {
118 switch route {
119 case .list(let repo):
120 MRListView(client: client, repo: repo)
121 case .mr(let repo, let number):
122 MRView(client: client, repo: repo, number: number)
123 case .diff(let repo, let number):
124 DiffView(client: client, repo: repo, number: number)
125 }
126 }
127
128 @ViewBuilder
129 private func destination(_ route: IssueRoute, client: GitbayClient) -> some View {
130 switch route {
131 case .list(let repo):
132 IssueListView(client: client, repo: repo)
133 case .issue(let repo, let number):
134 IssueView(client: client, repo: repo, number: number)
135 }
136 }
137
138 @ViewBuilder
139 private func destination(_ route: OrgRoute, client: GitbayClient) -> some View {
140 switch route {
141 case .org(let name):
142 OrgView(client: client, org: name)
143 case .team(let org, let team):
144 TeamView(client: client, org: org, team: team)
145 }
146 }
147
148 @ViewBuilder
149 private func destination(_ route: ReleaseRoute, client: GitbayClient) -> some View {
150 switch route {
151 case .list(let repo):
152 ReleaseListView(client: client, repo: repo)
153 case .release(let repo, let tag):
154 ReleaseView(client: client, repo: repo, tag: tag)
155 }
156 }
157
158 @ViewBuilder
159 private func destination(_ route: BuildRoute, client: GitbayClient) -> some View {
160 switch route {
161 case .list(let repo):
162 BuildListView(client: client, repo: repo)
163 case .detail(let repo, let number):
164 BuildDetailView(client: client, repo: repo, number: number)
165 }
166 }
167}
168
169extension View {
170 func navigationDestinations(client: GitbayClient) -> some View {
171 modifier(RouteDestinations(client: client))
172 }
173}
174
175#Preview {
176 ContentView()
177 .environment(SessionStore())
178}