Fix verification persistence on iOS when app backgrounds (#822)

* Fix verification persistence on iOS when app backgrounds (#785)

Verification status was not being saved when the iOS app entered background
state, causing verified contacts to lose their verification status after the
app was closed. This happened because iOS can terminate backgrounded apps
without calling applicationWillTerminate.

Changes:
- Add saveIdentityState() method to force-save identity data without stopping services
- Call saveIdentityState() when iOS app enters background state
- Refactor applicationWillTerminate() to use new method
- Fix selector name typo (appWillTerminate -> applicationWillTerminate)

The verification data is now properly persisted to encrypted keychain storage
whenever the app backgrounds, ensuring verification status persists across
app launches.

Fixes #785

* Save identity state during verification events

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
jack
2025-10-28 19:19:00 +01:00
committed by GitHub
co-authored by jack
parent 01256f3041
commit 96c78ef5a2
2 changed files with 21 additions and 19 deletions
+17 -19
View File
@@ -720,7 +720,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
)
NotificationCenter.default.addObserver(
self,
selector: #selector(appWillTerminate),
selector: #selector(applicationWillTerminate),
name: NSApplication.willTerminateNotification,
object: nil
)
@@ -776,7 +776,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
)
NotificationCenter.default.addObserver(
self,
selector: #selector(appWillTerminate),
selector: #selector(applicationWillTerminate),
name: UIApplication.willTerminateNotification,
object: nil
)
@@ -3251,24 +3251,21 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
// No-op; avoid forcing synchronize on resign
}
/// Save identity state without stopping services (for backgrounding)
func saveIdentityState() {
// Force save any pending identity changes (verifications, favorites, etc)
identityManager.forceSave()
// Verify identity key is still there
_ = keychain.verifyIdentityKeyExists()
}
@objc func applicationWillTerminate() {
// Send leave message to all peers
meshService.stopServices()
// Force save any pending identity changes (verifications, favorites, etc)
identityManager.forceSave()
// Verify identity key is still there
_ = keychain.verifyIdentityKeyExists()
// No need to force synchronize here
// Verify identity key after save
_ = keychain.verifyIdentityKeyExists()
}
@objc private func appWillTerminate() {
// No need to force synchronize here
// Save identity state
saveIdentityState()
}
@MainActor
@@ -4464,6 +4461,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
// Update secure storage with verified status
identityManager.setVerified(fingerprint: fingerprint, verified: true)
saveIdentityState()
// Update local set for UI
verifiedFingerprints.insert(fingerprint)
@@ -4476,7 +4474,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
func unverifyFingerprint(for peerID: PeerID) {
guard let fingerprint = getFingerprint(for: peerID) else { return }
identityManager.setVerified(fingerprint: fingerprint, verified: false)
identityManager.forceSave()
saveIdentityState()
verifiedFingerprints.remove(fingerprint)
updateEncryptionStatus(for: peerID)
}
@@ -4685,7 +4683,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
let short = fp.prefix(8)
SecureLogger.info("🔐 Marking verified fingerprint: \(short)", category: .security)
identityManager.setVerified(fingerprint: fp, verified: true)
identityManager.forceSave()
saveIdentityState()
verifiedFingerprints.insert(fp)
let name = unifiedPeerService.getPeer(by: peerID)?.nickname ?? resolveNickname(for: peerID)
NotificationService.shared.sendLocalNotification(