From 6fdf544368d5a164b0b0356a6e1f413449efa479 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Wed, 18 Aug 2021 10:33:33 +1000 Subject: [PATCH] Implement end call message --- Session/Calls/CallVC.swift | 40 +++++++++++++++---- Session/Meta/AppDelegate.swift | 8 ++++ SessionMessagingKit/Calls/WebRTCSession.swift | 9 +++++ .../Control Messages/CallMessage.swift | 6 +++ .../Protos/Generated/SNProto.swift | 3 ++ .../Protos/Generated/SessionProtos.pb.swift | 4 ++ .../Protos/SessionProtos.proto | 1 + .../MessageReceiver+Handling.swift | 1 + .../Sending & Receiving/MessageReceiver.swift | 1 + 9 files changed, 65 insertions(+), 8 deletions(-) diff --git a/Session/Calls/CallVC.swift b/Session/Calls/CallVC.swift index 00f7bec44..197aef925 100644 --- a/Session/Calls/CallVC.swift +++ b/Session/Calls/CallVC.swift @@ -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) } } diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index 8880a26e0..63303881c 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -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) diff --git a/SessionMessagingKit/Calls/WebRTCSession.swift b/SessionMessagingKit/Calls/WebRTCSession.swift index 956c4f4ab..401991e96 100644 --- a/SessionMessagingKit/Calls/WebRTCSession.swift +++ b/SessionMessagingKit/Calls/WebRTCSession.swift @@ -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() } diff --git a/SessionMessagingKit/Messages/Control Messages/CallMessage.swift b/SessionMessagingKit/Messages/Control Messages/CallMessage.swift index c1d4865a1..ac566c14c 100644 --- a/SessionMessagingKit/Messages/Control Messages/CallMessage.swift +++ b/SessionMessagingKit/Messages/Control Messages/CallMessage.swift @@ -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) diff --git a/SessionMessagingKit/Protos/Generated/SNProto.swift b/SessionMessagingKit/Protos/Generated/SNProto.swift index 134c63017..dae62350a 100644 --- a/SessionMessagingKit/Protos/Generated/SNProto.swift +++ b/SessionMessagingKit/Protos/Generated/SNProto.swift @@ -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 } } diff --git a/SessionMessagingKit/Protos/Generated/SessionProtos.pb.swift b/SessionMessagingKit/Protos/Generated/SessionProtos.pb.swift index bf534a845..7b4894f60 100644 --- a/SessionMessagingKit/Protos/Generated/SessionProtos.pb.swift +++ b/SessionMessagingKit/Protos/Generated/SessionProtos.pb.swift @@ -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"), ] } diff --git a/SessionMessagingKit/Protos/SessionProtos.proto b/SessionMessagingKit/Protos/SessionProtos.proto index a2927a698..4193d202c 100644 --- a/SessionMessagingKit/Protos/SessionProtos.proto +++ b/SessionMessagingKit/Protos/SessionProtos.proto @@ -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 diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index 0f856f255..8cd74e633 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -289,6 +289,7 @@ extension MessageReceiver { candidates.append(candidate) } getWebRTCSession().handleICECandidates(candidates) + case .endCall: handleEndCallMessage?(message) } } diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index 78ba53208..26a809089 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -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