-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathSettings.swift
More file actions
94 lines (80 loc) · 2.85 KB
/
Settings.swift
File metadata and controls
94 lines (80 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//
// Settings.swift
// CodeEditModules/Settings
//
// Created by Lukas Pistrol on 01.04.22.
//
import Foundation
import SwiftUI
import Combine
/// The Preferences View Model. Accessible via the singleton "``SettingsModel/shared``".
///
/// **Usage:**
/// ```swift
/// @StateObject
/// private var prefs: SettingsModel = .shared
/// ```
final class Settings: ObservableObject {
/// The publicly available singleton instance of ``SettingsModel``
static let shared: Settings = .init()
private var storeTask: AnyCancellable!
private init() {
self.preferences = .init()
self.preferences = loadSettings()
self.storeTask = self.$preferences.throttle(for: 2, scheduler: RunLoop.main, latest: true).sink {
try? self.savePreferences($0)
}
}
static subscript<T>(_ path: WritableKeyPath<SettingsData, T>, suite: Settings = .shared) -> T {
get {
suite.preferences[keyPath: path]
}
set {
suite.preferences[keyPath: path] = newValue
}
}
/// Published instance of the ``Settings`` model.
///
/// Changes are saved automatically.
@Published var preferences: SettingsData
/// Load and construct ``Settings`` model from
/// `~/Library/Application Support/CodeEdit/settings.json`
private func loadSettings() -> SettingsData {
if !filemanager.fileExists(atPath: settingsURL.path) {
try? filemanager.createDirectory(at: baseURL, withIntermediateDirectories: false)
return .init()
}
guard let json = try? Data(contentsOf: settingsURL),
let prefs = try? JSONDecoder().decode(SettingsData.self, from: json)
else {
return .init()
}
return prefs
}
/// Save``Settings`` model to
/// `~/Library/Application Support/CodeEdit/settings.json`
private func savePreferences(_ data: SettingsData) throws {
let data = try JSONEncoder().encode(data)
let json = try JSONSerialization.jsonObject(with: data)
let prettyJSON = try JSONSerialization.data(withJSONObject: json, options: [.prettyPrinted])
try prettyJSON.write(to: settingsURL, options: .atomic)
}
/// Default instance of the `FileManager`
private let filemanager = FileManager.default
/// The base URL of settings.
///
/// Points to `~/Library/Application Support/CodeEdit/`
internal var baseURL: URL {
filemanager
.homeDirectoryForCurrentUser
.appending(path: "Library/Application Support/CodeEdit", directoryHint: .isDirectory)
}
/// The URL of the `settings.json` settings file.
///
/// Points to `~/Library/Application Support/CodeEdit/settings.json`
private var settingsURL: URL {
baseURL
.appending(path: "settings")
.appendingPathExtension("json")
}
}