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