/* * Copyright 2024 LiveKit * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import Combine import KeychainAccess import LiveKit import SwiftUI struct Preferences: Codable, Equatable { // General var applicationServerUrl = "" // Room var livekitUrl = "" var name = "" var token = "" var localParticipantName = "" } let encoder = JSONEncoder() let decoder = JSONDecoder() class ValueStore: ObservableObject { private let store: Keychain private let key: String private let message = "" private weak var timer: Timer? public var value: T { didSet { guard oldValue != value else { return } lazySync() } } private var storeWithOptions: Keychain { store .accessibility(.whenUnlocked) .synchronizable(true) } public init(store: Keychain, key: String, default: T) { self.store = store self.key = key value = `default` if let data = try? storeWithOptions.getData(key), let result = try? decoder.decode(T.self, from: data) { value = result } } deinit { timer?.invalidate() } public func lazySync() { timer?.invalidate() timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false, block: { _ in self.sync() }) } public func sync() { do { let data = try encoder.encode(value) try storeWithOptions.set(data, key: key) } catch { print("Failed to write in Keychain, error: \(error)") } } }