mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-25 18:34:24 +00:00
ios: reverted some changes related to lockScreen (#2011)
* Revert "ios: CallKit enhancements (#2010)" This reverts commit840df89ca6. * Revert "ios: CallKit integrated with app lock and screen protect (#2007)" This reverts commit0404b020e6. * ios: reverted some changes related to lockScreen * undo delay * better support of appLock + call * refactor * refactor 2 * refactor 3 * refactor 4 --------- Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
840df89ca6
commit
2643ea9066
@@ -94,16 +94,6 @@ class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
return configuration
|
||||
}
|
||||
|
||||
func applicationProtectedDataWillBecomeUnavailable(_ application: UIApplication) {
|
||||
logger.debug("AppDelegate: will lock screen")
|
||||
ChatModel.shared.onLockScreenCurrently = true
|
||||
}
|
||||
|
||||
func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
|
||||
logger.debug("AppDelegate: did unlock screen")
|
||||
ChatModel.shared.onLockScreenCurrently = false
|
||||
}
|
||||
|
||||
private func receiveMessages(_ completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
||||
let complete = BGManager.shared.completionHandler {
|
||||
logger.debug("AppDelegate: completed BGManager.receiveMessages")
|
||||
|
||||
@@ -27,48 +27,64 @@ struct ContentView: View {
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
contentView()
|
||||
if chatModel.showCallView, let call = chatModel.activeCall {
|
||||
ActiveCallView(call: call, canConnectCall: $canConnectCall)
|
||||
}
|
||||
if prefPerformLA && userAuthorized != true {
|
||||
Rectangle().fill(colorScheme == .dark ? .black : .white)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.onTapGesture(perform: {})
|
||||
Button(action: runAuthenticate) { Label("Unlock", systemImage: "lock") }
|
||||
} else if let status = chatModel.chatDbStatus, status != .ok {
|
||||
DatabaseErrorView(status: status)
|
||||
} else if !chatModel.v3DBMigration.startChat {
|
||||
MigrateToAppGroupView()
|
||||
} else if let step = chatModel.onboardingStage, (!chatModel.showCallView || chatModel.activeCall == nil) {
|
||||
if case .onboardingComplete = step,
|
||||
chatModel.currentUser != nil {
|
||||
mainView()
|
||||
} else {
|
||||
OnboardingView(onboarding: step)
|
||||
}
|
||||
callView(call)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
logger.debug("ContentView: canConnectCall \(canConnectCall), doAuthenticate \(doAuthenticate)")
|
||||
if doAuthenticate { runAuthenticate() }
|
||||
if prefPerformLA { requestNtfAuthorization() }
|
||||
initAuthenticate()
|
||||
}
|
||||
.onChange(of: doAuthenticate) { _ in
|
||||
initAuthenticate()
|
||||
}
|
||||
.onChange(of: doAuthenticate) { _ in if doAuthenticate { runAuthenticate() } }
|
||||
.alert(isPresented: $alertManager.presentAlert) { alertManager.alertView! }
|
||||
}
|
||||
|
||||
@ViewBuilder private func contentView() -> some View {
|
||||
if prefPerformLA && userAuthorized != true {
|
||||
lockButton()
|
||||
} else if let status = chatModel.chatDbStatus, status != .ok {
|
||||
DatabaseErrorView(status: status)
|
||||
} else if !chatModel.v3DBMigration.startChat {
|
||||
MigrateToAppGroupView()
|
||||
} else if let step = chatModel.onboardingStage {
|
||||
if case .onboardingComplete = step,
|
||||
chatModel.currentUser != nil {
|
||||
mainView()
|
||||
} else {
|
||||
OnboardingView(onboarding: step)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func callView(_ call: Call) -> some View {
|
||||
if CallController.useCallKit() {
|
||||
ActiveCallView(call: call, canConnectCall: Binding.constant(true))
|
||||
.onDisappear {
|
||||
if userAuthorized == false && doAuthenticate { runAuthenticate() }
|
||||
}
|
||||
} else {
|
||||
ActiveCallView(call: call, canConnectCall: $canConnectCall)
|
||||
if prefPerformLA && userAuthorized != true {
|
||||
Rectangle()
|
||||
.fill(colorScheme == .dark ? .black : .white)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
lockButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func lockButton() -> some View {
|
||||
Button(action: runAuthenticate) { Label("Unlock", systemImage: "lock") }
|
||||
}
|
||||
|
||||
private func mainView() -> some View {
|
||||
ZStack(alignment: .top) {
|
||||
ChatListView().privacySensitive(protectScreen)
|
||||
.onAppear {
|
||||
NtfManager.shared.requestAuthorization(
|
||||
onDeny: {
|
||||
if (!notificationAlertShown) {
|
||||
notificationAlertShown = true
|
||||
alertManager.showAlert(notificationAlert())
|
||||
}
|
||||
},
|
||||
onAuthorized: { notificationAlertShown = false }
|
||||
)
|
||||
if !prefPerformLA { requestNtfAuthorization() }
|
||||
// Local Authentication notice is to be shown on next start after onboarding is complete
|
||||
if (!prefLANoticeShown && prefShowLANotice && !chatModel.chats.isEmpty) {
|
||||
prefLANoticeShown = true
|
||||
@@ -93,24 +109,29 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
// private func processUserActivity(_ activity: NSUserActivity) {
|
||||
// let intent = activity.interaction?.intent
|
||||
// if let contacts = (intent as? INStartCallIntent)?.contacts {
|
||||
// callToContact(contacts, .audio)
|
||||
// } else if let contacts = (intent as? INStartAudioCallIntent)?.contacts {
|
||||
// callToContact(contacts, .audio)
|
||||
// } else if let contacts = (intent as? INStartVideoCallIntent)?.contacts {
|
||||
// callToContact(contacts, .video)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private func callToContact(_ contacts: [INPerson], _ mediaType: CallMediaType) {
|
||||
// if let contactId = contacts.first?.personHandle?.value,
|
||||
// let chatInfo = chatModel.chats.first(where: { $0.id == contactId })?.chatInfo,
|
||||
// case let .direct(contact) = chatInfo {
|
||||
// CallController.shared.startCall(contact, mediaType)
|
||||
// let callToContact = { (contactId: ChatId?, mediaType: CallMediaType) in
|
||||
// if let chatInfo = chatModel.chats.first(where: { $0.id == contactId })?.chatInfo,
|
||||
// case let .direct(contact) = chatInfo {
|
||||
// CallController.shared.startCall(contact, mediaType)
|
||||
// }
|
||||
// }
|
||||
// if let intent = activity.interaction?.intent as? INStartCallIntent {
|
||||
// callToContact(intent.contacts?.first?.personHandle?.value, .audio)
|
||||
// } else if let intent = activity.interaction?.intent as? INStartAudioCallIntent {
|
||||
// callToContact(intent.contacts?.first?.personHandle?.value, .audio)
|
||||
// } else if let intent = activity.interaction?.intent as? INStartVideoCallIntent {
|
||||
// callToContact(intent.contacts?.first?.personHandle?.value, .video)
|
||||
// }
|
||||
// }
|
||||
|
||||
private func initAuthenticate() {
|
||||
if CallController.useCallKit() && chatModel.showCallView && chatModel.activeCall != nil {
|
||||
userAuthorized = false
|
||||
} else if doAuthenticate {
|
||||
runAuthenticate()
|
||||
}
|
||||
}
|
||||
|
||||
private func runAuthenticate() {
|
||||
if !prefPerformLA {
|
||||
userAuthorized = true
|
||||
@@ -134,13 +155,25 @@ struct ContentView: View {
|
||||
break
|
||||
case .unavailable:
|
||||
userAuthorized = true
|
||||
canConnectCall = true
|
||||
prefPerformLA = false
|
||||
canConnectCall = true
|
||||
AlertManager.shared.showAlert(laUnavailableTurningOffAlert())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func requestNtfAuthorization() {
|
||||
NtfManager.shared.requestAuthorization(
|
||||
onDeny: {
|
||||
if (!notificationAlertShown) {
|
||||
notificationAlertShown = true
|
||||
alertManager.showAlert(notificationAlert())
|
||||
}
|
||||
},
|
||||
onAuthorized: { notificationAlertShown = false }
|
||||
)
|
||||
}
|
||||
|
||||
func laNoticeAlert() -> Alert {
|
||||
Alert(
|
||||
title: Text("SimpleX Lock"),
|
||||
|
||||
@@ -59,9 +59,6 @@ final class ChatModel: ObservableObject {
|
||||
@Published var draft: ComposeState?
|
||||
@Published var draftChatId: String?
|
||||
|
||||
var sceneWasActiveAtLeastOnce = false
|
||||
var onLockScreenCurrently = false
|
||||
|
||||
var messageDelivery: Dictionary<Int64, () -> Void> = [:]
|
||||
|
||||
var filesToDelete: [String] = []
|
||||
|
||||
@@ -20,8 +20,8 @@ struct SimpleXApp: App {
|
||||
@AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false
|
||||
@State private var userAuthorized: Bool?
|
||||
@State private var doAuthenticate = false
|
||||
@State private var canConnectCall = false
|
||||
@State private var enteredBackground: TimeInterval? = nil
|
||||
@State private var canConnectCall = false
|
||||
@State private var lastSuccessfulUnlock: TimeInterval? = nil
|
||||
|
||||
init() {
|
||||
@@ -66,7 +66,6 @@ struct SimpleXApp: App {
|
||||
NtfManager.shared.setNtfBadgeCount(chatModel.totalUnreadCountForAllUsers())
|
||||
case .active:
|
||||
CallController.shared.onEndCall = nil
|
||||
chatModel.sceneWasActiveAtLeastOnce = true
|
||||
let appState = appStateGroupDefault.get()
|
||||
startChatAndActivate()
|
||||
if appState.inactive && chatModel.chatRunning == true {
|
||||
@@ -116,7 +115,6 @@ struct SimpleXApp: App {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func unlockedRecently() -> Bool {
|
||||
if let lastSuccessfulUnlock = lastSuccessfulUnlock {
|
||||
return ProcessInfo.processInfo.systemUptime - lastSuccessfulUnlock < 2
|
||||
|
||||
@@ -12,12 +12,12 @@ import SimpleXChat
|
||||
|
||||
struct ActiveCallView: View {
|
||||
@EnvironmentObject var m: ChatModel
|
||||
@Environment(\.scenePhase) var scenePhase
|
||||
@ObservedObject var call: Call
|
||||
@Binding var canConnectCall: Bool
|
||||
@Environment(\.scenePhase) var scenePhase
|
||||
@State private var client: WebRTCClient? = nil
|
||||
@State private var activeCall: WebRTCClient.Call? = nil
|
||||
@State private var localRendererAspectRatio: CGFloat? = nil
|
||||
@Binding var canConnectCall: Bool
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .bottom) {
|
||||
@@ -38,7 +38,7 @@ struct ActiveCallView: View {
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
logger.debug("ActiveCallView: appear client is nil \(client == nil), canConnectCall \(canConnectCall, privacy: .public), scenePhase \(String(describing: scenePhase), privacy: .public)")
|
||||
logger.debug("ActiveCallView: appear client is nil \(client == nil), scenePhase \(String(describing: scenePhase), privacy: .public), canConnectCall \(canConnectCall)")
|
||||
createWebRTCClient()
|
||||
}
|
||||
.onChange(of: canConnectCall) { _ in
|
||||
@@ -55,22 +55,8 @@ struct ActiveCallView: View {
|
||||
}
|
||||
|
||||
private func createWebRTCClient() {
|
||||
if client == nil && (canConnectCall || m.onLockScreenCurrently) {
|
||||
createWebRTCClientWithoutWait()
|
||||
} else if (!m.sceneWasActiveAtLeastOnce) {
|
||||
// This code waits a second until it recheck `sceneWasActiveAtLeastOnce`.
|
||||
// It helps to know whether a call from lockscreen or not.
|
||||
// After the second `sceneWasActiveAtLeastOnce` will still be false when the call from lockscreen
|
||||
Task {
|
||||
try? await Task.sleep(nanoseconds: 1_000_000_000)
|
||||
createWebRTCClientWithoutWait()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func createWebRTCClientWithoutWait() {
|
||||
if client == nil && (canConnectCall || !m.sceneWasActiveAtLeastOnce || m.onLockScreenCurrently) {
|
||||
client = WebRTCClient($activeCall, { msg in await MainActor.run {processRtcMessage(msg: msg)} }, $localRendererAspectRatio)
|
||||
if client == nil && canConnectCall {
|
||||
client = WebRTCClient($activeCall, { msg in await MainActor.run { processRtcMessage(msg: msg) } }, $localRendererAspectRatio)
|
||||
sendCommandToClient()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
|
||||
print("received", #function)
|
||||
logger.debug("CallController: activating audioSession and audio in WebRTCClient")
|
||||
RTCAudioSession.sharedInstance().audioSessionDidActivate(audioSession)
|
||||
RTCAudioSession.sharedInstance().isAudioEnabled = true
|
||||
@@ -113,7 +112,6 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
||||
}
|
||||
|
||||
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
|
||||
print("received", #function)
|
||||
logger.debug("CallController: deactivating audioSession and audio in WebRTCClient")
|
||||
RTCAudioSession.sharedInstance().audioSessionDidDeactivate(audioSession)
|
||||
RTCAudioSession.sharedInstance().isAudioEnabled = false
|
||||
@@ -265,7 +263,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
||||
}
|
||||
|
||||
func endCall(callUUID: UUID) {
|
||||
logger.debug("CallController: ending the call")
|
||||
logger.debug("CallController: ending the call with UUID \(callUUID.uuidString)")
|
||||
if CallController.useCallKit() {
|
||||
requestTransaction(with: CXEndCallAction(call: callUUID))
|
||||
} else {
|
||||
@@ -280,7 +278,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
||||
}
|
||||
|
||||
func endCall(invitation: RcvCallInvitation) {
|
||||
logger.debug("CallController: ending the call")
|
||||
logger.debug("CallController: ending the call with invitation")
|
||||
callManager.endCall(invitation: invitation) {
|
||||
if invitation.contact.id == self.activeCallInvitation?.contact.id {
|
||||
DispatchQueue.main.async {
|
||||
@@ -291,7 +289,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse
|
||||
}
|
||||
|
||||
func endCall(call: Call, completed: @escaping () -> Void) {
|
||||
logger.debug("CallController: ending the call")
|
||||
logger.debug("CallController: ending the call with call instance")
|
||||
callManager.endCall(call: call, completed: completed)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user