ListlessiOS/Views/SettingsView.swift (4489B)
1import SwiftUI
2
3struct SettingsView: View {
4 @ObservedObject var syncMonitor: CloudKitSyncMonitor
5 @Environment(\.dismiss) private var dismiss
6 @AppStorage("appearanceMode") private var appearanceMode = 0
7 @AppStorage("colorTheme") private var colorThemeRaw = 0
8 @AppStorage("hapticsEnabled") private var hapticsEnabled = true
9 @AppStorage("debugMode") private var debugMode = false
10 @AppStorage("showFPSOverlay") private var showFPSOverlay = false
11 @AppStorage("didCompleteTutorial") private var didCompleteTutorial = false
12 @State private var easterEggTaps = 0
13
14 var body: some View {
15 NavigationStack {
16 List {
17 Section("Theme") {
18 ForEach(ColorTheme.displayOrder) { theme in
19 Button {
20 colorThemeRaw = theme.rawValue
21 } label: {
22 HStack {
23 Image(systemName: "checkmark")
24 .fontWeight(.semibold)
25 .foregroundStyle(.blue)
26 .opacity(colorThemeRaw == theme.rawValue ? 1 : 0)
27 Text(theme.displayName)
28 Spacer()
29 LinearGradient(
30 colors: [
31 itemColor(forIndex: 0, total: 5, theme: theme),
32 itemColor(forIndex: 2, total: 5, theme: theme),
33 itemColor(forIndex: 4, total: 5, theme: theme),
34 ],
35 startPoint: .leading,
36 endPoint: .trailing
37 )
38 .frame(width: 80, height: 24)
39 .clipShape(RoundedRectangle(cornerRadius: 6))
40 }
41 .contentShape(Rectangle())
42 }
43 .buttonStyle(.plain)
44 }
45 }
46
47 if UIDevice.current.userInterfaceIdiom == .phone {
48 Section("Interactions") {
49 Toggle("Haptics", isOn: $hapticsEnabled)
50 }
51 }
52
53 Section("Appearance") {
54 Picker("Appearance", selection: $appearanceMode) {
55 Text("System").tag(0)
56 Text("Light").tag(1)
57 Text("Dark").tag(2)
58 }
59 .pickerStyle(.segmented)
60 }
61
62 if debugMode {
63 Section("Debugging") {
64 Toggle("FPS Overlay", isOn: $showFPSOverlay)
65 NavigationLink("iCloud Diagnostics") {
66 SyncDiagnosticsView(syncMonitor: syncMonitor)
67 }
68 NavigationLink("Perf Samples") {
69 PerfDebugView()
70 }
71 Button("Reset Tutorial") {
72 didCompleteTutorial = false
73 dismiss()
74 }
75 }
76 }
77
78 Section {
79 NavigationLink("About") {
80 AboutView()
81 }
82 } footer: {
83 Text("Made in Tokyo from natural ones and zeros")
84 .frame(maxWidth: .infinity)
85 .multilineTextAlignment(.center)
86 .padding(.top, 24)
87 .onTapGesture {
88 easterEggTaps += 1
89 if easterEggTaps >= 4 {
90 debugMode.toggle()
91 if !debugMode {
92 showFPSOverlay = false
93 }
94 easterEggTaps = 0
95 }
96 }
97 }
98 }
99 .navigationTitle("Settings")
100 .navigationBarTitleDisplayMode(.inline)
101 .toolbar {
102 ToolbarItem(placement: .topBarLeading) {
103 Button("Done") { dismiss() }
104 }
105 }
106 }
107 }
108}