gitbay/Views/Discovery/ExploreView.swift
69 lines · 2650 bytes
1import SwiftUI
2
3/// What this instance hosts. `repo search` needs a query; this is the
4/// listing you read when you do not know a name yet.
5struct ExploreView: View {
6
7 @State private var list: PagedListModel<PublicRepo>
8
9 init(client: GitbayClient) {
10 _list = State(initialValue: PagedListModel(
11 client: client,
12 argv: ["explore"],
13 emptyMessage: "This instance hosts no public repositories."
14 ))
15 }
16
17 /// One Text, not two: the HStack spaces its children, and a gap
18 /// between the owner and the name would read as part of the path.
19 private func path(of repo: PublicRepo) -> AttributedString {
20 var owner = AttributedString(repo.owner + "/")
21 owner.foregroundColor = .secondary
22 var name = AttributedString(repo.name)
23 name.font = .gbSans(.subheadline).weight(.medium)
24 return owner + name
25 }
26
27 var body: some View {
28 List {
29 ForEach(list.state.value ?? []) { repo in
30 NavigationLink(value: RepoRoute.repo(repo.path)) {
31 VStack(alignment: .leading, spacing: 4) {
32 HStack(spacing: 6) {
33 Text(path(of: repo))
34 if repo.isArchived {
35 GBChip("archived", .secondary)
36 }
37 }
38 .font(.gbSans(.subheadline))
39 .lineLimit(1)
40
41 if let description = repo.description, !description.isEmpty {
42 Text(description)
43 .font(.gbSans(.caption))
44 .foregroundStyle(.secondary)
45 .lineLimit(2)
46 }
47 if let topics = repo.topics, !topics.isEmpty {
48 ScrollView(.horizontal, showsIndicators: false) {
49 HStack(spacing: 6) {
50 ForEach(topics, id: \.self) { topic in
51 GBChip(topic, .gbAccent)
52 }
53 }
54 }
55 }
56 }
57 .padding(.vertical, 2)
58 }
59 }
60 PageFooter(list: list)
61 }
62 .overlay { LoadStateOverlay(state: list.state) }
63 .navigationTitle("Explore")
64 .task {
65 if list.state.value == nil { await list.reload() }
66 }
67 .refreshable { await list.reload() }
68 }
69}