You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/Session/Calls/Call Management/SessionCall.swift

133 lines
3.7 KiB
Swift

import Foundation
import WebRTC
import SessionMessagingKit
public final class SessionCall: NSObject {
// MARK: Metadata Properties
let uuid: UUID
let sessionID: String
let mode: Mode
let webRTCSession: WebRTCSession
var contactName: String {
let contact = Storage.shared.getContact(with: self.sessionID)
return contact?.displayName(for: Contact.Context.regular) ?? self.sessionID
}
var profilePicture: UIImage {
if let result = OWSProfileManager.shared().profileAvatar(forRecipientId: sessionID) {
return result
} else {
return Identicon.generatePlaceholderIcon(seed: sessionID, text: contactName, size: 300)
}
}
// MARK: Mode
enum Mode {
case offer
case answer(sdp: RTCSessionDescription)
}
// MARK: Call State Properties
var connectingDate: Date? {
didSet {
stateDidChange?()
hasStartedConnectingDidChange?()
}
}
var connectedDate: Date? {
didSet {
stateDidChange?()
hasConnectedDidChange?()
}
}
var endDate: Date? {
didSet {
stateDidChange?()
hasEndedDidChange?()
}
}
// Not yet implemented
var isOnHold = false {
didSet {
stateDidChange?()
}
}
// MARK: State Change Callbacks
var stateDidChange: (() -> Void)?
var hasStartedConnectingDidChange: (() -> Void)?
var hasConnectedDidChange: (() -> Void)?
var hasEndedDidChange: (() -> Void)?
// MARK: Derived Properties
var hasStartedConnecting: Bool {
get { return connectingDate != nil }
set { connectingDate = newValue ? Date() : nil }
}
var hasConnected: Bool {
get { return connectedDate != nil }
set { connectedDate = newValue ? Date() : nil }
}
var hasEnded: Bool {
get { return endDate != nil }
set { endDate = newValue ? Date() : nil }
}
var duration: TimeInterval {
guard let connectedDate = connectedDate else {
return 0
}
return Date().timeIntervalSince(connectedDate)
}
// MARK: Initialization
init(for sessionID: String, uuid: String, mode: Mode) {
self.sessionID = sessionID
self.uuid = UUID(uuidString: uuid)!
self.mode = mode
self.webRTCSession = WebRTCSession.current ?? WebRTCSession(for: sessionID, with: uuid)
super.init()
reportIncomingCallIfNeeded()
}
func reportIncomingCallIfNeeded() {
guard case .offer = mode else { return }
AppEnvironment.shared.callManager.reportIncomingCall(self, callerName: contactName) { error in
}
}
// MARK: Actions
func startSessionCall(completion: (() -> Void)?) {
guard case .offer = mode else { return }
Storage.write { transaction in
self.webRTCSession.sendPreOffer(to: self.sessionID, using: transaction).done {
self.webRTCSession.sendOffer(to: self.sessionID, using: transaction).done {
self.hasStartedConnecting = true
}.retainUntilComplete()
}.retainUntilComplete()
}
completion?()
}
func answerSessionCall(completion: (() -> Void)?) {
guard case let .answer(sdp) = mode else { return }
hasStartedConnecting = true
webRTCSession.handleRemoteSDP(sdp, from: sessionID) // This sends an answer message internally
completion?()
}
func endSessionCall() {
guard !hasEnded else { return }
Storage.write { transaction in
self.webRTCSession.endCall(with: self.sessionID, using: transaction)
}
hasEnded = true
}
}