Implement end call message
This commit is contained in:
parent
ae3cce97df
commit
6fdf544368
|
@ -42,7 +42,7 @@ final class CallVC : UIViewController, WebRTCSessionDelegate {
|
|||
return result
|
||||
}()
|
||||
|
||||
private lazy var titleView: UILabel = {
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let result = UILabel()
|
||||
result.textColor = .white
|
||||
result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
|
||||
|
@ -50,6 +50,16 @@ final class CallVC : UIViewController, WebRTCSessionDelegate {
|
|||
return result
|
||||
}()
|
||||
|
||||
private lazy var callEndedLabel: UILabel = {
|
||||
let result = UILabel()
|
||||
result.textColor = .white
|
||||
result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
|
||||
result.textAlignment = .center
|
||||
result.text = "Call Ended"
|
||||
result.alpha = 0
|
||||
return result
|
||||
}()
|
||||
|
||||
// MARK: Mode
|
||||
enum Mode {
|
||||
case offer
|
||||
|
@ -78,7 +88,7 @@ final class CallVC : UIViewController, WebRTCSessionDelegate {
|
|||
Storage.read { transaction in
|
||||
contact = Storage.shared.getContact(with: self.sessionID)
|
||||
}
|
||||
titleView.text = contact?.displayName(for: Contact.Context.regular) ?? sessionID
|
||||
titleLabel.text = contact?.displayName(for: Contact.Context.regular) ?? sessionID
|
||||
if case .offer = mode {
|
||||
Storage.write { transaction in
|
||||
self.webRTCSession.sendOffer(to: self.sessionID, using: transaction).retainUntilComplete()
|
||||
|
@ -116,10 +126,14 @@ final class CallVC : UIViewController, WebRTCSessionDelegate {
|
|||
closeButton.pin(.left, to: .left, of: view)
|
||||
closeButton.pin(.top, to: .top, of: view, withInset: 32)
|
||||
// Title view
|
||||
view.addSubview(titleView)
|
||||
titleView.translatesAutoresizingMaskIntoConstraints = false
|
||||
titleView.center(.vertical, in: closeButton)
|
||||
titleView.center(.horizontal, in: view)
|
||||
view.addSubview(titleLabel)
|
||||
titleLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
titleLabel.center(.vertical, in: closeButton)
|
||||
titleLabel.center(.horizontal, in: view)
|
||||
// Call ended label
|
||||
view.addSubview(callEndedLabel)
|
||||
callEndedLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
callEndedLabel.center(in: view)
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
|
@ -132,12 +146,22 @@ final class CallVC : UIViewController, WebRTCSessionDelegate {
|
|||
cameraManager.stop()
|
||||
}
|
||||
|
||||
deinit {
|
||||
// MARK: Interaction
|
||||
func handleEndCallMessage(_ message: CallMessage) {
|
||||
WebRTCSession.current?.dropConnection()
|
||||
WebRTCSession.current = nil
|
||||
UIView.animate(withDuration: 0.25) {
|
||||
self.callEndedLabel.alpha = 1
|
||||
}
|
||||
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
|
||||
self.presentingViewController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Interaction
|
||||
@objc private func close() {
|
||||
Storage.write { transaction in
|
||||
WebRTCSession.current?.endCall(with: self.sessionID, using: transaction)
|
||||
}
|
||||
presentingViewController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ extension AppDelegate {
|
|||
|
||||
@objc
|
||||
func setUpCallHandling() {
|
||||
// Offer messages
|
||||
MessageReceiver.handleOfferCallMessage = { message in
|
||||
DispatchQueue.main.async {
|
||||
let sdp = RTCSessionDescription(type: .offer, sdp: message.sdps![0])
|
||||
|
@ -24,6 +25,13 @@ extension AppDelegate {
|
|||
presentingVC.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
// End call messages
|
||||
MessageReceiver.handleEndCallMessage = { message in
|
||||
DispatchQueue.main.async {
|
||||
guard let callVC = CurrentAppContext().frontmostViewController() as? CallVC else { return }
|
||||
callVC.handleEndCallMessage(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc(syncConfigurationIfNeeded)
|
||||
|
|
|
@ -190,6 +190,15 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
public func endCall(with sessionID: String, using transaction: YapDatabaseReadWriteTransaction) {
|
||||
guard let thread = TSContactThread.fetch(for: sessionID, using: transaction) else { return }
|
||||
let message = CallMessage()
|
||||
message.kind = .endCall
|
||||
MessageSender.sendNonDurably(message, in: thread, using: transaction).retainUntilComplete()
|
||||
dropConnection()
|
||||
WebRTCSession.current = nil
|
||||
}
|
||||
|
||||
public func dropConnection() {
|
||||
peerConnection.close()
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ public final class CallMessage : ControlMessage {
|
|||
case answer
|
||||
case provisionalAnswer
|
||||
case iceCandidates(sdpMLineIndexes: [UInt32], sdpMids: [String])
|
||||
case endCall
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
|
@ -22,6 +23,7 @@ public final class CallMessage : ControlMessage {
|
|||
case .answer: return "answer"
|
||||
case .provisionalAnswer: return "provisionalAnswer"
|
||||
case .iceCandidates(_, _): return "iceCandidates"
|
||||
case .endCall: return "endCall"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +56,7 @@ public final class CallMessage : ControlMessage {
|
|||
guard let sdpMLineIndexes = coder.decodeObject(forKey: "sdpMLineIndexes") as? [UInt32],
|
||||
let sdpMids = coder.decodeObject(forKey: "sdpMids") as? [String] else { return nil }
|
||||
kind = .iceCandidates(sdpMLineIndexes: sdpMLineIndexes, sdpMids: sdpMids)
|
||||
case "endCall": kind = .endCall
|
||||
default: preconditionFailure()
|
||||
}
|
||||
if let sdps = coder.decodeObject(forKey: "sdps") as! [String]? { self.sdps = sdps }
|
||||
|
@ -69,6 +72,7 @@ public final class CallMessage : ControlMessage {
|
|||
coder.encode("iceCandidates", forKey: "kind")
|
||||
coder.encode(sdpMLineIndexes, forKey: "sdpMLineIndexes")
|
||||
coder.encode(sdpMids, forKey: "sdpMids")
|
||||
case .endCall: coder.encode("endCall", forKey: "kind")
|
||||
default: preconditionFailure()
|
||||
}
|
||||
coder.encode(sdps, forKey: "sdps")
|
||||
|
@ -86,6 +90,7 @@ public final class CallMessage : ControlMessage {
|
|||
let sdpMLineIndexes = callMessageProto.sdpMlineIndexes
|
||||
let sdpMids = callMessageProto.sdpMids
|
||||
kind = .iceCandidates(sdpMLineIndexes: sdpMLineIndexes, sdpMids: sdpMids)
|
||||
case .endCall: kind = .endCall
|
||||
}
|
||||
let sdps = callMessageProto.sdps
|
||||
return CallMessage(kind: kind, sdps: sdps)
|
||||
|
@ -102,6 +107,7 @@ public final class CallMessage : ControlMessage {
|
|||
case .answer: type = .answer
|
||||
case .provisionalAnswer: type = .provisionalAnswer
|
||||
case .iceCandidates(_, _): type = .iceCandidates
|
||||
case .endCall: type = .endCall
|
||||
}
|
||||
let callMessageProto = SNProtoCallMessage.builder(type: type)
|
||||
callMessageProto.setSdps(sdps)
|
||||
|
|
|
@ -657,6 +657,7 @@ extension SNProtoContent.SNProtoContentBuilder {
|
|||
case answer = 2
|
||||
case provisionalAnswer = 3
|
||||
case iceCandidates = 4
|
||||
case endCall = 5
|
||||
}
|
||||
|
||||
private class func SNProtoCallMessageTypeWrap(_ value: SessionProtos_CallMessage.TypeEnum) -> SNProtoCallMessageType {
|
||||
|
@ -665,6 +666,7 @@ extension SNProtoContent.SNProtoContentBuilder {
|
|||
case .answer: return .answer
|
||||
case .provisionalAnswer: return .provisionalAnswer
|
||||
case .iceCandidates: return .iceCandidates
|
||||
case .endCall: return .endCall
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -674,6 +676,7 @@ extension SNProtoContent.SNProtoContentBuilder {
|
|||
case .answer: return .answer
|
||||
case .provisionalAnswer: return .provisionalAnswer
|
||||
case .iceCandidates: return .iceCandidates
|
||||
case .endCall: return .endCall
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -333,6 +333,7 @@ struct SessionProtos_CallMessage {
|
|||
case answer // = 2
|
||||
case provisionalAnswer // = 3
|
||||
case iceCandidates // = 4
|
||||
case endCall // = 5
|
||||
|
||||
init() {
|
||||
self = .offer
|
||||
|
@ -344,6 +345,7 @@ struct SessionProtos_CallMessage {
|
|||
case 2: self = .answer
|
||||
case 3: self = .provisionalAnswer
|
||||
case 4: self = .iceCandidates
|
||||
case 5: self = .endCall
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
@ -354,6 +356,7 @@ struct SessionProtos_CallMessage {
|
|||
case .answer: return 2
|
||||
case .provisionalAnswer: return 3
|
||||
case .iceCandidates: return 4
|
||||
case .endCall: return 5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1849,6 +1852,7 @@ extension SessionProtos_CallMessage.TypeEnum: SwiftProtobuf._ProtoNameProviding
|
|||
2: .same(proto: "ANSWER"),
|
||||
3: .same(proto: "PROVISIONAL_ANSWER"),
|
||||
4: .same(proto: "ICE_CANDIDATES"),
|
||||
5: .same(proto: "END_CALL"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ message CallMessage {
|
|||
ANSWER = 2;
|
||||
PROVISIONAL_ANSWER = 3;
|
||||
ICE_CANDIDATES = 4;
|
||||
END_CALL = 5;
|
||||
}
|
||||
|
||||
// Multiple ICE candidates may be batched together for performance
|
||||
|
|
|
@ -289,6 +289,7 @@ extension MessageReceiver {
|
|||
candidates.append(candidate)
|
||||
}
|
||||
getWebRTCSession().handleICECandidates(candidates)
|
||||
case .endCall: handleEndCallMessage?(message)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import SessionUtilitiesKit
|
|||
public enum MessageReceiver {
|
||||
private static var lastEncryptionKeyPairRequest: [String:Date] = [:]
|
||||
public static var handleOfferCallMessage: ((CallMessage) -> Void)?
|
||||
public static var handleEndCallMessage: ((CallMessage) -> Void)?
|
||||
|
||||
public enum Error : LocalizedError {
|
||||
case duplicateMessage
|
||||
|
|
Loading…
Reference in New Issue