138 lines
4.8 KiB
Swift
138 lines
4.8 KiB
Swift
/*
|
||
* 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 Foundation
|
||
import LiveKit
|
||
import SFSafeSymbols
|
||
import SwiftUI
|
||
|
||
struct ConnectView: View {
|
||
@EnvironmentObject var appCtx: AppContext
|
||
@EnvironmentObject var roomCtx: RoomContext
|
||
@EnvironmentObject var room: Room
|
||
|
||
var httpService = HTTPClient()
|
||
|
||
|
||
var body: some View {
|
||
GeometryReader { geometry in
|
||
Color.ovGray
|
||
.ignoresSafeArea()
|
||
ScrollView {
|
||
VStack(alignment: .center, spacing: 40.0) {
|
||
VStack(spacing: 10) {
|
||
Image("logo")
|
||
.resizable()
|
||
.aspectRatio(contentMode: .fit)
|
||
.frame(height: 50)
|
||
.padding(.bottom, 10)
|
||
}
|
||
|
||
VStack(spacing: 15) {
|
||
LKTextField(title: "Participant Name", text: $roomCtx.localParticipantName, type: .ascii)
|
||
LKTextField(title: "Room Name", text: $roomCtx.name, type: .ascii)
|
||
}
|
||
.frame(maxWidth: 350)
|
||
|
||
if case .connecting = room.connectionState {
|
||
HStack(alignment: .center) {
|
||
ProgressView()
|
||
|
||
LKButton(title: "Cancel") {
|
||
roomCtx.cancelConnect()
|
||
}
|
||
}
|
||
} else {
|
||
HStack(alignment: .center) {
|
||
|
||
|
||
Spacer()
|
||
|
||
LKButton(title: "Reset urls", action: {
|
||
Task.detached { @MainActor in
|
||
roomCtx.livekitUrl = ""
|
||
appCtx.applicationServerUrl = ""
|
||
}
|
||
}, color: Color.ovYellow)
|
||
|
||
|
||
LKButton(title: "Join") {
|
||
Task.detached { @MainActor in
|
||
await connectToRoom()
|
||
}
|
||
}
|
||
|
||
Spacer()
|
||
}
|
||
}
|
||
}
|
||
.padding()
|
||
.frame(width: geometry.size.width) // Make the scroll view full-width
|
||
.frame(minHeight: geometry.size.height) // Set the content’s min height to the parent
|
||
}
|
||
}
|
||
#if os(macOS)
|
||
.frame(minWidth: 500, minHeight: 500)
|
||
#endif
|
||
.alert(isPresented: $roomCtx.shouldShowDisconnectReason) {
|
||
Alert(title: Text("Disconnected"),
|
||
message: Text("Reason: " + String(describing: roomCtx.latestError)))
|
||
}
|
||
}
|
||
|
||
func connectToRoom() async {
|
||
let livekitUrl = roomCtx.livekitUrl
|
||
let roomName = roomCtx.name
|
||
let participantName = roomCtx.localParticipantName
|
||
let applicationServerUrl = appCtx.applicationServerUrl
|
||
|
||
guard !livekitUrl.isEmpty, !roomName.isEmpty else {
|
||
print("LiveKit URL or room name is empty")
|
||
return
|
||
}
|
||
|
||
do {
|
||
let token = try await httpService.getToken(applicationServerUrl: applicationServerUrl, roomName: roomName, participantName: participantName)
|
||
print("Token received: \(token)")
|
||
|
||
if token.isEmpty {
|
||
print("Received empty token")
|
||
return
|
||
}
|
||
|
||
roomCtx.token = token
|
||
print("Connecting to room...")
|
||
try await roomCtx.connect()
|
||
print("Room connected")
|
||
await enableCameraAndMicrophone()
|
||
|
||
} catch {
|
||
print("Error trying to connect to room: \(error.localizedDescription)")
|
||
}
|
||
}
|
||
|
||
func enableCameraAndMicrophone() async {
|
||
do {
|
||
try await room.localParticipant.setCamera(enabled: true)
|
||
try await room.localParticipant.setMicrophone(enabled: true)
|
||
} catch {
|
||
print("Error enabling camera and microphone: \(error.localizedDescription)")
|
||
}
|
||
}
|
||
|
||
|
||
}
|