iOS client for Grain grain.social
ios photography atproto
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add appearance settings for auto, light, and dark mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+55 -2
+10
Grain/GrainApp.swift
··· 44 44 @State private var viewedStoryStorage = ViewedStoryStorage() 45 45 @State private var labelDefsCache = LabelDefinitionsCache() 46 46 @State private var pendingDeepLink: DeepLink? 47 + @AppStorage("appearance") private var appearance: String = "auto" 48 + 49 + private var colorScheme: ColorScheme? { 50 + switch appearance { 51 + case "light": .light 52 + case "dark": .dark 53 + default: nil 54 + } 55 + } 47 56 48 57 var body: some Scene { 49 58 WindowGroup { ··· 86 95 pendingDeepLink = deepLink 87 96 } 88 97 } 98 + .preferredColorScheme(colorScheme) 89 99 } 90 100 .environment(authManager) 91 101 }
+45 -2
Grain/Views/Settings/SettingsView.swift
··· 9 9 @State private var cacheSizeText = "Calculating..." 10 10 @State private var safariURL: URL? 11 11 12 + @AppStorage("appearance") private var appearance: String = "auto" 13 + 14 + private var appearanceLabel: String { 15 + switch appearance { 16 + case "light": "Light" 17 + case "dark": "Dark" 18 + default: "Auto" 19 + } 20 + } 21 + 12 22 var body: some View { 13 23 List { 14 24 Section { 25 + NavigationLink { 26 + AppearanceSettingsView() 27 + } label: { 28 + LabeledContent("Appearance", value: appearanceLabel) 29 + } 15 30 NavigationLink("Account") { 16 31 AccountDetailView() 17 32 } ··· 22 37 ModerationView(client: client) 23 38 } 24 39 NavigationLink("Feeds") { 25 - AppearanceSettingsView() 40 + FeedsSettingsView() 26 41 } 27 42 NavigationLink("Privacy") { 28 43 UploadDefaultsView(client: client) ··· 165 180 } 166 181 } 167 182 168 - private struct AppearanceSettingsView: View { 183 + private struct FeedsSettingsView: View { 169 184 @AppStorage("privacy.showSuggestedUsers") private var showSuggestedUsers = true 170 185 171 186 var body: some View { ··· 175 190 } 176 191 } 177 192 .navigationTitle("Feeds") 193 + } 194 + } 195 + 196 + private struct AppearanceSettingsView: View { 197 + @AppStorage("appearance") private var appearance: String = "auto" 198 + 199 + var body: some View { 200 + List { 201 + Section { 202 + ForEach(["auto", "light", "dark"], id: \.self) { option in 203 + HStack { 204 + Text(option == "auto" ? "Automatic" : option == "light" ? "Light" : "Dark") 205 + Spacer() 206 + if appearance == option { 207 + Image(systemName: "checkmark.circle.fill") 208 + .foregroundStyle(Color.accentColor) 209 + } 210 + } 211 + .contentShape(Rectangle()) 212 + .onTapGesture { 213 + appearance = option 214 + } 215 + } 216 + } footer: { 217 + Text("Automatic follows your device's system setting.") 218 + } 219 + } 220 + .navigationTitle("Appearance") 178 221 } 179 222 } 180 223