a native ios client for gitbay

client ios swift

https://gitbay.org

gitbay/Views/Repos/WikiView.swift

79 lines · 2762 bytes

 1import SwiftUI
 2
 3/// A repository's wiki pages, landing page first.
 4struct WikiView: View {
 5
 6    @State private var model: WikiViewModel
 7
 8    init(client: GitbayClient, repo: String) {
 9        _model = State(initialValue: WikiViewModel(client: client, repoPath: repo))
10    }
11
12    /// The landing page leads, then the rest in the order the server
13    /// gave them  the same order the web's sidebar shows.
14    private var ordered: [String] {
15        guard let listing = model.state.value else { return [] }
16        guard let home = listing.home else { return listing.pages }
17        return [home] + listing.pages.filter { $0 != home }
18    }
19
20    var body: some View {
21        List {
22            ForEach(ordered, id: \.self) { page in
23                NavigationLink(value: RepoRoute.wikiPage(
24                    repo: model.repoPath, page: page
25                )) {
26                    HStack(spacing: 8) {
27                        Label(page, systemImage: "doc.text")
28                            .font(.gbSans(.subheadline))
29                        if page == model.state.value?.home {
30                            GBChip("home", .gbAccent)
31                        }
32                    }
33                }
34            }
35        }
36        .overlay { LoadStateOverlay(state: model.state) }
37        .navigationTitle("Wiki")
38        .navigationBarTitleDisplayMode(.inline)
39        .task { await model.load() }
40        .refreshable { await model.load() }
41    }
42}
43
44/// One wiki page, rendered by its format  the pages here are .org as
45/// often as .md, so ReadmeView picks the renderer.
46struct WikiPageView: View {
47
48    @State private var model: WikiPageViewModel
49
50    init(client: GitbayClient, repo: String, page: String) {
51        _model = State(initialValue: WikiPageViewModel(
52            client: client, repoPath: repo, page: page
53        ))
54    }
55
56    var body: some View {
57        ScrollView {
58            if let page = model.state.value {
59                if page.isBinary {
60                    ContentUnavailableView {
61                        Label("Not a page", systemImage: "doc.zipper")
62                    } description: {
63                        Text(page.file)
64                    }
65                } else if let content = page.content {
66                    ReadmeView(name: page.file, content: content)
67                        .padding(.horizontal, 16)
68                        .padding(.vertical, 12)
69                        .frame(maxWidth: .infinity, alignment: .leading)
70                }
71            }
72        }
73        .overlay { LoadStateOverlay(state: model.state) }
74        .navigationTitle(model.page)
75        .navigationBarTitleDisplayMode(.inline)
76        .task { await model.load() }
77        .refreshable { await model.load() }
78    }
79}