summaryrefslogtreecommitdiff
path: root/DomainDig/AppInfo.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-07-25 11:35:46 -0500
committerChristian Cleberg <[email protected]>2026-07-25 11:49:23 -0500
commit074052763638a36e274e18d00f5f5ab21846be28 (patch)
tree9daf0a4c919fa8dc79c24b629157af45577ed4e4 /DomainDig/AppInfo.swift
parentb824dae8ea16d20d75136687a7c59bc7b01afe27 (diff)
downloaddomain-dig-074052763638a36e274e18d00f5f5ab21846be28.tar.gz
domain-dig-074052763638a36e274e18d00f5f5ab21846be28.tar.bz2
domain-dig-074052763638a36e274e18d00f5f5ab21846be28.zip
feat: enrich Settings → App Info with metadata & resource links (#56)
Replaces the three-row App Info screen with a full About/Resources/Support/ Legal layout, driven by a declarative AppInfoRow model with all URLs centralized in one AppLinks namespace. - About: Version now shows "5.0.0 (build N)" (CFBundleShortVersionString + CFBundleVersion), plus Storage, Backup Schema, and Minimum iOS (17.6). - Resources: What's New (bundled ReleaseNotes.json sheet, no network), Documentation & FAQ, Source Code, Privacy Policy, and Acknowledgements ("no third-party dependencies" + MIT license). - Support: Report an Issue (a sheet that shows the locally-assembled version/OS/device diagnostics before offering Email or GitHub — nothing is collected silently) and Contact (mailto). - Support the App: Rate (SwiftUI's @Environment(\.requestReview), which handles the scene internally and respects Apple's throttling — the modern, safer equivalent of the issue's SKStoreReviewController + connectedScenes path) and Share (ShareLink to the App Store listing). - Legal: copyright footer with the current year. External rows use Link/openURL with an "opens outside the app" accessibility hint; the screen is standard adaptive Form controls with semantic colors, so it tracks Dynamic Type and light/dark automatically. New files (AppLinks, AppInfo, ReleaseNotes[.swift/.json], AppInfoView) auto- compile/bundle via the synchronized DomainDig/ group. AppInfoTests covers the mailto builder, version format, diagnostics contents, and that the bundled notes ship and parse. Unit suite green. Placeholder pending the App Store listing: AppLinks.appStoreID (the review/share URLs derive from it), flagged with a TODO.
Diffstat (limited to 'DomainDig/AppInfo.swift')
-rw-r--r--DomainDig/AppInfo.swift52
1 files changed, 52 insertions, 0 deletions
diff --git a/DomainDig/AppInfo.swift b/DomainDig/AppInfo.swift
new file mode 100644
index 0000000..28b0826
--- /dev/null
+++ b/DomainDig/AppInfo.swift
@@ -0,0 +1,52 @@
+import Foundation
+import UIKit
+
+/// Runtime app metadata read from the bundle, plus the locally-assembled
+/// diagnostics used to prefill an issue report. Nothing here touches the network
+/// or collects any identifier beyond the app version, iOS version, and hardware
+/// model string.
+enum AppInfo {
+ /// CFBundleShortVersionString (marketing version), falling back to the
+ /// compiled-in `AppVersion.current` if the Info.plist key is missing.
+ static var marketingVersion: String {
+ Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? AppVersion.current
+ }
+
+ /// CFBundleVersion (build number).
+ static var buildNumber: String {
+ Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "—"
+ }
+
+ /// "5.0.0 (build 45)" — version alongside build, as the App Info row shows it.
+ static var versionDisplay: String {
+ "\(marketingVersion) (build \(buildNumber))"
+ }
+
+ static let minimumOS = "17.6"
+
+ static var systemVersion: String {
+ UIDevice.current.systemVersion
+ }
+
+ /// Hardware model identifier (e.g. "iPhone15,2") — a model string, not a
+ /// per-device identifier.
+ static var deviceModel: String {
+ var systemInfo = utsname()
+ uname(&systemInfo)
+ let identifier = withUnsafeBytes(of: &systemInfo.machine) { raw -> String in
+ let bytes = raw.prefix { $0 != 0 }
+ return String(decoding: bytes, as: UTF8.self)
+ }
+ return identifier.isEmpty ? "Unknown" : identifier
+ }
+
+ /// Diagnostics prefilled into an issue report. Shown to the user before any
+ /// send — never collected silently.
+ static var diagnosticsReport: String {
+ """
+ DomainDig \(versionDisplay)
+ iOS \(systemVersion)
+ Device \(deviceModel)
+ """
+ }
+}