Fixed an issue where you could answer calls without having the mic permission

pull/1018/head
Morgan Pretty 8 months ago
parent e1aedb36da
commit 597f94a954

@ -902,11 +902,25 @@ extension ConversationVC:
// For call info messages show the "call missed" modal // For call info messages show the "call missed" modal
guard cellViewModel.variant != .infoCall else { guard cellViewModel.variant != .infoCall else {
// If the failure was due to the mic permission being denied then we want to show the permission modal,
// otherwise we want to show the call missed tips modal
guard
let infoMessageData: Data = (cellViewModel.rawBody ?? "").data(using: .utf8),
let messageInfo: CallMessage.MessageInfo = try? JSONDecoder().decode(
CallMessage.MessageInfo.self,
from: infoMessageData
),
messageInfo.state == .permissionDeniedMicrophone
else {
let callMissedTipsModal: CallMissedTipsModal = CallMissedTipsModal(caller: cellViewModel.authorName) let callMissedTipsModal: CallMissedTipsModal = CallMissedTipsModal(caller: cellViewModel.authorName)
present(callMissedTipsModal, animated: true, completion: nil) present(callMissedTipsModal, animated: true, completion: nil)
return return
} }
Permissions.requestMicrophonePermissionIfNeeded(presentingViewController: self)
return
}
// For disappearing messages config update, show the following settings modal // For disappearing messages config update, show the following settings modal
guard cellViewModel.variant != .infoDisappearingMessagesUpdate else { guard cellViewModel.variant != .infoDisappearingMessagesUpdate else {
let messageDisappearingConfig = cellViewModel.messageDisappearingConfiguration() let messageDisappearingConfig = cellViewModel.messageDisappearingConfiguration()

@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit import UIKit
import AVFAudio
import SessionUIKit import SessionUIKit
import SessionMessagingKit import SessionMessagingKit
import SessionUtilitiesKit import SessionUtilitiesKit
@ -147,14 +148,15 @@ final class CallMessageCell: MessageCell {
switch messageInfo.state { switch messageInfo.state {
case .outgoing: return UIImage(named: "CallOutgoing")?.withRenderingMode(.alwaysTemplate) case .outgoing: return UIImage(named: "CallOutgoing")?.withRenderingMode(.alwaysTemplate)
case .incoming: return UIImage(named: "CallIncoming")?.withRenderingMode(.alwaysTemplate) case .incoming: return UIImage(named: "CallIncoming")?.withRenderingMode(.alwaysTemplate)
case .missed, .permissionDenied: return UIImage(named: "CallMissed")?.withRenderingMode(.alwaysTemplate) case .missed, .permissionDenied, .permissionDeniedMicrophone:
return UIImage(named: "CallMissed")?.withRenderingMode(.alwaysTemplate)
default: return nil default: return nil
} }
}() }()
iconImageView.themeTintColor = { iconImageView.themeTintColor = {
switch messageInfo.state { switch messageInfo.state {
case .outgoing, .incoming: return .textPrimary case .outgoing, .incoming: return .textPrimary
case .missed, .permissionDenied: return .danger case .missed, .permissionDenied, .permissionDeniedMicrophone: return .danger
default: return nil default: return nil
} }
}() }()
@ -162,8 +164,13 @@ final class CallMessageCell: MessageCell {
iconImageViewHeightConstraint.constant = (iconImageView.image != nil ? CallMessageCell.iconSize : 0) iconImageViewHeightConstraint.constant = (iconImageView.image != nil ? CallMessageCell.iconSize : 0)
let shouldShowInfoIcon: Bool = ( let shouldShowInfoIcon: Bool = (
(
messageInfo.state == .permissionDenied && messageInfo.state == .permissionDenied &&
!Storage.shared[.areCallsEnabled] !Storage.shared[.areCallsEnabled]
) || (
messageInfo.state == .permissionDeniedMicrophone &&
AVAudioSession.sharedInstance().recordPermission != .granted
)
) )
infoImageViewWidthConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0) infoImageViewWidthConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0)
infoImageViewHeightConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0) infoImageViewHeightConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0)
@ -217,7 +224,15 @@ final class CallMessageCell: MessageCell {
else { return } else { return }
// Should only be tappable if the info icon is visible // Should only be tappable if the info icon is visible
guard messageInfo.state == .permissionDenied && !Storage.shared[.areCallsEnabled] else { return } guard
(
messageInfo.state == .permissionDenied &&
!Storage.shared[.areCallsEnabled]
) || (
messageInfo.state == .permissionDeniedMicrophone &&
AVAudioSession.sharedInstance().recordPermission != .granted
)
else { return }
self.delegate?.handleItemTapped(cellViewModel, cell: self, cellLocation: gestureRecognizer.location(in: self)) self.delegate?.handleItemTapped(cellViewModel, cell: self, cellLocation: gestureRecognizer.location(in: self))
} }

@ -244,7 +244,10 @@ public class NotificationPresenter: NotificationsProtocol {
else { return } else { return }
// Only notify missed calls // Only notify missed calls
guard messageInfo.state == .missed || messageInfo.state == .permissionDenied else { return } switch messageInfo.state {
case .missed, .permissionDenied, .permissionDeniedMicrophone: break
default: return
}
let category = AppNotificationCategory.errorMessage let category = AppNotificationCategory.errorMessage
let previewType: Preferences.NotificationPreviewType = db[.preferencesNotificationPreviewType] let previewType: Preferences.NotificationPreviewType = db[.preferencesNotificationPreviewType]
@ -264,6 +267,11 @@ public class NotificationPresenter: NotificationsProtocol {
format: "modal_call_missed_tips_explanation".localized(), format: "modal_call_missed_tips_explanation".localized(),
senderName senderName
) )
case .permissionDeniedMicrophone:
return String(
format: "call_missed".localized(),
senderName
)
case .missed: case .missed:
return String( return String(
format: "call_missed".localized(), format: "call_missed".localized(),

@ -3,6 +3,7 @@
import UIKit import UIKit
import Photos import Photos
import PhotosUI import PhotosUI
import AVFAudio
import SessionUIKit import SessionUIKit
import SessionUtilitiesKit import SessionUtilitiesKit
import SessionMessagingKit import SessionMessagingKit

@ -226,6 +226,7 @@ public extension CallMessage {
case outgoing case outgoing
case missed case missed
case permissionDenied case permissionDenied
case permissionDeniedMicrophone
case unknown case unknown
} }
@ -253,7 +254,7 @@ public extension CallMessage {
threadContactDisplayName threadContactDisplayName
) )
case .missed, .permissionDenied: case .missed, .permissionDenied, .permissionDeniedMicrophone:
return String( return String(
format: "call_missed".localized(), format: "call_missed".localized(),
threadContactDisplayName threadContactDisplayName

@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation import Foundation
import AVFAudio
import GRDB import GRDB
import WebRTC import WebRTC
import SessionUtilitiesKit import SessionUtilitiesKit
@ -75,8 +76,11 @@ extension MessageReceiver {
return return
} }
guard db[.areCallsEnabled] else { let hasMicrophonePermission: Bool = (AVAudioSession.sharedInstance().recordPermission == .granted)
if let interaction: Interaction = try MessageReceiver.insertCallInfoMessage(db, for: message, state: .permissionDenied, using: dependencies) { guard db[.areCallsEnabled] && hasMicrophonePermission else {
let state: CallMessage.MessageInfo.State = (db[.areCallsEnabled] ? .permissionDeniedMicrophone : .permissionDenied)
if let interaction: Interaction = try MessageReceiver.insertCallInfoMessage(db, for: message, state: state, using: dependencies) {
let thread: SessionThread = try SessionThread let thread: SessionThread = try SessionThread
.fetchOrCreate(db, id: sender, variant: .contact, shouldBeVisible: nil) .fetchOrCreate(db, id: sender, variant: .contact, shouldBeVisible: nil)

@ -146,7 +146,10 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol {
else { return } else { return }
// Only notify missed calls // Only notify missed calls
guard messageInfo.state == .missed || messageInfo.state == .permissionDenied else { return } switch messageInfo.state {
case .missed, .permissionDenied, .permissionDeniedMicrophone: break
default: return
}
let userInfo: [String: Any] = [ let userInfo: [String: Any] = [
NotificationServiceExtension.isFromRemoteKey: true, NotificationServiceExtension.isFromRemoteKey: true,
@ -174,6 +177,12 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol {
senderName senderName
) )
} }
else if messageInfo.state == .permissionDeniedMicrophone {
notificationContent.body = String(
format: "call_missed".localized(),
senderName
)
}
addNotifcationRequest( addNotifcationRequest(
identifier: UUID().uuidString, identifier: UUID().uuidString,

@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation import Foundation
import AVFAudio
import Combine import Combine
import GRDB import GRDB
import CallKit import CallKit
@ -158,14 +159,15 @@ public final class NotificationServiceExtension: UNNotificationServiceExtension
throw NotificationError.ignorableMessage throw NotificationError.ignorableMessage
} }
switch (db[.areCallsEnabled], isCallOngoing) { let hasMicrophonePermission: Bool = (AVAudioSession.sharedInstance().recordPermission == .granted)
switch ((db[.areCallsEnabled] && hasMicrophonePermission), isCallOngoing) {
case (false, _): case (false, _):
if if
let sender: String = callMessage.sender, let sender: String = callMessage.sender,
let interaction: Interaction = try MessageReceiver.insertCallInfoMessage( let interaction: Interaction = try MessageReceiver.insertCallInfoMessage(
db, db,
for: callMessage, for: callMessage,
state: .permissionDenied, state: (db[.areCallsEnabled] ? .permissionDeniedMicrophone : .permissionDenied),
using: dependencies using: dependencies
) )
{ {

Loading…
Cancel
Save