Skip to content

Commit

Permalink
store token in keychain
Browse files Browse the repository at this point in the history
  • Loading branch information
hiroshihorie committed Feb 10, 2022
1 parent f40b4f1 commit c727651
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{
"object": {
"pins": [
{
"package": "KeychainAccess",
"repositoryURL": "https://github.com/kishikawakatsumi/KeychainAccess.git",
"state": {
"branch": null,
"revision": "84e546727d66f1adc5439debad16270d0fdd04e7",
"version": "4.2.2"
}
},
{
"package": "Promises",
"repositoryURL": "https://github.com/google/promises.git",
Expand Down
33 changes: 32 additions & 1 deletion LiveKitExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
6866E93E27A1974B008AD2DF /* LiveKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6866E93D27A1974B008AD2DF /* LiveKit */; };
6867533B27A65652003707B9 /* AppContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6867533A27A65652003707B9 /* AppContext.swift */; };
6867533C27A65652003707B9 /* AppContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6867533A27A65652003707B9 /* AppContext.swift */; };
68816CC127B4D6BC00E24622 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 68816CC027B4D6BC00E24622 /* KeychainAccess */; };
68816CC327B4D94200E24622 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 68816CC227B4D94200E24622 /* KeychainAccess */; };
68816CC527B4DCD500E24622 /* SecureStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68816CC427B4DCD500E24622 /* SecureStore.swift */; };
68816CC627B4DCD500E24622 /* SecureStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68816CC427B4DCD500E24622 /* SecureStore.swift */; };
6884B77C2750507400732D47 /* ScreenShareSourcePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6884B77B2750507400732D47 /* ScreenShareSourcePickerView.swift */; };
6884B77D2750507400732D47 /* ScreenShareSourcePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6884B77B2750507400732D47 /* ScreenShareSourcePickerView.swift */; };
68B3854C271E780700711D5F /* LiveKitExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68B3853C271E780600711D5F /* LiveKitExample.swift */; };
Expand Down Expand Up @@ -83,6 +87,7 @@
6865EA2527513B4500FFAFC3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6865EA2D27513B6D00FFAFC3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6867533A27A65652003707B9 /* AppContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppContext.swift; sourceTree = "<group>"; };
68816CC427B4DCD500E24622 /* SecureStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureStore.swift; sourceTree = "<group>"; };
6884B77B2750507400732D47 /* ScreenShareSourcePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenShareSourcePickerView.swift; sourceTree = "<group>"; };
68B3853C271E780600711D5F /* LiveKitExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveKitExample.swift; sourceTree = "<group>"; };
68B3853E271E780700711D5F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand All @@ -108,6 +113,7 @@
files = (
680FE2F227A8EF7700B6F6DB /* SFSafeSymbols in Frameworks */,
6866E93C27A196C4008AD2DF /* LiveKit in Frameworks */,
68816CC127B4D6BC00E24622 /* KeychainAccess in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -117,6 +123,7 @@
files = (
680FE2F427A8EFF700B6F6DB /* SFSafeSymbols in Frameworks */,
6866E93E27A1974B008AD2DF /* LiveKit in Frameworks */,
68816CC327B4D94200E24622 /* KeychainAccess in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -137,6 +144,7 @@
children = (
683720D127A06404007DA986 /* ConnectionHistory.swift */,
6847616327B44A1A001611BE /* Bundle.swift */,
68816CC427B4DCD500E24622 /* SecureStore.swift */,
);
path = Support;
sourceTree = "<group>";
Expand Down Expand Up @@ -266,6 +274,7 @@
packageProductDependencies = (
6866E93B27A196C4008AD2DF /* LiveKit */,
680FE2F127A8EF7700B6F6DB /* SFSafeSymbols */,
68816CC027B4D6BC00E24622 /* KeychainAccess */,
);
productName = "Multiplatform-SwiftUI (iOS)";
productReference = 68B38543271E780700711D5F /* LiveKitExample.app */;
Expand All @@ -287,6 +296,7 @@
packageProductDependencies = (
6866E93D27A1974B008AD2DF /* LiveKit */,
680FE2F327A8EFF700B6F6DB /* SFSafeSymbols */,
68816CC227B4D94200E24622 /* KeychainAccess */,
);
productName = "Multiplatform-SwiftUI (macOS)";
productReference = 68B38549271E780700711D5F /* LiveKitExample.app */;
Expand Down Expand Up @@ -326,6 +336,7 @@
685271E727407BBC006B4D6A /* XCRemoteSwiftPackageReference "swift-protobuf" */,
6866E93A27A196C4008AD2DF /* XCRemoteSwiftPackageReference "client-sdk-swift" */,
680FE2F027A8EF7700B6F6DB /* XCRemoteSwiftPackageReference "SFSafeSymbols" */,
68816CBF27B4D6BC00E24622 /* XCRemoteSwiftPackageReference "KeychainAccess" */,
);
productRefGroup = 68B38544271E780700711D5F /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -383,6 +394,7 @@
683720D227A06404007DA986 /* ConnectionHistory.swift in Sources */,
681E3F43271FC7AD007BB547 /* RoomView.swift in Sources */,
6816B1B0272D9198005ADB85 /* ParticipantView.swift in Sources */,
68816CC527B4DCD500E24622 /* SecureStore.swift in Sources */,
68B3854C271E780700711D5F /* LiveKitExample.swift in Sources */,
681E3F3F271FC795007BB547 /* Custom.swift in Sources */,
6847616427B44A1A001611BE /* Bundle.swift in Sources */,
Expand All @@ -401,6 +413,7 @@
683720D327A06404007DA986 /* ConnectionHistory.swift in Sources */,
681E3F44271FC7AD007BB547 /* RoomView.swift in Sources */,
6816B1B1272D9198005ADB85 /* ParticipantView.swift in Sources */,
68816CC627B4DCD500E24622 /* SecureStore.swift in Sources */,
68B3854D271E780700711D5F /* LiveKitExample.swift in Sources */,
681E3F40271FC795007BB547 /* Custom.swift in Sources */,
6847616527B44A1A001611BE /* Bundle.swift in Sources */,
Expand Down Expand Up @@ -691,7 +704,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = MacAppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
CODE_SIGN_ENTITLEMENTS = "LiveKitExample (macOS)Release.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
Expand Down Expand Up @@ -782,6 +795,14 @@
version = 0.9.6;
};
};
68816CBF27B4D6BC00E24622 /* XCRemoteSwiftPackageReference "KeychainAccess" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.2.2;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand All @@ -805,6 +826,16 @@
package = 6866E93A27A196C4008AD2DF /* XCRemoteSwiftPackageReference "client-sdk-swift" */;
productName = LiveKit;
};
68816CC027B4D6BC00E24622 /* KeychainAccess */ = {
isa = XCSwiftPackageProductDependency;
package = 68816CBF27B4D6BC00E24622 /* XCRemoteSwiftPackageReference "KeychainAccess" */;
productName = KeychainAccess;
};
68816CC227B4D94200E24622 /* KeychainAccess */ = {
isa = XCSwiftPackageProductDependency;
package = 68816CBF27B4D6BC00E24622 /* XCRemoteSwiftPackageReference "KeychainAccess" */;
productName = KeychainAccess;
};
9E7835E42751A6D900559DEC /* LiveKit */ = {
isa = XCSwiftPackageProductDependency;
productName = LiveKit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
"version": "0.9.6"
}
},
{
"package": "KeychainAccess",
"repositoryURL": "https://github.com/kishikawakatsumi/KeychainAccess.git",
"state": {
"branch": null,
"revision": "84e546727d66f1adc5439debad16270d0fdd04e7",
"version": "4.2.2"
}
},
{
"package": "Promises",
"repositoryURL": "https://github.com/google/promises.git",
Expand Down
5 changes: 1 addition & 4 deletions Shared/ConnectView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,13 @@ struct ConnectView: View {
LKTextField(title: "Token", text: $roomCtx.token, type: .ascii)

HStack {

Menu {

Toggle(isOn: $roomCtx.autoSubscribe) {
Text("Auto-Subscribe")
}
Toggle(isOn: $roomCtx.publish) {
Text("Publish only mode")
}

} label: {
Image(systemSymbol: .boltFill)
.renderingMode(.original)
Expand Down Expand Up @@ -87,7 +84,7 @@ struct ConnectView: View {

if !appCtx.connectionHistory.isEmpty {
Menu {
ForEach(appCtx.connectionHistory.view) { entry in
ForEach(appCtx.connectionHistory.sortedByUpdated) { entry in
Button {
roomCtx.connect(entry: entry).then { room in
appCtx.connectionHistory.update(room: room)
Expand Down
36 changes: 31 additions & 5 deletions Shared/Controllers/AppContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,35 @@ import WebRTC

// This class contains the logic to control behavior of the whole app.
final class AppContext: ObservableObject {
@AppStorage("connectionHistory") var connectionHistory = ConnectionHistory()
@AppStorage("videoViewVisible") var videoViewVisible: Bool = true
@AppStorage("showInformationOverlay") var showInformationOverlay: Bool = false
@AppStorage("preferMetal") var preferMetal: Bool = true
@AppStorage("videoViewMode") var videoViewMode: VideoView.Mode = .fill

private let store: SecureStore<SecureStoreKeys>

@Published var videoViewVisible: Bool {
didSet { store.set(.videoViewVisible, value: videoViewVisible) }
}

@Published var showInformationOverlay: Bool {
didSet { store.set(.showInformationOverlay, value: showInformationOverlay) }
}

@Published var preferMetal: Bool {
didSet { store.set(.preferMetal, value: preferMetal) }
}

@Published var videoViewMode: VideoView.Mode {
didSet { store.set(.videoViewMode, value: videoViewMode) }
}

@Published var connectionHistory: Set<ConnectionHistory> {
didSet { store.set(.connectionHistory, value: connectionHistory) }
}

public init(store: SecureStore<SecureStoreKeys>) {
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.connectionHistory = store.get(.connectionHistory) ?? []
}
}
47 changes: 38 additions & 9 deletions Shared/Controllers/RoomContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import Promises

// This class contains the logic to control behavior of the whole app.
final class RoomContext: ObservableObject {

private let store: SecureStore<SecureStoreKeys>

// Used to show connection error dialog
// private var didClose: Bool = false
@Published var shouldShowError: Bool = false
Expand All @@ -15,23 +18,49 @@ final class RoomContext: ObservableObject {
room.room.connectionState
}

@AppStorage("url") var url: String = ""
@AppStorage("token") var token: String = ""
@Published var url: String {
didSet { store.set(.url, value: url) }
}

@Published var token: String {
didSet { store.set(.token, value: token) }
}

// RoomOptions
@AppStorage("simulcast") var simulcast: Bool = true
@AppStorage("adaptiveStream") var adaptiveStream: Bool = false
@AppStorage("dynacast") var dynacast: Bool = false
@Published var simulcast: Bool {
didSet { store.set(.simulcast, value: simulcast) }
}

@Published var adaptiveStream: Bool {
didSet { store.set(.adaptiveStream, value: adaptiveStream) }
}

@Published var dynacast: Bool {
didSet { store.set(.dynacast, value: dynacast) }
}

// ConnectOptions
@AppStorage("autoSubscribe") var autoSubscribe: Bool = true
@AppStorage("publish") var publish: Bool = false
@Published var autoSubscribe: Bool {
didSet { store.set(.autoSubscribe, value: autoSubscribe) }
}

@Published var publish: Bool {
didSet { store.set(.publishMode, value: publish) }
}

public init() {
public init(store: SecureStore<SecureStoreKeys>) {
self.store = store
self.url = store.get(.url) ?? ""
self.token = store.get(.token) ?? ""
self.simulcast = store.get(.simulcast) ?? true
self.adaptiveStream = store.get(.adaptiveStream) ?? false
self.dynacast = store.get(.dynacast) ?? false
self.autoSubscribe = store.get(.autoSubscribe) ?? true
self.publish = store.get(.publishMode) ?? false
room.room.add(delegate: self)
}

func connect(entry: ConnectionHistoryEntry? = nil) -> Promise<Room> {
func connect(entry: ConnectionHistory? = nil) -> Promise<Room> {

if let entry = entry {
url = entry.url
Expand Down
6 changes: 4 additions & 2 deletions Shared/LiveKitExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import SwiftUI
import Logging
import LiveKit

let store = SecureStore<SecureStoreKeys>()

struct RoomContextView: View {

@StateObject var roomCtx = RoomContext()
@StateObject var roomCtx = RoomContext(store: store)

var shouldShowRoomView: Bool {
roomCtx.connectionState.isConnected || roomCtx.connectionState.isReconnecting
Expand Down Expand Up @@ -75,7 +77,7 @@ extension Decimal {
@main
struct LiveKitExample: App {

@StateObject var appCtx = AppContext()
@StateObject var appCtx = AppContext(store: store)

func nearestSafeScale(for target: Int, scale: Double) -> Decimal {

Expand Down
36 changes: 10 additions & 26 deletions Shared/Support/ConnectionHistory.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import SwiftUI
import LiveKit

typealias ConnectionHistory = Set<ConnectionHistoryEntry>

struct ConnectionHistoryEntry: Codable {
struct ConnectionHistory: Codable {

let updated: Date
let url: String
Expand All @@ -15,55 +13,41 @@ struct ConnectionHistoryEntry: Codable {
let participantName: String?
}

extension ConnectionHistoryEntry: Identifiable {
extension ConnectionHistory: Identifiable {

var id: Int {
self.hashValue
}
}

extension ConnectionHistoryEntry: Hashable, Equatable {
extension ConnectionHistory: Hashable, Equatable {

func hash(into hasher: inout Hasher) {
hasher.combine(url)
hasher.combine(token)
}

static func == (lhs: ConnectionHistoryEntry, rhs: ConnectionHistoryEntry) -> Bool {
static func == (lhs: ConnectionHistory, rhs: ConnectionHistory) -> Bool {
return lhs.url == rhs.url && lhs.token == rhs.token
}
}

extension ConnectionHistory: RawRepresentable {

private static let encoder = JSONEncoder()
private static let decoder = JSONDecoder()
extension Sequence where Element == ConnectionHistory {

var view: [ConnectionHistoryEntry] {
var sortedByUpdated: [ConnectionHistory] {
Array(self).sorted { $0.updated > $1.updated }
}
}

public init?(rawValue: String) {
guard let data = rawValue.data(using: .utf8),
let result = try? Self.decoder.decode(Set<ConnectionHistoryEntry>.self, from: data)
else { return nil }
self = result
}

public var rawValue: String {
guard let data = try? Self.encoder.encode(self),
let result = String(data: data, encoding: .utf8)
else { return "[]" }
return result
}
extension Set where Element == ConnectionHistory {

public mutating func update(room: Room) {
mutating func update(room: Room) {

guard let url = room.url,
let token = room.token,
let localParticipant = room.localParticipant else { return }

let element = ConnectionHistoryEntry(
let element = ConnectionHistory(
updated: Date(),
url: url,
token: token,
Expand Down
Loading

0 comments on commit c727651

Please sign in to comment.