gitbay/ContentView.swift

v1.2.0
gitbay-ios/gitbay/ContentView.swift history · blame · raw

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}