mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 16:24:11 +00:00
Merge the UserDefaultsStorage helpers into UserDefaultsProtocol.
This commit is contained in:
@@ -9,8 +9,8 @@ import SwiftSyntax
|
||||
import SwiftSyntaxMacros
|
||||
|
||||
/// Implements `@UserPreference`. The generated property reads and writes through the enclosing
|
||||
/// type's `store` (a `UserDefaultsProtocol`), wrapped in `UserDefaultsStorage` for the
|
||||
/// encode/decode handling, and publishes changes via a generated per-preference subject.
|
||||
/// type's `store` (a `UserDefaultsProtocol`), and publishes changes via a generated per-preference
|
||||
/// subject.
|
||||
///
|
||||
/// A `volatile` preference instead reads and writes through a generated in-memory store, so its
|
||||
/// value is never persisted and resets on each launch.
|
||||
@@ -33,7 +33,7 @@ public enum UserPreferenceMacro {
|
||||
let name: String
|
||||
let type: TypeSyntax
|
||||
let key: ExprSyntax
|
||||
let defaultValue: ExprSyntax
|
||||
let defaultValue: ExprSyntax?
|
||||
let isVolatile: Bool
|
||||
|
||||
var subjectName: TokenSyntax {
|
||||
@@ -79,7 +79,7 @@ public enum UserPreferenceMacro {
|
||||
return Preference(name: name,
|
||||
type: type,
|
||||
key: key ?? "\(literal: name)",
|
||||
defaultValue: defaultValue ?? "nil",
|
||||
defaultValue: defaultValue,
|
||||
isVolatile: isVolatile)
|
||||
}
|
||||
}
|
||||
@@ -106,30 +106,34 @@ extension UserPreferenceMacro: AccessorMacro {
|
||||
]
|
||||
}
|
||||
|
||||
let type = preference.type
|
||||
let key = preference.key
|
||||
|
||||
// Parenthesise a default that's a binary expression: `??` binds tighter than e.g. `==`,
|
||||
// so `storage[key] ?? a == b` would otherwise parse as `(storage[key] ?? a) == b`.
|
||||
let isBinaryExpression = preference.defaultValue.is(SequenceExprSyntax.self) || preference.defaultValue.is(InfixOperatorExprSyntax.self)
|
||||
let defaultValue: ExprSyntax = isBinaryExpression ? "(\(preference.defaultValue))" : preference.defaultValue
|
||||
|
||||
return [
|
||||
"""
|
||||
get {
|
||||
let storage = UserDefaultsStorage<\(type)>(userDefaults: store)
|
||||
return storage[\(key)] ?? \(defaultValue)
|
||||
\(readExpression(for: preference))
|
||||
}
|
||||
""",
|
||||
"""
|
||||
set {
|
||||
let storage = UserDefaultsStorage<\(type)>(userDefaults: store)
|
||||
storage[\(key)] = newValue
|
||||
store[\(key)] = newValue
|
||||
\(preference.subjectName).send(newValue)
|
||||
}
|
||||
"""
|
||||
]
|
||||
}
|
||||
|
||||
/// The getter expression: `store[key]`, with the default appended when there is one. A default
|
||||
/// that's a binary expression is parenthesised, as `??` binds tighter than e.g. `==`.
|
||||
private static func readExpression(for preference: Preference) -> ExprSyntax {
|
||||
guard let defaultValue = preference.defaultValue else {
|
||||
return "store[\(preference.key)]"
|
||||
}
|
||||
|
||||
let isBinaryExpression = defaultValue.is(SequenceExprSyntax.self) || defaultValue.is(InfixOperatorExprSyntax.self)
|
||||
let wrappedDefault: ExprSyntax = isBinaryExpression ? "(\(defaultValue))" : defaultValue
|
||||
return "store[\(preference.key)] ?? \(wrappedDefault)"
|
||||
}
|
||||
}
|
||||
|
||||
extension UserPreferenceMacro: PeerMacro {
|
||||
@@ -143,7 +147,7 @@ extension UserPreferenceMacro: PeerMacro {
|
||||
var peers: [DeclSyntax] = []
|
||||
|
||||
if preference.isVolatile {
|
||||
peers.append("private var \(preference.volatileValueName): \(type) = \(preference.defaultValue)")
|
||||
peers.append("private var \(preference.volatileValueName): \(type) = \(preference.defaultValue ?? "nil")")
|
||||
}
|
||||
|
||||
peers.append("private let \(preference.subjectName) = PassthroughSubject<\(type), Never>()")
|
||||
@@ -163,14 +167,13 @@ extension UserPreferenceMacro: PeerMacro {
|
||||
if preference.isVolatile {
|
||||
"""
|
||||
func \(preference.resetMethodName)() {
|
||||
\(preference.volatileValueName) = \(preference.defaultValue)
|
||||
\(preference.volatileValueName) = \(preference.defaultValue ?? "nil")
|
||||
}
|
||||
"""
|
||||
} else {
|
||||
"""
|
||||
func \(preference.resetMethodName)() {
|
||||
let storage = UserDefaultsStorage<\(preference.type)>(userDefaults: store)
|
||||
storage[\(preference.key)] = nil
|
||||
store.removeObject(forKey: \(preference.key))
|
||||
}
|
||||
"""
|
||||
}
|
||||
|
||||
@@ -21,12 +21,10 @@ final class UserPreferenceMacroTests: XCTestCase {
|
||||
"""
|
||||
var hasSeenNewSoundBanner: Bool {
|
||||
get {
|
||||
let storage = UserDefaultsStorage<Bool>(userDefaults: store)
|
||||
return storage["hasSeenNewSoundBanner"] ?? true
|
||||
store["hasSeenNewSoundBanner"] ?? true
|
||||
}
|
||||
set {
|
||||
let storage = UserDefaultsStorage<Bool>(userDefaults: store)
|
||||
storage["hasSeenNewSoundBanner"] = newValue
|
||||
store["hasSeenNewSoundBanner"] = newValue
|
||||
_hasSeenNewSoundBannerSubject.send(newValue)
|
||||
}
|
||||
}
|
||||
@@ -38,8 +36,7 @@ final class UserPreferenceMacroTests: XCTestCase {
|
||||
}
|
||||
|
||||
func resetHasSeenNewSoundBanner() {
|
||||
let storage = UserDefaultsStorage<Bool>(userDefaults: store)
|
||||
storage["hasSeenNewSoundBanner"] = nil
|
||||
store.removeObject(forKey: "hasSeenNewSoundBanner")
|
||||
}
|
||||
""",
|
||||
macros: macros)
|
||||
@@ -54,12 +51,10 @@ final class UserPreferenceMacroTests: XCTestCase {
|
||||
"""
|
||||
var liveLocationSharingSessionsByRoomID: [String: LiveLocationSession] {
|
||||
get {
|
||||
let storage = UserDefaultsStorage<[String: LiveLocationSession]>(userDefaults: store)
|
||||
return storage["liveLocationSharingTimeoutDatesByRoomID"] ?? [String: LiveLocationSession]()
|
||||
store["liveLocationSharingTimeoutDatesByRoomID"] ?? [String: LiveLocationSession]()
|
||||
}
|
||||
set {
|
||||
let storage = UserDefaultsStorage<[String: LiveLocationSession]>(userDefaults: store)
|
||||
storage["liveLocationSharingTimeoutDatesByRoomID"] = newValue
|
||||
store["liveLocationSharingTimeoutDatesByRoomID"] = newValue
|
||||
_liveLocationSharingSessionsByRoomIDSubject.send(newValue)
|
||||
}
|
||||
}
|
||||
@@ -71,8 +66,7 @@ final class UserPreferenceMacroTests: XCTestCase {
|
||||
}
|
||||
|
||||
func resetLiveLocationSharingSessionsByRoomID() {
|
||||
let storage = UserDefaultsStorage<[String: LiveLocationSession]>(userDefaults: store)
|
||||
storage["liveLocationSharingTimeoutDatesByRoomID"] = nil
|
||||
store.removeObject(forKey: "liveLocationSharingTimeoutDatesByRoomID")
|
||||
}
|
||||
""",
|
||||
macros: macros)
|
||||
@@ -87,12 +81,10 @@ final class UserPreferenceMacroTests: XCTestCase {
|
||||
"""
|
||||
var pusherProfileTag: String? {
|
||||
get {
|
||||
let storage = UserDefaultsStorage<String?>(userDefaults: store)
|
||||
return storage["pusherProfileTag"] ?? nil
|
||||
store["pusherProfileTag"]
|
||||
}
|
||||
set {
|
||||
let storage = UserDefaultsStorage<String?>(userDefaults: store)
|
||||
storage["pusherProfileTag"] = newValue
|
||||
store["pusherProfileTag"] = newValue
|
||||
_pusherProfileTagSubject.send(newValue)
|
||||
}
|
||||
}
|
||||
@@ -104,8 +96,7 @@ final class UserPreferenceMacroTests: XCTestCase {
|
||||
}
|
||||
|
||||
func resetPusherProfileTag() {
|
||||
let storage = UserDefaultsStorage<String?>(userDefaults: store)
|
||||
storage["pusherProfileTag"] = nil
|
||||
store.removeObject(forKey: "pusherProfileTag")
|
||||
}
|
||||
""",
|
||||
macros: macros)
|
||||
@@ -120,12 +111,10 @@ final class UserPreferenceMacroTests: XCTestCase {
|
||||
"""
|
||||
var viewSourceEnabled: Bool {
|
||||
get {
|
||||
let storage = UserDefaultsStorage<Bool>(userDefaults: store)
|
||||
return storage["viewSourceEnabled"] ?? (Self.appBuildType == .debug)
|
||||
store["viewSourceEnabled"] ?? (Self.appBuildType == .debug)
|
||||
}
|
||||
set {
|
||||
let storage = UserDefaultsStorage<Bool>(userDefaults: store)
|
||||
storage["viewSourceEnabled"] = newValue
|
||||
store["viewSourceEnabled"] = newValue
|
||||
_viewSourceEnabledSubject.send(newValue)
|
||||
}
|
||||
}
|
||||
@@ -137,8 +126,7 @@ final class UserPreferenceMacroTests: XCTestCase {
|
||||
}
|
||||
|
||||
func resetViewSourceEnabled() {
|
||||
let storage = UserDefaultsStorage<Bool>(userDefaults: store)
|
||||
storage["viewSourceEnabled"] = nil
|
||||
store.removeObject(forKey: "viewSourceEnabled")
|
||||
}
|
||||
""",
|
||||
macros: macros)
|
||||
|
||||
Reference in New Issue
Block a user