show verification code requested sheet in CVC
This commit is contained in:
parent
b1279de2b7
commit
4497fe6396
@ -58,6 +58,7 @@
|
||||
044D77782E5E6D750048C21A /* PollVoteRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 044D77772E5E6D700048C21A /* PollVoteRecord.swift */; };
|
||||
044D84452E9FDDF00090BA64 /* BackupArchivePollTerminateChatUpdateArchiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 044D84442E9FDDE30090BA64 /* BackupArchivePollTerminateChatUpdateArchiver.swift */; };
|
||||
044D84472E9FEE010090BA64 /* BackupArchivePollArchiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 044D84462E9FEDE20090BA64 /* BackupArchivePollArchiver.swift */; };
|
||||
044EA2232FC0EFAE005B5A3E /* SafetyTipsSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 044EA2222FC0EFA6005B5A3E /* SafetyTipsSheet.swift */; };
|
||||
045B40892EC67510002D3F9A /* PinnedMessageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045B40882EC6750A002D3F9A /* PinnedMessageManager.swift */; };
|
||||
045B408C2EC67C03002D3F9A /* PinnedMessageRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045B408B2EC67BFF002D3F9A /* PinnedMessageRecord.swift */; };
|
||||
045B408E2EC6897B002D3F9A /* PinnedMessageManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045B408D2EC68974002D3F9A /* PinnedMessageManagerTest.swift */; };
|
||||
@ -4204,6 +4205,7 @@
|
||||
044D77772E5E6D700048C21A /* PollVoteRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollVoteRecord.swift; sourceTree = "<group>"; };
|
||||
044D84442E9FDDE30090BA64 /* BackupArchivePollTerminateChatUpdateArchiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupArchivePollTerminateChatUpdateArchiver.swift; sourceTree = "<group>"; };
|
||||
044D84462E9FEDE20090BA64 /* BackupArchivePollArchiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupArchivePollArchiver.swift; sourceTree = "<group>"; };
|
||||
044EA2222FC0EFA6005B5A3E /* SafetyTipsSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafetyTipsSheet.swift; sourceTree = "<group>"; };
|
||||
045B40882EC6750A002D3F9A /* PinnedMessageManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedMessageManager.swift; sourceTree = "<group>"; };
|
||||
045B408B2EC67BFF002D3F9A /* PinnedMessageRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedMessageRecord.swift; sourceTree = "<group>"; };
|
||||
045B408D2EC68974002D3F9A /* PinnedMessageManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedMessageManagerTest.swift; sourceTree = "<group>"; };
|
||||
@ -11311,6 +11313,7 @@
|
||||
0550A5E12C4035170072CC02 /* CLVViewInfo.swift */,
|
||||
34E95C1F269F4F4F004807EC /* CLVViewState.swift */,
|
||||
4C20B2B820CA10DE001BAC90 /* ConversationSearchViewController.swift */,
|
||||
044EA2222FC0EFA6005B5A3E /* SafetyTipsSheet.swift */,
|
||||
1477630A275E20D700D1067E /* ThreadContextualActionProvider.swift */,
|
||||
);
|
||||
path = "Chat List";
|
||||
@ -18710,6 +18713,7 @@
|
||||
348EE28F25B897BF00814FC2 /* ReusableMediaView.swift in Sources */,
|
||||
66A22C0928A18D49007CD4F5 /* RingerSwitch.swift in Sources */,
|
||||
D9E43C2C2CC194140001536E /* RTCIceServerFetcher.swift in Sources */,
|
||||
044EA2232FC0EFAE005B5A3E /* SafetyTipsSheet.swift in Sources */,
|
||||
C1D9B1552B7FA28200D94595 /* SafetyTipsViewController.swift in Sources */,
|
||||
7677E41329F84C2100AC6A75 /* ScreenLockUI.swift in Sources */,
|
||||
667EDE6428F8D6B7001FB487 /* SDAnimatedImage+Duration.swift in Sources */,
|
||||
|
||||
@ -78,6 +78,14 @@ extension ConversationViewController {
|
||||
object: AVAudioSession.sharedInstance(),
|
||||
)
|
||||
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(smsVerificationCodeRequested),
|
||||
name: .smsVerificationCodeRequested,
|
||||
object: nil,
|
||||
)
|
||||
SafetyTipsManager.startObservingDarwinNotifications()
|
||||
|
||||
AppEnvironment.shared.callService.callServiceState.addObserver(self, syncStateImmediately: false)
|
||||
}
|
||||
|
||||
@ -203,6 +211,28 @@ extension ConversationViewController {
|
||||
AssertIsOnMainThread()
|
||||
ensureBottomViewType()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func smsVerificationCodeRequested(_ notification: NSNotification) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
let db = DependenciesBridge.shared.db
|
||||
let safetyTipsManager = SafetyTipsManager()
|
||||
let timestamp: UInt64? = db.read { tx in
|
||||
safetyTipsManager.lastVerificationCodeTimestampMsWithinExpiryTime(transaction: tx)
|
||||
}
|
||||
|
||||
guard let timestamp else { return }
|
||||
let actionSheetController = SafetyTipsSheet.makeSmsCodeRequestedSheet(
|
||||
timestampMs: timestamp,
|
||||
fromViewController: self,
|
||||
)
|
||||
present(actionSheetController, animated: true, completion: {
|
||||
db.write { tx in
|
||||
safetyTipsManager.removeVerificationCodeRequestedTimestampMs(transaction: tx)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@ -61,6 +61,7 @@ class ChatListFYISheetCoordinator {
|
||||
private let keyTransparencyStore: KeyTransparencyStore
|
||||
private let networkManager: NetworkManager
|
||||
private let profileManager: ProfileManager
|
||||
private let safetyTipsManager: SafetyTipsManager
|
||||
|
||||
init(
|
||||
backupExportJobRunner: BackupExportJobRunner,
|
||||
@ -80,6 +81,7 @@ class ChatListFYISheetCoordinator {
|
||||
self.keyTransparencyStore = keyTransparencyStore
|
||||
self.networkManager = networkManager
|
||||
self.profileManager = profileManager
|
||||
self.safetyTipsManager = SafetyTipsManager()
|
||||
}
|
||||
|
||||
func presentIfNecessary(
|
||||
@ -142,8 +144,7 @@ class ChatListFYISheetCoordinator {
|
||||
tx: DBReadTransaction,
|
||||
) -> FYISheet? {
|
||||
|
||||
let safetyTipsKVStore = SafetyTipsManager()
|
||||
guard let timestamp = safetyTipsKVStore.lastVerificationCodeTimestampMsWithinExpiryTime(transaction: tx) else {
|
||||
guard let timestamp = safetyTipsManager.lastVerificationCodeTimestampMsWithinExpiryTime(transaction: tx) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -491,67 +492,13 @@ class ChatListFYISheetCoordinator {
|
||||
smsVerificationCodeSent: FYISheet.SMSVerificationCodeSent,
|
||||
from chatListViewController: ChatListViewController,
|
||||
) async {
|
||||
let timestampString = DateUtil.formatMessageTimestampForCVC(
|
||||
smsVerificationCodeSent.timestampMs,
|
||||
shouldUseLongFormat: true,
|
||||
let actionSheetController = SafetyTipsSheet.makeSmsCodeRequestedSheet(
|
||||
timestampMs: smsVerificationCodeSent.timestampMs,
|
||||
fromViewController: chatListViewController,
|
||||
)
|
||||
let bodyPartOne = OWSLocalizedString(
|
||||
"VERIFICATION_CODE_REQUESTED_HERO_BODY_FIRST",
|
||||
comment: "First part of body for a hero sheet informing the user a verification code was requested. {{ Embeds time the code was requested }}",
|
||||
)
|
||||
let bodyPartTwo = OWSLocalizedString(
|
||||
"VERIFICATION_CODE_REQUESTED_HERO_BODY_SECOND",
|
||||
comment: "Second part of body for a hero sheet informing the user a verification code was requested.",
|
||||
)
|
||||
let body: NSAttributedString = .composed(of: [
|
||||
bodyPartOne.styled(
|
||||
with: .font(.dynamicTypeHeadline),
|
||||
.color(UIColor.Signal.label),
|
||||
.paragraphSpacingAfter(4.0),
|
||||
),
|
||||
"\n",
|
||||
timestampString.styled(
|
||||
with: .font(.dynamicTypeBody),
|
||||
.color(UIColor.Signal.label),
|
||||
),
|
||||
"\n",
|
||||
bodyPartTwo.styled(
|
||||
with: .font(.dynamicTypeBody),
|
||||
.color(UIColor.Signal.label),
|
||||
.paragraphSpacingBefore(12.0),
|
||||
),
|
||||
])
|
||||
|
||||
let actionSheet = ActionSheetController(
|
||||
message: body,
|
||||
image: UIImage(resource: .verificationcodeAlert96),
|
||||
)
|
||||
actionSheet.addAction(ActionSheetAction(
|
||||
title: OWSLocalizedString(
|
||||
"SAFETY_TIPS_BUTTON_ACTION_TITLE",
|
||||
comment: "Title for Safety Tips button in thread details.",
|
||||
),
|
||||
handler: { [weak chatListViewController] _ in
|
||||
guard let chatListViewController else { return }
|
||||
let safetyTipsVC = SafetyTipsViewController(
|
||||
primaryButton: SafetyTipsViewController.Button(
|
||||
title: OWSLocalizedString(
|
||||
"SETTINGS_ACCOUNT_BUTTON",
|
||||
comment: "Label for button in Safety Tips to go to 'account' page in settings.",
|
||||
),
|
||||
action: { [weak chatListViewController] in
|
||||
chatListViewController?.showAppSettings(mode: .accountSettings)
|
||||
},
|
||||
),
|
||||
)
|
||||
chatListViewController.present(safetyTipsVC, animated: true)
|
||||
},
|
||||
))
|
||||
actionSheet.addAction(.ok)
|
||||
chatListViewController.present(actionSheet, animated: true, completion: { [self] in
|
||||
let kvStore = SafetyTipsManager()
|
||||
chatListViewController.present(actionSheetController, animated: true, completion: { [self] in
|
||||
db.write { tx in
|
||||
kvStore.removeVerificationCodeRequestedTimestampMs(transaction: tx)
|
||||
safetyTipsManager.removeVerificationCodeRequestedTimestampMs(transaction: tx)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
//
|
||||
// Copyright 2026 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import SignalServiceKit
|
||||
import SignalUI
|
||||
|
||||
enum SafetyTipsSheet {
|
||||
static func makeSmsCodeRequestedSheet(timestampMs: UInt64, fromViewController: UIViewController) -> ActionSheetController {
|
||||
let timestampString = DateUtil.formatMessageTimestampForCVC(
|
||||
timestampMs,
|
||||
shouldUseLongFormat: true,
|
||||
)
|
||||
let bodyPartOne = OWSLocalizedString(
|
||||
"VERIFICATION_CODE_REQUESTED_HERO_BODY_FIRST",
|
||||
comment: "First part of body for a hero sheet informing the user a verification code was requested. {{ Embeds time the code was requested }}",
|
||||
)
|
||||
let bodyPartTwo = OWSLocalizedString(
|
||||
"VERIFICATION_CODE_REQUESTED_HERO_BODY_SECOND",
|
||||
comment: "Second part of body for a hero sheet informing the user a verification code was requested.",
|
||||
)
|
||||
let body: NSAttributedString = .composed(of: [
|
||||
bodyPartOne.styled(
|
||||
with: .font(.dynamicTypeHeadline),
|
||||
.color(UIColor.Signal.label),
|
||||
.paragraphSpacingAfter(4.0),
|
||||
),
|
||||
"\n",
|
||||
timestampString.styled(
|
||||
with: .font(.dynamicTypeBody),
|
||||
.color(UIColor.Signal.label),
|
||||
),
|
||||
"\n",
|
||||
bodyPartTwo.styled(
|
||||
with: .font(.dynamicTypeBody),
|
||||
.color(UIColor.Signal.label),
|
||||
.paragraphSpacingBefore(12.0),
|
||||
),
|
||||
])
|
||||
|
||||
let actionSheet = ActionSheetController(
|
||||
message: body,
|
||||
image: UIImage(resource: .verificationcodeAlert96),
|
||||
)
|
||||
actionSheet.addAction(ActionSheetAction(
|
||||
title: OWSLocalizedString(
|
||||
"SAFETY_TIPS_BUTTON_ACTION_TITLE",
|
||||
comment: "Title for Safety Tips button in thread details.",
|
||||
),
|
||||
handler: { [weak fromViewController] _ in
|
||||
let safetyTipsVC = SafetyTipsViewController(
|
||||
primaryButton: SafetyTipsViewController.Button(
|
||||
title: OWSLocalizedString(
|
||||
"SETTINGS_ACCOUNT_BUTTON",
|
||||
comment: "Label for button in Safety Tips to go to 'account' page in settings.",
|
||||
),
|
||||
action: {
|
||||
SignalApp.shared.showAppSettings(mode: .accountSettings)
|
||||
},
|
||||
),
|
||||
)
|
||||
fromViewController?.present(safetyTipsVC, animated: true)
|
||||
},
|
||||
))
|
||||
actionSheet.addAction(.ok)
|
||||
return actionSheet
|
||||
}
|
||||
}
|
||||
@ -146,6 +146,11 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
if let timestamp = verificationCodeRequestTimestampMs(userInfo: request.content.userInfo) {
|
||||
await SSKEnvironment.shared.databaseStorageRef.awaitableWrite { transaction in
|
||||
guard DependenciesBridge.shared.tsAccountManager.registrationState(tx: transaction).isPrimaryDevice == true else {
|
||||
Logger.info("Received verification code push on non-primary device; ignoring.")
|
||||
return
|
||||
}
|
||||
|
||||
let kvStore = SafetyTipsManager()
|
||||
kvStore.setLastVerificationCodeRequestedTimestampMs(value: timestamp, transaction: transaction)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user