-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
319f328
commit ec74a4c
Showing
6 changed files
with
145 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,53 @@ | ||
import SwiftUI | ||
import LiveKit | ||
import WebRTC | ||
import Combine | ||
|
||
extension ObservableObject where Self.ObjectWillChangePublisher == ObservableObjectPublisher { | ||
func notify() { | ||
DispatchQueue.main.async { self.objectWillChange.send() } | ||
} | ||
} | ||
|
||
// This class contains the logic to control behavior of the whole app. | ||
final class AppContext: ObservableObject { | ||
|
||
private let store: SecureStore<SecureStoreKeys> | ||
private let store: ValueStore<Preferences> | ||
|
||
@Published var videoViewVisible: Bool { | ||
didSet { store.set(.videoViewVisible, value: videoViewVisible) } | ||
@Published var videoViewVisible: Bool = true { | ||
didSet { store.value.videoViewVisible = videoViewVisible } | ||
} | ||
|
||
@Published var showInformationOverlay: Bool { | ||
didSet { store.set(.showInformationOverlay, value: showInformationOverlay) } | ||
@Published var showInformationOverlay: Bool = false { | ||
didSet { store.value.showInformationOverlay = showInformationOverlay } | ||
} | ||
|
||
@Published var preferMetal: Bool { | ||
didSet { store.set(.preferMetal, value: preferMetal) } | ||
@Published var preferMetal: Bool = true { | ||
didSet { store.value.preferMetal = preferMetal } | ||
} | ||
|
||
@Published var videoViewMode: VideoView.Mode { | ||
didSet { store.set(.videoViewMode, value: videoViewMode) } | ||
@Published var videoViewMode: VideoView.Mode = .fit { | ||
didSet { store.value.videoViewMode = videoViewMode } | ||
} | ||
|
||
@Published var videoViewMirrored: Bool { | ||
didSet { store.set(.videoViewMirrored, value: videoViewMirrored) } | ||
@Published var videoViewMirrored: Bool = false { | ||
didSet { store.value.videoViewMirrored = videoViewMirrored } | ||
} | ||
|
||
@Published var connectionHistory: Set<ConnectionHistory> { | ||
didSet { store.set(.connectionHistory, value: connectionHistory) } | ||
@Published var connectionHistory: Set<ConnectionHistory> = [] { | ||
didSet { store.value.connectionHistory = connectionHistory } | ||
} | ||
|
||
public init(store: SecureStore<SecureStoreKeys>) { | ||
public init(store: ValueStore<Preferences>) { | ||
self.store = store | ||
self.videoViewVisible = store.get(.videoViewVisible) ?? true | ||
self.showInformationOverlay = store.get(.showInformationOverlay) ?? false | ||
self.preferMetal = store.get(.preferMetal) ?? true | ||
self.videoViewMode = store.get(.videoViewMode) ?? .fit | ||
self.videoViewMirrored = store.get(.videoViewMirrored) ?? false | ||
self.connectionHistory = store.get(.connectionHistory) ?? Set<ConnectionHistory>() | ||
|
||
store.onLoaded.then { preferences in | ||
self.videoViewVisible = preferences.videoViewVisible | ||
self.showInformationOverlay = preferences.showInformationOverlay | ||
self.preferMetal = preferences.preferMetal | ||
self.videoViewMode = preferences.videoViewMode | ||
self.videoViewMirrored = preferences.videoViewMirrored | ||
self.connectionHistory = preferences.connectionHistory | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,98 @@ | ||
import SwiftUI | ||
import KeychainAccess | ||
import Combine | ||
import LiveKit | ||
import Promises | ||
|
||
enum SecureStoreKeys: String { | ||
case url = "url" | ||
case token = "token" | ||
struct Preferences: Codable, Equatable { | ||
var url = "" | ||
var token = "" | ||
|
||
// Connect options | ||
case autoSubscribe = "autoSubscribe" | ||
case publishMode = "publishMode" | ||
var autoSubscribe = true | ||
var publishMode = false | ||
|
||
// Room options | ||
case simulcast = "simulcast" | ||
case adaptiveStream = "adaptiveStream" | ||
case dynacast = "dynacast" | ||
var simulcast = true | ||
var adaptiveStream = false | ||
var dynacast = false | ||
|
||
// Settings | ||
case videoViewVisible = "videoViewVisible" | ||
case showInformationOverlay = "showInformationOverlay" | ||
case preferMetal = "preferMetal" | ||
case videoViewMode = "videoViewMode" | ||
case videoViewMirrored = "videoViewMirrored" | ||
var videoViewVisible = true | ||
var showInformationOverlay = false | ||
var preferMetal = true | ||
var videoViewMode: VideoView.Mode = .fit | ||
var videoViewMirrored = false | ||
|
||
case connectionHistory = "connectionHistory" | ||
var connectionHistory = Set<ConnectionHistory>() | ||
} | ||
|
||
class SecureStore<K: RawRepresentable> where K.RawValue == String { | ||
let encoder = JSONEncoder() | ||
let decoder = JSONDecoder() | ||
|
||
let keychain: Keychain | ||
let encoder = JSONEncoder() | ||
let decoder = JSONDecoder() | ||
// Promise version | ||
extension Keychain { | ||
|
||
init(service: String) { | ||
self.keychain = Keychain(service: service) | ||
@discardableResult | ||
func get<T: Decodable>(_ key: String) -> Promise<T?> { | ||
Promise(on: .global()) { () -> T? in | ||
guard let data = try self.getData(key) else { return nil } | ||
return try decoder.decode(T.self, from: data) | ||
} | ||
} | ||
|
||
func get<T: Decodable>(_ key: K) -> T? { | ||
guard let data = try? keychain.getData(key.rawValue) else { return nil } | ||
return try? decoder.decode(T.self, from: data) | ||
@discardableResult | ||
func set<T: Encodable>(_ key: String, value: T) -> Promise<Void> { | ||
Promise(on: .global()) { () -> Void in | ||
let data = try encoder.encode(value) | ||
try self.set(data, key: key) | ||
} | ||
} | ||
} | ||
|
||
class ValueStore<T: Codable & Equatable>: ObservableObject { | ||
|
||
private let store: Keychain | ||
private let key: String | ||
private let message = "" | ||
private weak var timer: Timer? | ||
|
||
public let onLoaded = Promise<T>.pending() | ||
|
||
public var value: T { | ||
didSet { | ||
guard oldValue != value else { return } | ||
lazySync() | ||
} | ||
} | ||
|
||
private var storeWithOptions: Keychain { | ||
store.accessibility(.whenUnlocked) | ||
} | ||
|
||
public init(store: Keychain, key: String, `default`: T) { | ||
self.store = store | ||
self.key = key | ||
self.value = `default` | ||
|
||
storeWithOptions.get(key).then { (result: T?) -> Void in | ||
self.value = result ?? self.value | ||
self.onLoaded.fulfill(self.value) | ||
} | ||
} | ||
|
||
deinit { | ||
timer?.invalidate() | ||
} | ||
|
||
public func lazySync() { | ||
timer?.invalidate() | ||
timer = Timer.scheduledTimer(withTimeInterval: 1, | ||
repeats: false, | ||
block: { _ in self.sync() }) | ||
} | ||
|
||
func set<T: Encodable>(_ key: K, value: T) { | ||
guard let data = try? encoder.encode(value) else { return } | ||
try? keychain.set(data, key: key.rawValue) | ||
public func sync() { | ||
storeWithOptions.set(key, value: value) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters