mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Merge pull request #615 from RyanRory/bug-fix-for-calls
Fix for call release
This commit is contained in:
commit
5221537e56
|
@ -128,6 +128,7 @@
|
||||||
7B0EFDF2275449AA00FFAAE7 /* TSInfoMessage+Calls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0EFDF1275449AA00FFAAE7 /* TSInfoMessage+Calls.swift */; };
|
7B0EFDF2275449AA00FFAAE7 /* TSInfoMessage+Calls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0EFDF1275449AA00FFAAE7 /* TSInfoMessage+Calls.swift */; };
|
||||||
7B0EFDF4275490EA00FFAAE7 /* ringing.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 7B0EFDF3275490EA00FFAAE7 /* ringing.mp3 */; };
|
7B0EFDF4275490EA00FFAAE7 /* ringing.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 7B0EFDF3275490EA00FFAAE7 /* ringing.mp3 */; };
|
||||||
7B0EFDF62755CC5400FFAAE7 /* CallMissedTipsModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0EFDF52755CC5400FFAAE7 /* CallMissedTipsModal.swift */; };
|
7B0EFDF62755CC5400FFAAE7 /* CallMissedTipsModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0EFDF52755CC5400FFAAE7 /* CallMissedTipsModal.swift */; };
|
||||||
|
7B13E1E92810F01300BD4F64 /* SessionCallManager+Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B13E1E82810F01300BD4F64 /* SessionCallManager+Action.swift */; };
|
||||||
7B1581E2271E743B00848B49 /* OWSSounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E1271E743B00848B49 /* OWSSounds.swift */; };
|
7B1581E2271E743B00848B49 /* OWSSounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E1271E743B00848B49 /* OWSSounds.swift */; };
|
||||||
7B1581E4271FC59D00848B49 /* CallModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E3271FC59C00848B49 /* CallModal.swift */; };
|
7B1581E4271FC59D00848B49 /* CallModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E3271FC59C00848B49 /* CallModal.swift */; };
|
||||||
7B1581E6271FD2A100848B49 /* VideoPreviewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E5271FD2A100848B49 /* VideoPreviewVC.swift */; };
|
7B1581E6271FD2A100848B49 /* VideoPreviewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E5271FD2A100848B49 /* VideoPreviewVC.swift */; };
|
||||||
|
@ -1115,6 +1116,7 @@
|
||||||
7B0EFDF1275449AA00FFAAE7 /* TSInfoMessage+Calls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSInfoMessage+Calls.swift"; sourceTree = "<group>"; };
|
7B0EFDF1275449AA00FFAAE7 /* TSInfoMessage+Calls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSInfoMessage+Calls.swift"; sourceTree = "<group>"; };
|
||||||
7B0EFDF3275490EA00FFAAE7 /* ringing.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ringing.mp3; sourceTree = "<group>"; };
|
7B0EFDF3275490EA00FFAAE7 /* ringing.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ringing.mp3; sourceTree = "<group>"; };
|
||||||
7B0EFDF52755CC5400FFAAE7 /* CallMissedTipsModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMissedTipsModal.swift; sourceTree = "<group>"; };
|
7B0EFDF52755CC5400FFAAE7 /* CallMissedTipsModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMissedTipsModal.swift; sourceTree = "<group>"; };
|
||||||
|
7B13E1E82810F01300BD4F64 /* SessionCallManager+Action.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionCallManager+Action.swift"; sourceTree = "<group>"; };
|
||||||
7B1581E1271E743B00848B49 /* OWSSounds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSSounds.swift; sourceTree = "<group>"; };
|
7B1581E1271E743B00848B49 /* OWSSounds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSSounds.swift; sourceTree = "<group>"; };
|
||||||
7B1581E3271FC59C00848B49 /* CallModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallModal.swift; sourceTree = "<group>"; };
|
7B1581E3271FC59C00848B49 /* CallModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallModal.swift; sourceTree = "<group>"; };
|
||||||
7B1581E5271FD2A100848B49 /* VideoPreviewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPreviewVC.swift; sourceTree = "<group>"; };
|
7B1581E5271FD2A100848B49 /* VideoPreviewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPreviewVC.swift; sourceTree = "<group>"; };
|
||||||
|
@ -2098,6 +2100,7 @@
|
||||||
7BC707F127290ACB002817AD /* SessionCallManager.swift */,
|
7BC707F127290ACB002817AD /* SessionCallManager.swift */,
|
||||||
7BA6890C27325CCC00EFC32F /* SessionCallManager+CXCallController.swift */,
|
7BA6890C27325CCC00EFC32F /* SessionCallManager+CXCallController.swift */,
|
||||||
7BA6890E27325CE300EFC32F /* SessionCallManager+CXProvider.swift */,
|
7BA6890E27325CE300EFC32F /* SessionCallManager+CXProvider.swift */,
|
||||||
|
7B13E1E82810F01300BD4F64 /* SessionCallManager+Action.swift */,
|
||||||
);
|
);
|
||||||
path = "Call Management";
|
path = "Call Management";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -4952,6 +4955,7 @@
|
||||||
7B7CB190270FB2150079FF93 /* MiniCallView.swift in Sources */,
|
7B7CB190270FB2150079FF93 /* MiniCallView.swift in Sources */,
|
||||||
B875885A264503A6000E60D0 /* JoinOpenGroupModal.swift in Sources */,
|
B875885A264503A6000E60D0 /* JoinOpenGroupModal.swift in Sources */,
|
||||||
B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */,
|
B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */,
|
||||||
|
7B13E1E92810F01300BD4F64 /* SessionCallManager+Action.swift in Sources */,
|
||||||
C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */,
|
C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */,
|
||||||
7B1581E827210ECC00848B49 /* RenderView.swift in Sources */,
|
7B1581E827210ECC00848B49 /* RenderView.swift in Sources */,
|
||||||
7BC707F227290ACB002817AD /* SessionCallManager.swift in Sources */,
|
7BC707F227290ACB002817AD /* SessionCallManager.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
extension SessionCallManager {
|
||||||
|
@discardableResult
|
||||||
|
public func startCallAction() -> Bool {
|
||||||
|
guard let call = self.currentCall else { return false }
|
||||||
|
call.startSessionCall()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public func answerCallAction() -> Bool {
|
||||||
|
guard let call = self.currentCall else { return false }
|
||||||
|
if let _ = CurrentAppContext().frontmostViewController() as? CallVC {
|
||||||
|
call.answerSessionCall()
|
||||||
|
} else {
|
||||||
|
guard let presentingVC = CurrentAppContext().frontmostViewController() else { return false } // FIXME: Handle more gracefully
|
||||||
|
let callVC = CallVC(for: self.currentCall!)
|
||||||
|
if let conversationVC = presentingVC as? ConversationVC {
|
||||||
|
callVC.conversationVC = conversationVC
|
||||||
|
conversationVC.inputAccessoryView?.isHidden = true
|
||||||
|
conversationVC.inputAccessoryView?.alpha = 0
|
||||||
|
}
|
||||||
|
presentingVC.present(callVC, animated: true) {
|
||||||
|
call.answerSessionCall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public func endCallAction() -> Bool {
|
||||||
|
guard let call = self.currentCall else { return false }
|
||||||
|
call.endSessionCall()
|
||||||
|
if call.didTimeout {
|
||||||
|
reportCurrentCallEnded(reason: .unanswered)
|
||||||
|
} else {
|
||||||
|
reportCurrentCallEnded(reason: nil)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public func setMutedCallAction(isMuted: Bool) -> Bool {
|
||||||
|
guard let call = self.currentCall else { return false }
|
||||||
|
call.isMuted = isMuted
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,45 +5,62 @@ extension SessionCallManager {
|
||||||
public func startCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
public func startCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
||||||
guard case .offer = call.mode else { return }
|
guard case .offer = call.mode else { return }
|
||||||
guard !call.hasConnected else { return }
|
guard !call.hasConnected else { return }
|
||||||
let handle = CXHandle(type: .generic, value: call.sessionID)
|
|
||||||
let startCallAction = CXStartCallAction(call: call.callID, handle: handle)
|
|
||||||
|
|
||||||
startCallAction.isVideo = false
|
|
||||||
|
|
||||||
let transaction = CXTransaction()
|
|
||||||
transaction.addAction(startCallAction)
|
|
||||||
|
|
||||||
reportOutgoingCall(call)
|
reportOutgoingCall(call)
|
||||||
requestTransaction(transaction, completion: completion)
|
if callController != nil {
|
||||||
|
let handle = CXHandle(type: .generic, value: call.sessionID)
|
||||||
|
let startCallAction = CXStartCallAction(call: call.callID, handle: handle)
|
||||||
|
|
||||||
|
startCallAction.isVideo = false
|
||||||
|
|
||||||
|
let transaction = CXTransaction()
|
||||||
|
transaction.addAction(startCallAction)
|
||||||
|
|
||||||
|
requestTransaction(transaction, completion: completion)
|
||||||
|
} else {
|
||||||
|
startCallAction()
|
||||||
|
completion?(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func answerCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
public func answerCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
||||||
let answerCallAction = CXAnswerCallAction(call: call.callID)
|
if callController != nil {
|
||||||
let transaction = CXTransaction()
|
let answerCallAction = CXAnswerCallAction(call: call.callID)
|
||||||
transaction.addAction(answerCallAction)
|
let transaction = CXTransaction()
|
||||||
|
transaction.addAction(answerCallAction)
|
||||||
|
|
||||||
requestTransaction(transaction, completion: completion)
|
requestTransaction(transaction, completion: completion)
|
||||||
|
} else {
|
||||||
|
answerCallAction()
|
||||||
|
completion?(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func endCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
public func endCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
||||||
let endCallAction = CXEndCallAction(call: call.callID)
|
if callController != nil {
|
||||||
let transaction = CXTransaction()
|
let endCallAction = CXEndCallAction(call: call.callID)
|
||||||
transaction.addAction(endCallAction)
|
let transaction = CXTransaction()
|
||||||
|
transaction.addAction(endCallAction)
|
||||||
|
|
||||||
requestTransaction(transaction, completion: completion)
|
requestTransaction(transaction, completion: completion)
|
||||||
|
} else {
|
||||||
|
endCallAction()
|
||||||
|
completion?(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not currently in use
|
// Not currently in use
|
||||||
public func setOnHoldStatus(for call: SessionCall) {
|
public func setOnHoldStatus(for call: SessionCall) {
|
||||||
let setHeldCallAction = CXSetHeldCallAction(call: call.callID, onHold: true)
|
if callController != nil {
|
||||||
let transaction = CXTransaction()
|
let setHeldCallAction = CXSetHeldCallAction(call: call.callID, onHold: true)
|
||||||
transaction.addAction(setHeldCallAction)
|
let transaction = CXTransaction()
|
||||||
|
transaction.addAction(setHeldCallAction)
|
||||||
|
|
||||||
requestTransaction(transaction)
|
requestTransaction(transaction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func requestTransaction(_ transaction: CXTransaction, completion: ((Error?) -> Void)? = nil) {
|
private func requestTransaction(_ transaction: CXTransaction, completion: ((Error?) -> Void)? = nil) {
|
||||||
callController.request(transaction) { error in
|
callController?.request(transaction) { error in
|
||||||
if let error = error {
|
if let error = error {
|
||||||
SNLog("Error requesting transaction: \(error)")
|
SNLog("Error requesting transaction: \(error)")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,9 +8,11 @@ extension SessionCallManager: CXProviderDelegate {
|
||||||
|
|
||||||
public func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
public func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
||||||
AssertIsOnMainThread()
|
AssertIsOnMainThread()
|
||||||
guard let call = self.currentCall else { return action.fail() }
|
if startCallAction() {
|
||||||
call.startSessionCall()
|
action.fulfill()
|
||||||
action.fulfill()
|
} else {
|
||||||
|
action.fail()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
public func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
||||||
|
@ -18,21 +20,11 @@ extension SessionCallManager: CXProviderDelegate {
|
||||||
print("[CallKit] Perform CXAnswerCallAction")
|
print("[CallKit] Perform CXAnswerCallAction")
|
||||||
guard let call = self.currentCall else { return action.fail() }
|
guard let call = self.currentCall else { return action.fail() }
|
||||||
if CurrentAppContext().isMainAppAndActive {
|
if CurrentAppContext().isMainAppAndActive {
|
||||||
if let _ = CurrentAppContext().frontmostViewController() as? CallVC {
|
if answerCallAction() {
|
||||||
call.answerSessionCall()
|
action.fulfill()
|
||||||
} else {
|
} else {
|
||||||
guard let presentingVC = CurrentAppContext().frontmostViewController() else { preconditionFailure() } // FIXME: Handle more gracefully
|
action.fail()
|
||||||
let callVC = CallVC(for: self.currentCall!)
|
|
||||||
if let conversationVC = presentingVC as? ConversationVC {
|
|
||||||
callVC.conversationVC = conversationVC
|
|
||||||
conversationVC.inputAccessoryView?.isHidden = true
|
|
||||||
conversationVC.inputAccessoryView?.alpha = 0
|
|
||||||
}
|
|
||||||
presentingVC.present(callVC, animated: true) {
|
|
||||||
call.answerSessionCall()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
action.fulfill()
|
|
||||||
} else {
|
} else {
|
||||||
call.answerSessionCallInBackground(action: action)
|
call.answerSessionCallInBackground(action: action)
|
||||||
}
|
}
|
||||||
|
@ -41,22 +33,21 @@ extension SessionCallManager: CXProviderDelegate {
|
||||||
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
||||||
print("[CallKit] Perform CXEndCallAction")
|
print("[CallKit] Perform CXEndCallAction")
|
||||||
AssertIsOnMainThread()
|
AssertIsOnMainThread()
|
||||||
guard let call = self.currentCall else { return action.fail() }
|
if endCallAction() {
|
||||||
call.endSessionCall()
|
action.fulfill()
|
||||||
if call.didTimeout {
|
|
||||||
reportCurrentCallEnded(reason: .unanswered)
|
|
||||||
} else {
|
} else {
|
||||||
reportCurrentCallEnded(reason: nil)
|
action.fail()
|
||||||
}
|
}
|
||||||
action.fulfill()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
public func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
||||||
print("[CallKit] Perform CXSetMutedCallAction, isMuted: \(action.isMuted)")
|
print("[CallKit] Perform CXSetMutedCallAction, isMuted: \(action.isMuted)")
|
||||||
AssertIsOnMainThread()
|
AssertIsOnMainThread()
|
||||||
guard let call = self.currentCall else { return action.fail() }
|
if setMutedCallAction(isMuted: action.isMuted) {
|
||||||
call.isMuted = action.isMuted
|
action.fulfill()
|
||||||
action.fulfill()
|
} else {
|
||||||
|
action.fail()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
|
public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
|
||||||
|
|
|
@ -2,8 +2,8 @@ import CallKit
|
||||||
import SessionMessagingKit
|
import SessionMessagingKit
|
||||||
|
|
||||||
public final class SessionCallManager: NSObject {
|
public final class SessionCallManager: NSObject {
|
||||||
let provider: CXProvider
|
let provider: CXProvider?
|
||||||
let callController = CXCallController()
|
let callController: CXCallController?
|
||||||
var currentCall: SessionCall? = nil {
|
var currentCall: SessionCall? = nil {
|
||||||
willSet {
|
willSet {
|
||||||
if (newValue != nil) {
|
if (newValue != nil) {
|
||||||
|
@ -49,12 +49,16 @@ public final class SessionCallManager: NSObject {
|
||||||
|
|
||||||
init(useSystemCallLog: Bool = false) {
|
init(useSystemCallLog: Bool = false) {
|
||||||
AssertIsOnMainThread()
|
AssertIsOnMainThread()
|
||||||
self.provider = type(of: self).sharedProvider(useSystemCallLog: useSystemCallLog)
|
if SSKPreferences.isCallKitSupported {
|
||||||
|
self.provider = type(of: self).sharedProvider(useSystemCallLog: useSystemCallLog)
|
||||||
|
self.callController = CXCallController()
|
||||||
|
} else {
|
||||||
|
self.provider = nil
|
||||||
|
self.callController = nil
|
||||||
|
}
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
// We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings
|
// We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings
|
||||||
self.provider.setDelegate(self, queue: nil)
|
self.provider?.setDelegate(self, queue: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Report calls
|
// MARK: Report calls
|
||||||
|
@ -63,10 +67,10 @@ public final class SessionCallManager: NSObject {
|
||||||
UserDefaults(suiteName: "group.com.loki-project.loki-messenger")?.set(true, forKey: "isCallOngoing")
|
UserDefaults(suiteName: "group.com.loki-project.loki-messenger")?.set(true, forKey: "isCallOngoing")
|
||||||
call.stateDidChange = {
|
call.stateDidChange = {
|
||||||
if call.hasStartedConnecting {
|
if call.hasStartedConnecting {
|
||||||
self.provider.reportOutgoingCall(with: call.callID, startedConnectingAt: call.connectingDate)
|
self.provider?.reportOutgoingCall(with: call.callID, startedConnectingAt: call.connectingDate)
|
||||||
}
|
}
|
||||||
if call.hasConnected {
|
if call.hasConnected {
|
||||||
self.provider.reportOutgoingCall(with: call.callID, connectedAt: call.connectedDate)
|
self.provider?.reportOutgoingCall(with: call.callID, connectedAt: call.connectedDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,21 +78,26 @@ public final class SessionCallManager: NSObject {
|
||||||
public func reportIncomingCall(_ call: SessionCall, callerName: String, completion: @escaping (Error?) -> Void) {
|
public func reportIncomingCall(_ call: SessionCall, callerName: String, completion: @escaping (Error?) -> Void) {
|
||||||
AssertIsOnMainThread()
|
AssertIsOnMainThread()
|
||||||
|
|
||||||
// Construct a CXCallUpdate describing the incoming call, including the caller.
|
if let provider = provider {
|
||||||
let update = CXCallUpdate()
|
// Construct a CXCallUpdate describing the incoming call, including the caller.
|
||||||
update.localizedCallerName = callerName
|
let update = CXCallUpdate()
|
||||||
update.remoteHandle = CXHandle(type: .generic, value: call.callID.uuidString)
|
update.localizedCallerName = callerName
|
||||||
update.hasVideo = false
|
update.remoteHandle = CXHandle(type: .generic, value: call.callID.uuidString)
|
||||||
|
update.hasVideo = false
|
||||||
|
|
||||||
disableUnsupportedFeatures(callUpdate: update)
|
disableUnsupportedFeatures(callUpdate: update)
|
||||||
|
|
||||||
// Report the incoming call to the system
|
// Report the incoming call to the system
|
||||||
self.provider.reportNewIncomingCall(with: call.callID, update: update) { error in
|
provider.reportNewIncomingCall(with: call.callID, update: update) { error in
|
||||||
guard error == nil else {
|
guard error == nil else {
|
||||||
self.reportCurrentCallEnded(reason: .failed)
|
self.reportCurrentCallEnded(reason: .failed)
|
||||||
completion(error)
|
completion(error)
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
UserDefaults(suiteName: "group.com.loki-project.loki-messenger")?.set(true, forKey: "isCallOngoing")
|
||||||
|
completion(nil)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
UserDefaults(suiteName: "group.com.loki-project.loki-messenger")?.set(true, forKey: "isCallOngoing")
|
UserDefaults(suiteName: "group.com.loki-project.loki-messenger")?.set(true, forKey: "isCallOngoing")
|
||||||
completion(nil)
|
completion(nil)
|
||||||
}
|
}
|
||||||
|
@ -97,7 +106,7 @@ public final class SessionCallManager: NSObject {
|
||||||
public func reportCurrentCallEnded(reason: CXCallEndedReason?) {
|
public func reportCurrentCallEnded(reason: CXCallEndedReason?) {
|
||||||
guard let call = currentCall else { return }
|
guard let call = currentCall else { return }
|
||||||
if let reason = reason {
|
if let reason = reason {
|
||||||
self.provider.reportCall(with: call.callID, endedAt: nil, reason: reason)
|
self.provider?.reportCall(with: call.callID, endedAt: nil, reason: reason)
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case .answeredElsewhere: call.updateCallMessage(mode: .answeredElsewhere)
|
case .answeredElsewhere: call.updateCallMessage(mode: .answeredElsewhere)
|
||||||
case .unanswered: call.updateCallMessage(mode: .unanswered)
|
case .unanswered: call.updateCallMessage(mode: .unanswered)
|
||||||
|
|
|
@ -20,7 +20,7 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
|
||||||
private lazy var displayNameLabel: UILabel = {
|
private lazy var displayNameLabel: UILabel = {
|
||||||
let result = UILabel()
|
let result = UILabel()
|
||||||
result.textColor = UIColor.white
|
result.textColor = UIColor.white
|
||||||
result.font = .boldSystemFont(ofSize: Values.largeFontSize)
|
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
result.lineBreakMode = .byTruncatingTail
|
result.lineBreakMode = .byTruncatingTail
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
@ -78,8 +78,8 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setUpViewHierarchy() {
|
private func setUpViewHierarchy() {
|
||||||
self.backgroundColor = UIColor(hex: 0x000000).withAlphaComponent(0.9)
|
self.backgroundColor = UIColor(hex: 0x000000).withAlphaComponent(0.8)
|
||||||
self.layer.cornerRadius = Values.veryLargeSpacing
|
self.layer.cornerRadius = Values.largeSpacing
|
||||||
self.layer.masksToBounds = true
|
self.layer.masksToBounds = true
|
||||||
self.set(.height, to: 100)
|
self.set(.height, to: 100)
|
||||||
profilePictureView.publicKey = call.sessionID
|
profilePictureView.publicKey = call.sessionID
|
||||||
|
|
|
@ -437,6 +437,12 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
|
||||||
mediaCache.removeAllObjects()
|
mediaCache.removeAllObjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func appDidBecomeActive(_ notification: Notification) {
|
||||||
|
// This is a workaround for an issue where the textview is not scrollable
|
||||||
|
// after the app goes into background and goes back in foreground.
|
||||||
|
self.snInputView.text = self.snInputView.text
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
NotificationCenter.default.removeObserver(self)
|
NotificationCenter.default.removeObserver(self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,6 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
|
||||||
notificationCenter.addObserver(self, selector: #selector(handleLocalProfileDidChangeNotification(_:)), name: Notification.Name(kNSNotificationName_LocalProfileDidChange), object: nil)
|
notificationCenter.addObserver(self, selector: #selector(handleLocalProfileDidChangeNotification(_:)), name: Notification.Name(kNSNotificationName_LocalProfileDidChange), object: nil)
|
||||||
notificationCenter.addObserver(self, selector: #selector(handleSeedViewedNotification(_:)), name: .seedViewed, object: nil)
|
notificationCenter.addObserver(self, selector: #selector(handleSeedViewedNotification(_:)), name: .seedViewed, object: nil)
|
||||||
notificationCenter.addObserver(self, selector: #selector(handleBlockedContactsUpdatedNotification(_:)), name: .blockedContactsUpdated, object: nil)
|
notificationCenter.addObserver(self, selector: #selector(handleBlockedContactsUpdatedNotification(_:)), name: .blockedContactsUpdated, object: nil)
|
||||||
notificationCenter.addObserver(self, selector: #selector(applicationDidBecomeActive(_:)), name: .OWSApplicationDidBecomeActive, object: nil)
|
|
||||||
// Threads (part 2)
|
// Threads (part 2)
|
||||||
threads = YapDatabaseViewMappings(groups: [ TSMessageRequestGroup, TSInboxGroup ], view: TSThreadDatabaseViewExtensionName) // The extension should be registered at this point
|
threads = YapDatabaseViewMappings(groups: [ TSMessageRequestGroup, TSInboxGroup ], view: TSThreadDatabaseViewExtensionName) // The extension should be registered at this point
|
||||||
threads.setIsReversed(true, forGroup: TSInboxGroup)
|
threads.setIsReversed(true, forGroup: TSInboxGroup)
|
||||||
|
@ -187,7 +186,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
|
||||||
reload()
|
reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func applicationDidBecomeActive(_ notification: Notification) {
|
override func appDidBecomeActive(_ notification: Notification) {
|
||||||
reload()
|
reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@ extension AppDelegate {
|
||||||
conversationVC.inputAccessoryView?.isHidden = true
|
conversationVC.inputAccessoryView?.isHidden = true
|
||||||
conversationVC.inputAccessoryView?.alpha = 0
|
conversationVC.inputAccessoryView?.alpha = 0
|
||||||
presentingVC.present(callVC, animated: true, completion: nil)
|
presentingVC.present(callVC, animated: true, completion: nil)
|
||||||
|
} else if !SSKPreferences.isCallKitSupported {
|
||||||
|
let incomingCallBanner = IncomingCallBanner(for: call)
|
||||||
|
incomingCallBanner.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ class BaseVC : UIViewController {
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
setNeedsStatusBarAppearanceUpdate()
|
setNeedsStatusBarAppearanceUpdate()
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(handleAppModeChangedNotification(_:)), name: .appModeChanged, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(handleAppModeChangedNotification(_:)), name: .appModeChanged, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive(_:)), name: .OWSApplicationDidBecomeActive, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal func ensureWindowBackground() {
|
internal func ensureWindowBackground() {
|
||||||
|
@ -104,6 +105,10 @@ class BaseVC : UIViewController {
|
||||||
deinit {
|
deinit {
|
||||||
NotificationCenter.default.removeObserver(self)
|
NotificationCenter.default.removeObserver(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func appDidBecomeActive(_ notification: Notification) {
|
||||||
|
// To be implemented by child class
|
||||||
|
}
|
||||||
|
|
||||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
|
|
|
@ -37,6 +37,20 @@ public class SSKPreferences: NSObject {
|
||||||
setBool(newValue, key: areCallsEnabledKey)
|
setBool(newValue, key: areCallsEnabledKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
public static var isCallKitSupported: Bool {
|
||||||
|
let userLocale = NSLocale.current
|
||||||
|
|
||||||
|
guard let regionCode = userLocale.regionCode else { return false }
|
||||||
|
|
||||||
|
if regionCode.contains("CN") ||
|
||||||
|
regionCode.contains("CHN") {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: -
|
// MARK: -
|
||||||
|
|
||||||
|
|
|
@ -174,8 +174,9 @@ public enum MessageReceiver {
|
||||||
// • This method was invoked and the received message timestamps table was updated
|
// • This method was invoked and the received message timestamps table was updated
|
||||||
// • Processing wasn't finished
|
// • Processing wasn't finished
|
||||||
// • The user doesn't see the new closed group
|
// • The user doesn't see the new closed group
|
||||||
} else if let message = message as? CallMessage, case .offer = message.kind{
|
} else if let message = message as? CallMessage, message.kind?.description != "preOffer" {
|
||||||
// Allow duplicates for all call offer messages
|
// Allow duplicates for all call messages except preOffer which may generate
|
||||||
|
// a new incoming call
|
||||||
} else {
|
} else {
|
||||||
guard !Set(storage.getReceivedMessageTimestamps(using: transaction)).contains(envelope.timestamp) || isRetry else { throw Error.duplicateMessage }
|
guard !Set(storage.getReceivedMessageTimestamps(using: transaction)).contains(envelope.timestamp) || isRetry else { throw Error.duplicateMessage }
|
||||||
storage.addReceivedMessageTimestamp(envelope.timestamp, using: transaction)
|
storage.addReceivedMessageTimestamp(envelope.timestamp, using: transaction)
|
||||||
|
|
|
@ -203,7 +203,7 @@ public final class NotificationServiceExtension : UNNotificationServiceExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleSuccessForIncomingCall(for callMessage: CallMessage, using transaction: YapDatabaseReadWriteTransaction) {
|
private func handleSuccessForIncomingCall(for callMessage: CallMessage, using transaction: YapDatabaseReadWriteTransaction) {
|
||||||
if #available(iOSApplicationExtension 14.5, *) {
|
if #available(iOSApplicationExtension 14.5, *), SSKPreferences.isCallKitSupported {
|
||||||
if let uuid = callMessage.uuid, let caller = callMessage.sender, let timestamp = callMessage.sentTimestamp {
|
if let uuid = callMessage.uuid, let caller = callMessage.sender, let timestamp = callMessage.sentTimestamp {
|
||||||
let payload: JSON = ["uuid": uuid, "caller": caller, "timestamp": timestamp]
|
let payload: JSON = ["uuid": uuid, "caller": caller, "timestamp": timestamp]
|
||||||
CXProvider.reportNewIncomingVoIPPushPayload(payload) { error in
|
CXProvider.reportNewIncomingVoIPPushPayload(payload) { error in
|
||||||
|
@ -239,8 +239,15 @@ public final class NotificationServiceExtension : UNNotificationServiceExtension
|
||||||
}
|
}
|
||||||
let identifier = self.request?.identifier ?? UUID().uuidString
|
let identifier = self.request?.identifier ?? UUID().uuidString
|
||||||
let request = UNNotificationRequest(identifier: identifier, content: notificationContent, trigger: nil)
|
let request = UNNotificationRequest(identifier: identifier, content: notificationContent, trigger: nil)
|
||||||
|
let semaphore = DispatchSemaphore(value: 0)
|
||||||
|
UNUserNotificationCenter.current().add(request) { error in
|
||||||
|
if let error = error {
|
||||||
|
SNLog("Failed to add notification request due to error:\(error)")
|
||||||
|
}
|
||||||
|
semaphore.signal()
|
||||||
|
}
|
||||||
|
semaphore.wait()
|
||||||
SNLog("Add remote notification request")
|
SNLog("Add remote notification request")
|
||||||
UNUserNotificationCenter.current().add(request)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleSuccess(for content: UNMutableNotificationContent) {
|
private func handleSuccess(for content: UNMutableNotificationContent) {
|
||||||
|
|
Loading…
Reference in a new issue