diff options
| author | Christian Cleberg <[email protected]> | 2026-04-14 10:42:05 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-14 10:42:05 -0500 |
| commit | 205c8ea9b2c6dfa62bc8b2342d1aa71e2da7d6ac (patch) | |
| tree | e7e9b8190ffc15d3cd3e696da4c8acf8c472a193 /Hutch/Views/More/AboutView.swift | |
| parent | d6968ea122d910b432bd539cf2fa3d1cee962fdb (diff) | |
| download | hutch-3.1.6.tar.gz hutch-3.1.6.tar.bz2 hutch-3.1.6.zip | |
fix: remove prototype screens from developer menuv3.1.6
- removed prototype screens
- limited Recent section to 3 items
- added initial support for tips
Fixes: https://todo.sr.ht/~ccleberg/hutch/65
Diffstat (limited to 'Hutch/Views/More/AboutView.swift')
| -rw-r--r-- | Hutch/Views/More/AboutView.swift | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/Hutch/Views/More/AboutView.swift b/Hutch/Views/More/AboutView.swift new file mode 100644 index 0000000..887bef1 --- /dev/null +++ b/Hutch/Views/More/AboutView.swift @@ -0,0 +1,146 @@ +import StoreKit +import SwiftUI + +struct AboutView: View { + @Environment(AppState.self) private var appState + private let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String + ?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String + ?? "Hutch" + private let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String + ?? "Unknown" + private let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String + ?? "Unknown" + @State private var developerRevealCount = 0 + @State private var storeViewModel = TipStoreViewModel() + + private var developerToolsVisible: Bool { + appState.isDebugModeEnabled || developerRevealCount >= 5 + } + + private var developerRevealFooterText: String { + developerRevealCount >= 5 + ? "Debug toggle unlocked. Scroll down to Developer to enable it." + : "Tap the build number 5 times to reveal the debug toggle." + } + + var body: some View { + Form { + Section { + VStack(alignment: .leading, spacing: 6) { + Text(appName) + .font(.title2.weight(.semibold)) + Text("A native SourceHut client for iOS.") + .font(.subheadline) + .foregroundStyle(.secondary) + } + .padding(.vertical, 4) + .themedRow() + + LabeledContent("Version", value: version) + .onTapGesture { + developerRevealCount = min(developerRevealCount + 1, 5) + } + .themedRow() + LabeledContent("Build", value: build) + .onTapGesture { + developerRevealCount = min(developerRevealCount + 1, 5) + } + .themedRow() + } footer: { + Text(developerRevealFooterText) + } + + Section("Links") { + Link(destination: URL(string: "https://sr.ht")!) { + SwiftUI.Label("SourceHut", systemImage: "link") + } + .themedRow() + Link(destination: URL(string: "https://man.sr.ht")!) { + SwiftUI.Label("SourceHut Manuals", systemImage: "book") + } + .themedRow() + Link(destination: URL(string: "https://sr.ht/~ccleberg/Hutch")!) { + SwiftUI.Label("Project Repository", systemImage: "folder") + } + .themedRow() + } + + Section("Support") { + Link(destination: URL(string: "mailto:[email protected]")!) { + SwiftUI.Label("Email Support", systemImage: "envelope") + } + .themedRow() + } + + Section("Privacy") { + Text("Hutch uses your SourceHut personal access token to make requests on your behalf. The token is stored locally in the iOS keychain.") + .font(.subheadline) + .foregroundStyle(.secondary) + .themedRow() + + Link(destination: URL(string: "https://zerolabs.sh/hutch/privacy-policy/")!) { + SwiftUI.Label("Privacy Policy", systemImage: "hand.raised") + } + .themedRow() + } + + Section("Acknowledgements") { + Text("Built for SourceHut users who want quick access to repositories, builds, and tickets on iOS.") + .font(.subheadline) + .foregroundStyle(.secondary) + .themedRow() + } + + Section { + if storeViewModel.isLoading { + ProgressView() + .themedRow() + } else if storeViewModel.products.isEmpty { + Text("Tips unavailable") + .foregroundStyle(.secondary) + .themedRow() + } else { + ForEach(storeViewModel.products, id: \.id) { product in + Button { + Task { + await storeViewModel.purchase(product) + } + } label: { + HStack { + Text(product.displayName) + Spacer() + Text(product.displayPrice) + .foregroundStyle(.secondary) + } + } + .themedRow() + } + } + } header: { + Text("Support Development") + } footer: { + Text("Tips help cover the costs of development and App Store distribution. They are one-time purchases and do not unlock any features.") + } + + if developerToolsVisible { + Section { + Toggle("Debug Mode", isOn: Binding( + get: { appState.isDebugModeEnabled }, + set: { appState.isDebugModeEnabled = $0 } + )) + .themedRow() + } header: { + Text("Developer") + } footer: { + Text("Shows raw API payloads and diagnostic details on builds and tickets screens. This stays hidden until explicitly enabled.") + } + } + } + .themedList() + .navigationTitle("About") + .navigationBarTitleDisplayMode(.inline) + .task { + await storeViewModel.loadProducts() + } + } +} |
