gitbay/ContentView.swift
172 lines · 6083 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 }
35 .id(account.id) // fresh screens on account switch
36 } else {
37 NavigationStack {
38 SignInView()
39 }
40 }
41 }
42
43}
44
45/// Every value-routed screen, attachable to any stack root.
46private struct RouteDestinations: ViewModifier {
47
48 let client: GitbayClient
49
50 func body(content: Content) -> some View {
51 content
52 .navigationDestination(for: RepoRoute.self) { route in
53 destination(route, client: client)
54 }
55 .navigationDestination(for: MRRoute.self) { route in
56 destination(route, client: client)
57 }
58 .navigationDestination(for: IssueRoute.self) { route in
59 destination(route, client: client)
60 }
61 .navigationDestination(for: BuildRoute.self) { route in
62 destination(route, client: client)
63 }
64 .navigationDestination(for: ReleaseRoute.self) { route in
65 destination(route, client: client)
66 }
67 .navigationDestination(for: OrgRoute.self) { route in
68 destination(route, client: client)
69 }
70 }
71
72 @ViewBuilder
73 private func destination(_ route: RepoRoute, client: GitbayClient) -> some View {
74 switch route {
75 case .repo(let path):
76 RepoView(client: client, path: path)
77 case .tree(let repo, let directory, let ref):
78 TreeView(client: client, repo: repo, directory: directory, ref: ref)
79 case .file(let repo, let path, let ref):
80 FileView(client: client, repo: repo, path: path, ref: ref)
81 case .log(let repo, let ref, let path):
82 LogView(client: client, repo: repo, ref: ref, path: path)
83 case .settings(let repo):
84 RepoSettingsView(client: client, repo: repo)
85 case .grep(let repo):
86 GrepView(client: client, repo: repo)
87 case .blame(let repo, let path, let ref):
88 BlameView(client: client, repo: repo, path: path, ref: ref)
89 case .refs(let repo):
90 RefsView(client: client, repo: repo)
91 case .milestones(let repo):
92 MilestoneListView(client: client, repo: repo)
93 case .wiki(let repo):
94 WikiView(client: client, repo: repo)
95 case .wikiPage(let repo, let page):
96 WikiPageView(client: client, repo: repo, page: page)
97 case .commit(let repo, let sha):
98 CommitView(client: client, repo: repo, sha: sha)
99 case .commitDiff(let repo, let sha):
100 CommitDiffView(client: client, repo: repo, sha: sha)
101 case .profile(let name):
102 ProfileView(client: client, name: name)
103 case .account:
104 AccountView(client: client)
105 case .addAccount:
106 SignInView()
107 }
108 }
109
110 @ViewBuilder
111 private func destination(_ route: MRRoute, client: GitbayClient) -> some View {
112 switch route {
113 case .list(let repo):
114 MRListView(client: client, repo: repo)
115 case .mr(let repo, let number):
116 MRView(client: client, repo: repo, number: number)
117 case .diff(let repo, let number):
118 DiffView(client: client, repo: repo, number: number)
119 }
120 }
121
122 @ViewBuilder
123 private func destination(_ route: IssueRoute, client: GitbayClient) -> some View {
124 switch route {
125 case .list(let repo):
126 IssueListView(client: client, repo: repo)
127 case .issue(let repo, let number):
128 IssueView(client: client, repo: repo, number: number)
129 }
130 }
131
132 @ViewBuilder
133 private func destination(_ route: OrgRoute, client: GitbayClient) -> some View {
134 switch route {
135 case .org(let name):
136 OrgView(client: client, org: name)
137 case .team(let org, let team):
138 TeamView(client: client, org: org, team: team)
139 }
140 }
141
142 @ViewBuilder
143 private func destination(_ route: ReleaseRoute, client: GitbayClient) -> some View {
144 switch route {
145 case .list(let repo):
146 ReleaseListView(client: client, repo: repo)
147 case .release(let repo, let tag):
148 ReleaseView(client: client, repo: repo, tag: tag)
149 }
150 }
151
152 @ViewBuilder
153 private func destination(_ route: BuildRoute, client: GitbayClient) -> some View {
154 switch route {
155 case .list(let repo):
156 BuildListView(client: client, repo: repo)
157 case .log(let repo, let number):
158 BuildLogView(client: client, repo: repo, number: number)
159 }
160 }
161}
162
163extension View {
164 func navigationDestinations(client: GitbayClient) -> some View {
165 modifier(RouteDestinations(client: client))
166 }
167}
168
169#Preview {
170 ContentView()
171 .environment(SessionStore())
172}