-
Notifications
You must be signed in to change notification settings - Fork 150
/
Copy pathPreferences.swift
361 lines (306 loc) · 12.8 KB
/
Preferences.swift
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
//
// Preferences.swift
// OpenGpxTracker
//
// Created by merlos on 04/05/2019.
// Copyright © 2019 TransitBox. All rights reserved.
//
// Shared file: this file is also included in the OpenGpxTracker-Watch Extension target.
import Foundation
import CoreLocation
/// Key on Defaults for the Tile Server integer.
let kDefaultsKeyTileServerInt: String = "TileServerInt"
/// Key on Defaults for the use cache setting.
let kDefaultsKeyUseCache: String = "UseCache"
/// Key on Defaults for the use of imperial units.
let kDefaultsKeyUseImperial: String = "UseImperial"
/// Key on Defaults for the current selected activity type.
let kDefaultsKeyActivityType: String = "ActivityType"
/// Key on Defaults for the current date format..
let kDefaultsKeyDateFormat: String = "DateFormat"
/// Key on Defaults for the current input date format
let kDefaultsKeyDateFormatInput: String = "DateFormatPresetInput"
/// Key on Defaults for the current selected date format preset cell index.
let kDefaultsKeyDateFormatPreset: String = "DateFormatPreset"
/// Key on Defaults for the current selected date format, to use UTC time or not..
let kDefaultsKeyDateFormatUseUTC: String = "DateFormatPresetUseUTC"
/// Key on Defaults for the current selected date format, to use local Locale or `en_US_POSIX`
let kDefaultsKeyDateFormatUseEN: String = "DateFormatPresetUseEN"
/// Key on Defaults for the folder where GPX files are store, `nil` means default folder
let kDefaultsKeyGPXFilesFolder: String = "GPXFilesFolder"
let kDefaultsKeyKeepScreenAlwaysOn: String = "KeepScreenAlwaysOn"
/// A class to handle app preferences in one single place.
/// When the app starts for the first time the following preferences are set:
///
/// * useCache = true
/// * useImperial = whatever is set by current locale (NSLocale.usesMetricUnits) or false
/// * tileServer = .apple
///
class Preferences: NSObject {
/// Shared preferences singleton.
/// Usage:
/// var preferences: Preferences = Preferences.shared
/// print (preferences.useCache)
///
static let shared = Preferences()
/// In memory value of the preference.
private var _useImperial: Bool = false
/// In memory value of the preference.
private var _useCache: Bool = true
/// In memory value of the preference.
private var _tileServer: GPXTileServer = .apple
/// In memory value of the preference.
private var _activityType: CLActivityType = .other
///
private var _dateFormat = "dd-MMM-yyyy-HHmm"
///
private var _dateFormatInput = "{dd}-{MMM}-{yyyy}-{HH}{mm}"
///
private var _dateFormatPreset: Int = 0
///
private var _dateFormatUseUTC: Bool = false
///
private var _dateFormatUseEN: Bool = false
///
private var _gpxFilesFolderBookmark: Data?
///
private var _keepScreenAlwaysOn: Bool = false
/// UserDefaults.standard shortcut
private let defaults = UserDefaults.standard
/// Loads preferences from UserDefaults.
private override init() {
// Loads preferences into private vars
// Use Imperial units
if let useImperialDefaults = defaults.object(forKey: kDefaultsKeyUseImperial) as? Bool {
print("** Preferences:: loaded from defaults. useImperial: \(useImperialDefaults)")
_useImperial = useImperialDefaults
} else { // get from locale config
let locale = NSLocale.current
_useImperial = !locale.usesMetricSystem
let langCode = locale.languageCode ?? "unknown"
let useMetric = locale.usesMetricSystem
print("** Preferences:: NO defaults for useImperial. Using locale: \(langCode) useImperial: \(_useImperial) usesMetric:\(useMetric)")
}
// Use cache
if let useCacheFromDefaults = defaults.object(forKey: kDefaultsKeyUseCache) as? Bool {
_useCache = useCacheFromDefaults
print("Preferences:: loaded preference from defaults useCache= \(useCacheFromDefaults)")
}
// Map Tile server
if var tileServerInt = defaults.object(forKey: kDefaultsKeyTileServerInt) as? Int {
// Check in case it was a tile server that is no longer supported
tileServerInt = tileServerInt >= GPXTileServer.count ? GPXTileServer.apple.rawValue : tileServerInt
_tileServer = GPXTileServer(rawValue: tileServerInt)!
print("** Preferences:: loaded preference from defaults tileServerInt \(tileServerInt)")
}
// load previous activity type
if let activityTypeInt = defaults.object(forKey: kDefaultsKeyActivityType) as? Int {
_activityType = CLActivityType(rawValue: activityTypeInt)!
print("** Preferences:: loaded preference from defaults activityTypeInt \(activityTypeInt)")
}
// load previous date format
if let dateFormatStr = defaults.object(forKey: kDefaultsKeyDateFormat) as? String {
_dateFormat = dateFormatStr
print("** Preferences:: loaded preference from defaults dateFormatStr \(dateFormatStr)")
}
// load previous date format (usr input)
if let dateFormatStrIn = defaults.object(forKey: kDefaultsKeyDateFormatInput) as? String {
_dateFormatInput = dateFormatStrIn
print("** Preferences:: loaded preference from defaults dateFormatStrIn \(dateFormatStrIn)")
}
// load previous date format preset
if let dateFormatPresetInt = defaults.object(forKey: kDefaultsKeyDateFormatPreset) as? Int {
_dateFormatPreset = dateFormatPresetInt
print("** Preferences:: loaded preference from defaults dateFormatPresetInt \(dateFormatPresetInt)")
}
// load previous date format, to use UTC time instead of local time
if let dateFormatUTCBool = defaults.object(forKey: kDefaultsKeyDateFormatUseUTC) as? Bool {
_dateFormatUseUTC = dateFormatUTCBool
print("** Preferences:: loaded preference from defaults dateFormatPresetUTCBool \(dateFormatUTCBool)")
}
// load previous date format, to use EN locale instead of local locale
if let dateFormatENBool = defaults.object(forKey: kDefaultsKeyDateFormatUseEN) as? Bool {
_dateFormatUseEN = dateFormatENBool
print("** Preferences:: loaded preference from defaults dateFormatPresetENBool \(dateFormatENBool)")
}
// load previous gpx files folder bookmark
if let gpxFilesFolderBookmark = defaults.object(forKey: kDefaultsKeyGPXFilesFolder) as? Data {
_gpxFilesFolderBookmark = gpxFilesFolderBookmark
print("** Preferences:: loaded preference from defaults gpxFilesFolderBookmark \(gpxFilesFolderBookmark)")
}
// load previous date format, to use EN locale instead of local locale
if let keepScreenAlwaysOnBool = defaults.object(forKey: kDefaultsKeyKeepScreenAlwaysOn) as? Bool {
_keepScreenAlwaysOn = keepScreenAlwaysOnBool
print("** Preferences:: loaded preference from defaults keepScreenAlwaysOn \(keepScreenAlwaysOnBool)")
}
}
/// If true, user prefers to display imperial units (miles, feets). Otherwise metric units
/// are displayed.
var useImperial: Bool {
get {
return _useImperial
}
set {
_useImperial = newValue
defaults.set(newValue, forKey: kDefaultsKeyUseImperial)
}
}
/// Gets and sets if user wants to use offline cache.
var useCache: Bool {
get {
return _useCache
}
set {
_useCache = newValue
// Set defaults
defaults.set(newValue, forKey: kDefaultsKeyUseCache)
}
}
/// Gets and sets user preference of the map tile server.
var tileServer: GPXTileServer {
get {
return _tileServer
}
set {
_tileServer = newValue
defaults.set(newValue.rawValue, forKey: kDefaultsKeyTileServerInt)
}
}
/// Get and sets user preference of the map tile server as Int.
var tileServerInt: Int {
get {
return _tileServer.rawValue
}
set {
_tileServer = GPXTileServer(rawValue: newValue)!
defaults.set(newValue, forKey: kDefaultsKeyTileServerInt)
}
}
/// Gets and sets the type of activity preference
var locationActivityType: CLActivityType {
get {
return _activityType
}
set {
_activityType = newValue
defaults.set(newValue.rawValue, forKey: kDefaultsKeyActivityType)
}
}
/// Gets and sets the activity type as its int value
var locationActivityTypeInt: Int {
get {
return _activityType.rawValue
}
set {
_activityType = CLActivityType(rawValue: newValue)!
defaults.set(newValue, forKey: kDefaultsKeyActivityType)
}
}
/// Gets and sets the date formatter friendly date format
var dateFormat: String {
get {
return _dateFormat
}
set {
_dateFormat = newValue
defaults.set(newValue, forKey: kDefaultsKeyDateFormat)
}
}
/// Gets and sets the user friendly input date format
var dateFormatInput: String {
get {
return _dateFormatInput
}
set {
_dateFormatInput = newValue
defaults.set(newValue, forKey: kDefaultsKeyDateFormatInput)
}
}
/// Get and sets user preference of date format presets. (-1 if custom)
var dateFormatPreset: Int {
get {
return _dateFormatPreset
}
set {
_dateFormatPreset = newValue
defaults.set(newValue, forKey: kDefaultsKeyDateFormatPreset)
}
}
/// Get date format preset name
var dateFormatPresetName: String {
let presets = ["Defaults", "ISO8601 (UTC)", "ISO8601 (UTC offset)", "Day, Date at time (12 hr)", "Day, Date at time (24 hr)"]
return _dateFormatPreset < presets.count ? presets[_dateFormatPreset] : "???"
}
/// Get and sets whether to use UTC for date format
var dateFormatUseUTC: Bool {
get {
return _dateFormatUseUTC
}
set {
_dateFormatUseUTC = newValue
defaults.set(newValue, forKey: kDefaultsKeyDateFormatUseUTC)
}
}
/// Get and sets whether to use local locale or EN
var dateFormatUseEN: Bool {
get {
return _dateFormatUseEN
}
set {
_dateFormatUseEN = newValue
defaults.set(newValue, forKey: kDefaultsKeyDateFormatUseEN)
}
}
/// Get and sets whether to set the screen always On or not
var keepScreenAlwaysOn: Bool {
get {
return _keepScreenAlwaysOn
}
set {
_keepScreenAlwaysOn = newValue
defaults.set(newValue, forKey: kDefaultsKeyKeepScreenAlwaysOn)
print("** Preferences:: setting keepScreenAlwaysOn: \(newValue)")
}
}
var gpxFilesFolderURL: URL? {
get {
guard let bookmarkData = self._gpxFilesFolderBookmark else {
return nil
}
do {
var isStale: Bool = false
let url = try URL(resolvingBookmarkData: bookmarkData, bookmarkDataIsStale: &isStale)
if isStale {
_ = url.startAccessingSecurityScopedResource()
defer {
url.stopAccessingSecurityScopedResource()
}
let newBookmark = try url.bookmarkData()
_gpxFilesFolderBookmark = newBookmark
defaults.set(newBookmark, forKey: kDefaultsKeyGPXFilesFolder)
}
return url
} catch {
print("** Preferences:: failed to retrieve url from bookmark data: \(String(describing: error))")
return nil
}
}
set {
guard let newValue else {
defaults.removeObject(forKey: kDefaultsKeyGPXFilesFolder)
return
}
do {
_ = newValue.startAccessingSecurityScopedResource()
defer {
newValue.stopAccessingSecurityScopedResource()
}
let newBookmark = try newValue.bookmarkData()
_gpxFilesFolderBookmark = newBookmark
defaults.set(newBookmark, forKey: kDefaultsKeyGPXFilesFolder)
} catch {
print("** Preferences:: failed to generate bookmark data for url: \(String(describing: error))")
}
}
}
}