krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v3.0.4: Hutch/Views/More/MoreView.swift · raw
1import SwiftUI
2
3struct MoreView: View {
4 @Environment(AppState.self) private var appState
5
6 private let unsupportedLinks: [(title: String, url: URL)] = [
7 ("chat.sr.ht", SRHTWebURL.chat)
8 ]
9
10 @State private var viewModel: MoreViewModel?
11 @State private var showAccountSwitcher = false
12
13 var body: some View {
14 List {
15 Section("Search") {
16 NavigationLink(value: MoreRoute.lookup) {
17 Label("Look Up", systemImage: "magnifyingglass")
18 }
19 }
20
21 Section("Other Services") {
22 NavigationLink(value: MoreRoute.projects) {
23 Label("Projects", systemImage: "square.stack.3d.up")
24 }
25
26 NavigationLink(value: MoreRoute.lists) {
27 Label("Mailing Lists", systemImage: "list.bullet.rectangle")
28 }
29
30 NavigationLink(value: MoreRoute.manPageBrowser) {
31 Label("Man Pages", systemImage: "book")
32 }
33
34 NavigationLink(value: MoreRoute.pastes) {
35 Label("Pastes", systemImage: "doc.on.clipboard")
36 }
37
38 NavigationLink(value: MoreRoute.systemStatus) {
39 SystemStatusSummaryRow(
40 snapshot: viewModel?.systemStatusSnapshot,
41 isLoading: viewModel?.isLoadingSystemStatus ?? true,
42 errorMessage: viewModel?.systemStatusErrorMessage,
43 isShowingStaleData: viewModel?.isShowingStaleSystemStatus ?? false
44 )
45 }
46 }
47
48 Section("Meta") {
49 NavigationLink(value: MoreRoute.profile) {
50 Label("Profile", systemImage: "person.text.rectangle")
51 }
52
53 NavigationLink(value: MoreRoute.settings) {
54 Label("Settings", systemImage: "gear")
55 }
56 }
57
58 Section {
59 ForEach(unsupportedLinks, id: \.title) { item in
60 Link(destination: item.url) {
61 Label(item.title, systemImage: "safari")
62 }
63 }
64 } header: {
65 Text("External Links")
66 } footer: {
67 Text("These SourceHut services are not supported in-app, as the SourceHut API does not support them, and will open in your browser.")
68 }
69 }
70 .themedList()
71 .navigationTitle("More")
72 .refreshable {
73 await ensureViewModel().loadSystemStatus(forceRefresh: true)
74 }
75 .task {
76 await ensureViewModel().loadIfNeeded()
77 }
78 .toolbar {
79 ToolbarItem(placement: .topBarTrailing) {
80 Button {
81 showAccountSwitcher = true
82 } label: {
83 Image(systemName: "person.crop.circle.badge.plus")
84 }
85 }
86 }
87 .sheet(isPresented: $showAccountSwitcher) {
88 AccountSwitcherView()
89 }
90 }
91
92 @MainActor
93 private func ensureViewModel() -> MoreViewModel {
94 if let viewModel {
95 return viewModel
96 }
97
98 let newViewModel = MoreViewModel(repository: appState.systemStatusRepository)
99 viewModel = newViewModel
100 return newViewModel
101 }
102}