native macOS codings agent orchestrator
6
fork

Configure Feed

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

Store repository settings in main settings file

khoi fed75b2c fda58dda

+35 -29
+1 -1
supacode/App/supacodeApp.swift
··· 54 54 _ghostty = State(initialValue: runtime) 55 55 let shortcuts = GhosttyShortcutManager(runtime: runtime) 56 56 _ghosttyShortcuts = State(initialValue: shortcuts) 57 - let initialSettings = SettingsStorage().load() 57 + let initialSettings = SettingsStorage().load().global 58 58 let terminalManager = WorktreeTerminalManager(runtime: runtime) 59 59 _terminalManager = State(initialValue: terminalManager) 60 60 let keyObserver = CommandKeyObserver()
+6 -2
supacode/Clients/Settings/SettingsClient.swift
··· 8 8 9 9 extension SettingsClient: DependencyKey { 10 10 static let liveValue = SettingsClient( 11 - load: { SettingsStorage().load() }, 12 - save: { SettingsStorage().save($0) } 11 + load: { SettingsStorage().load().global }, 12 + save: { settings in 13 + var fileSettings = SettingsStorage().load() 14 + fileSettings.global = settings 15 + SettingsStorage().save(fileSettings) 16 + } 13 17 ) 14 18 static let testValue = SettingsClient( 15 19 load: { .default },
+11 -18
supacode/Features/Settings/BusinessLogic/RepositorySettingsStorage.swift
··· 2 2 3 3 nonisolated struct RepositorySettingsStorage { 4 4 func load(for rootURL: URL) -> RepositorySettings { 5 - let settingsURL = settingsURL(for: rootURL) 6 - if let data = try? Data(contentsOf: settingsURL), 7 - let settings = try? JSONDecoder().decode(RepositorySettings.self, from: data) 8 - { 5 + let repositoryID = repositoryID(for: rootURL) 6 + var fileSettings = SettingsStorage().load() 7 + if let settings = fileSettings.repositories[repositoryID] { 9 8 return settings 10 9 } 11 10 let defaults = RepositorySettings.default 12 - save(defaults, for: rootURL) 11 + fileSettings.repositories[repositoryID] = defaults 12 + SettingsStorage().save(fileSettings) 13 13 return defaults 14 14 } 15 15 16 16 func save(_ settings: RepositorySettings, for rootURL: URL) { 17 - do { 18 - let settingsURL = settingsURL(for: rootURL) 19 - let directory = settingsURL.deletingLastPathComponent() 20 - try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) 21 - let encoder = JSONEncoder() 22 - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] 23 - let data = try encoder.encode(settings) 24 - try data.write(to: settingsURL, options: [.atomic]) 25 - } catch { 26 - } 17 + let repositoryID = repositoryID(for: rootURL) 18 + var fileSettings = SettingsStorage().load() 19 + fileSettings.repositories[repositoryID] = settings 20 + SettingsStorage().save(fileSettings) 27 21 } 28 22 29 - private func settingsURL(for rootURL: URL) -> URL { 30 - SupacodePaths.repositoryDirectory(for: rootURL) 31 - .appending(path: "settings.json", directoryHint: .notDirectory) 23 + private func repositoryID(for rootURL: URL) -> String { 24 + rootURL.standardizedFileURL.path(percentEncoded: false) 32 25 } 33 26 }
+4 -4
supacode/Features/Settings/BusinessLogic/SettingsStorage.swift
··· 7 7 self.settingsURL = settingsURL 8 8 } 9 9 10 - func load() -> GlobalSettings { 10 + func load() -> SettingsFile { 11 11 if let data = try? Data(contentsOf: settingsURL), 12 - let settings = try? JSONDecoder().decode(GlobalSettings.self, from: data) 12 + let settings = try? JSONDecoder().decode(SettingsFile.self, from: data) 13 13 { 14 14 return settings 15 15 } 16 - let defaults = GlobalSettings.default 16 + let defaults = SettingsFile.default 17 17 save(defaults) 18 18 return defaults 19 19 } 20 20 21 - func save(_ settings: GlobalSettings) { 21 + func save(_ settings: SettingsFile) { 22 22 do { 23 23 let directory = settingsURL.deletingLastPathComponent() 24 24 try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
+9
supacode/Features/Settings/Models/SettingsFile.swift
··· 1 + nonisolated struct SettingsFile: Codable, Equatable { 2 + var global: GlobalSettings 3 + var repositories: [String: RepositorySettings] 4 + 5 + static let `default` = SettingsFile( 6 + global: .default, 7 + repositories: [:] 8 + ) 9 + }
+4 -4
supacodeTests/SettingsStorageTests.swift
··· 16 16 #expect(FileManager.default.fileExists(atPath: settingsURL.path(percentEncoded: false))) 17 17 18 18 let data = try Data(contentsOf: settingsURL) 19 - let decoded = try JSONDecoder().decode(GlobalSettings.self, from: data) 19 + let decoded = try JSONDecoder().decode(SettingsFile.self, from: data) 20 20 #expect(decoded == .default) 21 21 } 22 22 ··· 27 27 let storage = SettingsStorage(settingsURL: settingsURL) 28 28 29 29 var settings = storage.load() 30 - settings.appearanceMode = .dark 30 + settings.global.appearanceMode = .dark 31 31 storage.save(settings) 32 32 33 33 let reloaded = SettingsStorage(settingsURL: settingsURL).load() 34 - #expect(reloaded.appearanceMode == .dark) 34 + #expect(reloaded.global.appearanceMode == .dark) 35 35 } 36 36 37 37 @Test func invalidJSONResetsToDefaults() throws { ··· 47 47 #expect(settings == .default) 48 48 49 49 let data = try Data(contentsOf: settingsURL) 50 - let decoded = try JSONDecoder().decode(GlobalSettings.self, from: data) 50 + let decoded = try JSONDecoder().decode(SettingsFile.self, from: data) 51 51 #expect(decoded == .default) 52 52 } 53 53