krz/hutch

an ios client for sourcehut

clone: git clone https://gitbay.org/krz/hutch.git

v3.1.5: 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                .themedRow()
 20            }
 21
 22            Section("Other Services") {
 23                NavigationLink(value: MoreRoute.projects) {
 24                    Label("Projects", systemImage: "square.stack.3d.up")
 25                }
 26                .themedRow()
 27
 28                NavigationLink(value: MoreRoute.lists) {
 29                    Label("Mailing Lists", systemImage: "list.bullet.rectangle")
 30                }
 31                .themedRow()
 32
 33                NavigationLink(value: MoreRoute.manPageBrowser) {
 34                    Label("Man Pages", systemImage: "book")
 35                }
 36                .themedRow()
 37
 38                NavigationLink(value: MoreRoute.pastes) {
 39                    Label("Pastes", systemImage: "doc.on.clipboard")
 40                }
 41                .themedRow()
 42
 43                NavigationLink(value: MoreRoute.systemStatus) {
 44                    SystemStatusSummaryRow(
 45                        snapshot: viewModel?.systemStatusSnapshot,
 46                        isLoading: viewModel?.isLoadingSystemStatus ?? true,
 47                        errorMessage: viewModel?.systemStatusErrorMessage,
 48                        isShowingStaleData: viewModel?.isShowingStaleSystemStatus ?? false
 49                    )
 50                }
 51                .themedRow()
 52            }
 53
 54            Section("Meta") {
 55                NavigationLink(value: MoreRoute.profile) {
 56                    Label("Profile", systemImage: "person.text.rectangle")
 57                }
 58                .themedRow()
 59
 60                NavigationLink(value: MoreRoute.settings) {
 61                    Label("Settings", systemImage: "gear")
 62                }
 63                .themedRow()
 64            }
 65
 66            Section {
 67                ForEach(unsupportedLinks, id: \.title) { item in
 68                    Link(destination: item.url) {
 69                        Label(item.title, systemImage: "safari")
 70                    }
 71                }
 72                .themedRow()
 73            } header: {
 74                Text("External Links")
 75            } footer: {
 76                Text("These SourceHut services are not supported in-app, as the SourceHut API does not support them, and will open in your browser.")
 77            }
 78        }
 79        .themedList()
 80        .navigationTitle("More")
 81        .refreshable {
 82            await ensureViewModel().loadSystemStatus(forceRefresh: true)
 83        }
 84        .task {
 85            await ensureViewModel().loadIfNeeded()
 86        }
 87        .toolbar {
 88            ToolbarItem(placement: .topBarTrailing) {
 89                Button {
 90                    showAccountSwitcher = true
 91                } label: {
 92                    Image(systemName: "person.crop.circle.badge.plus")
 93                }
 94            }
 95        }
 96        .sheet(isPresented: $showAccountSwitcher) {
 97            AccountSwitcherView()
 98        }
 99    }
100
101    @MainActor
102    private func ensureViewModel() -> MoreViewModel {
103        if let viewModel {
104            return viewModel
105        }
106
107        let newViewModel = MoreViewModel(repository: appState.systemStatusRepository)
108        viewModel = newViewModel
109        return newViewModel
110    }
111}