From c2d2629316ffa56cbccc8dc1793fa2e2759c8d3a Mon Sep 17 00:00:00 2001 From: Marissa Le Coz <129999395+marissa-signal@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:29:49 -0500 Subject: [PATCH] [Quick Restore] Add new QR code screen for registration --- Signal.xcodeproj/project.pbxproj | 32 +++- Signal/Registration/RegistrationStep.swift | 2 + .../RegistrationNavigationController.swift | 20 ++- ...tionQuickRestoreQRCodeViewController.swift | 163 ++++++++++++++++++ Signal/Symbols.xcassets/device/Contents.json | 6 + .../device-phone.imageset/Contents.json | 15 ++ .../device-phone.imageset/device-phone.pdf | Bin 0 -> 2542 bytes ...rnameLinkPresentQRCodeViewController.swift | 8 +- ...eLinkQRCodeColorPickerViewController.swift | 16 +- ...ift => SignalBrandedQRCodeGenerator.swift} | 4 +- .../translations/en.lproj/Localizable.strings | 12 ++ .../MessageBackupAccountDataArchiver.swift | 4 +- .../Usernames/MockLocalUsernameManager.swift | 4 +- .../SignalBrandedQRCodes+QRCodeColor.swift} | 6 +- .../QRCodes/SignalBrandedQRCodes.swift | 7 + .../StorageServiceProto+Sync.swift | 4 +- .../Usernames/LocalUsernameManager.swift | 12 +- .../Usernames/LocalUsernameManagerTests.swift | 2 +- 18 files changed, 278 insertions(+), 39 deletions(-) create mode 100644 Signal/Registration/UserInterface/RegistrationQuickRestoreQRCodeViewController.swift create mode 100644 Signal/Symbols.xcassets/device/Contents.json create mode 100644 Signal/Symbols.xcassets/device/device-phone.imageset/Contents.json create mode 100644 Signal/Symbols.xcassets/device/device-phone.imageset/device-phone.pdf rename Signal/src/QRCodes/{UsernameLinkQRCodeGenerator.swift => SignalBrandedQRCodeGenerator.swift} (98%) rename SignalServiceKit/{Usernames/Usernames+QRCodeColor.swift => QRCodes/SignalBrandedQRCodes+QRCodeColor.swift} (94%) create mode 100644 SignalServiceKit/QRCodes/SignalBrandedQRCodes.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 6ad15252ea..8a1d7b7d0b 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -2405,7 +2405,7 @@ D93830742A703969006CDCDE /* LocalUsernameManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93830732A703968006CDCDE /* LocalUsernameManager.swift */; }; D938307A2A704123006CDCDE /* UsernameLinkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93830792A704123006CDCDE /* UsernameLinkManager.swift */; }; D938307C2A704338006CDCDE /* LocalUsernameManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93830752A70396E006CDCDE /* LocalUsernameManagerTests.swift */; }; - D938307E2A70441D006CDCDE /* Usernames+QRCodeColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D938307D2A70441D006CDCDE /* Usernames+QRCodeColor.swift */; }; + D938307E2A70441D006CDCDE /* SignalBrandedQRCodes+QRCodeColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D938307D2A70441D006CDCDE /* SignalBrandedQRCodes+QRCodeColor.swift */; }; D93830802A705D64006CDCDE /* UsernameLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = D938307F2A705D64006CDCDE /* UsernameLogger.swift */; }; D93830812A7065C7006CDCDE /* UsernameValidationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C182BEF529ACFCB200E8E1E2 /* UsernameValidationManagerTests.swift */; }; D93830832A708E95006CDCDE /* UsernameChangeDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93830822A708E95006CDCDE /* UsernameChangeDelegate.swift */; }; @@ -2567,7 +2567,7 @@ D9DCFDA52A37D12100C73C0B /* UsernameLinkPresentQRCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9DCFDA42A37D12100C73C0B /* UsernameLinkPresentQRCodeViewController.swift */; }; D9DCFDAB2A39402F00C73C0B /* SettingsHeaderButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9DCFDAA2A39402F00C73C0B /* SettingsHeaderButton.swift */; }; D9DCFDAE2A3BB25200C73C0B /* QRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9DCFDAD2A3BB25200C73C0B /* QRCodeGenerator.swift */; }; - D9DCFDB02A3BC4A400C73C0B /* UsernameLinkQRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9DCFDAF2A3BC4A400C73C0B /* UsernameLinkQRCodeGenerator.swift */; }; + D9DCFDB02A3BC4A400C73C0B /* SignalBrandedQRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9DCFDAF2A3BC4A400C73C0B /* SignalBrandedQRCodeGenerator.swift */; }; D9DCFDB22A3BDAB000C73C0B /* ExportableQRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9DCFDB12A3BDAB000C73C0B /* ExportableQRCodeGenerator.swift */; }; D9DCFDB42A3BDC7400C73C0B /* BasicDisplayQRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9DCFDB32A3BDC7400C73C0B /* BasicDisplayQRCodeGenerator.swift */; }; D9E335A929933B1A00825677 /* Usernames+HashedUsername.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9E335A829933B1A00825677 /* Usernames+HashedUsername.swift */; }; @@ -2688,6 +2688,7 @@ E1368CBE18A1C36B00109378 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9EB5ABC1884C002007CBB57 /* MessageUI.framework */; }; E1447D8F2CCACFFD004D8FA2 /* MessageBackupCallLinkRecipientArchiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1447D8E2CCACFFA004D8FA2 /* MessageBackupCallLinkRecipientArchiver.swift */; }; E14EDF6E2A71AFDF00F0FD7C /* RecipientContextMenuHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14EDF6D2A71AFDF00F0FD7C /* RecipientContextMenuHelper.swift */; }; + E15066C32CED49C800F6F9AF /* RegistrationQuickRestoreQRCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E15066C22CED498600F6F9AF /* RegistrationQuickRestoreQRCodeViewController.swift */; }; E16026042CE7D2490032EA77 /* chat_item_group_change_chat_update_13.binproto in Resources */ = {isa = PBXBuildFile; fileRef = E16025DA2CE7D2490032EA77 /* chat_item_group_change_chat_update_13.binproto */; }; E16026052CE7D2490032EA77 /* chat_item_group_change_chat_update_33.txtproto in Resources */ = {isa = PBXBuildFile; fileRef = E16026032CE7D2490032EA77 /* chat_item_group_change_chat_update_33.txtproto */; }; E16026062CE7D2490032EA77 /* chat_item_group_change_chat_update_15.binproto in Resources */ = {isa = PBXBuildFile; fileRef = E16025DE2CE7D2490032EA77 /* chat_item_group_change_chat_update_15.binproto */; }; @@ -2814,6 +2815,7 @@ E19B35492CD2E8C40078A678 /* ad_hoc_call_02.binproto in Resources */ = {isa = PBXBuildFile; fileRef = E19B35442CD2E8C40078A678 /* ad_hoc_call_02.binproto */; }; E19B354A2CD2E8C40078A678 /* ad_hoc_call_00.binproto in Resources */ = {isa = PBXBuildFile; fileRef = E19B35402CD2E8C40078A678 /* ad_hoc_call_00.binproto */; }; E19B354B2CD2E8C40078A678 /* ad_hoc_call_01.binproto in Resources */ = {isa = PBXBuildFile; fileRef = E19B35422CD2E8C40078A678 /* ad_hoc_call_01.binproto */; }; + E19C3D942CF6B36500F2C496 /* SignalBrandedQRCodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19C3D932CF6B35A00F2C496 /* SignalBrandedQRCodes.swift */; }; E1A090382A4B909B00F2BE8B /* RecipientHidingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A090372A4B909B00F2BE8B /* RecipientHidingManager.swift */; }; E1B32F842CA6162A002141F4 /* LinkPreviewCallLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CFAAA22C9DD2B1003145C3 /* LinkPreviewCallLink.swift */; }; E1B628DA2CCC59E600C4DC7F /* chat_item_view_once_11.binproto in Resources */ = {isa = PBXBuildFile; fileRef = E1B628D22CCC59E600C4DC7F /* chat_item_view_once_11.binproto */; }; @@ -6157,7 +6159,7 @@ D93830752A70396E006CDCDE /* LocalUsernameManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalUsernameManagerTests.swift; sourceTree = ""; }; D93830772A70399C006CDCDE /* ConsumableMockPromise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsumableMockPromise.swift; sourceTree = ""; }; D93830792A704123006CDCDE /* UsernameLinkManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UsernameLinkManager.swift; sourceTree = ""; }; - D938307D2A70441D006CDCDE /* Usernames+QRCodeColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Usernames+QRCodeColor.swift"; sourceTree = ""; }; + D938307D2A70441D006CDCDE /* SignalBrandedQRCodes+QRCodeColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SignalBrandedQRCodes+QRCodeColor.swift"; sourceTree = ""; }; D938307F2A705D64006CDCDE /* UsernameLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UsernameLogger.swift; sourceTree = ""; }; D93830822A708E95006CDCDE /* UsernameChangeDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsernameChangeDelegate.swift; sourceTree = ""; }; D93830842A784210006CDCDE /* UsernameApiClientImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsernameApiClientImpl.swift; sourceTree = ""; }; @@ -6338,7 +6340,7 @@ D9DCFDA42A37D12100C73C0B /* UsernameLinkPresentQRCodeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsernameLinkPresentQRCodeViewController.swift; sourceTree = ""; }; D9DCFDAA2A39402F00C73C0B /* SettingsHeaderButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsHeaderButton.swift; sourceTree = ""; }; D9DCFDAD2A3BB25200C73C0B /* QRCodeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeGenerator.swift; sourceTree = ""; }; - D9DCFDAF2A3BC4A400C73C0B /* UsernameLinkQRCodeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsernameLinkQRCodeGenerator.swift; sourceTree = ""; }; + D9DCFDAF2A3BC4A400C73C0B /* SignalBrandedQRCodeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalBrandedQRCodeGenerator.swift; sourceTree = ""; }; D9DCFDB12A3BDAB000C73C0B /* ExportableQRCodeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportableQRCodeGenerator.swift; sourceTree = ""; }; D9DCFDB32A3BDC7400C73C0B /* BasicDisplayQRCodeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicDisplayQRCodeGenerator.swift; sourceTree = ""; }; D9E335A829933B1A00825677 /* Usernames+HashedUsername.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Usernames+HashedUsername.swift"; sourceTree = ""; }; @@ -6458,6 +6460,7 @@ D9FD2DF42CD959B000099627 /* StorageServiceRecordIkmCapabilityStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageServiceRecordIkmCapabilityStore.swift; sourceTree = ""; }; E1447D8E2CCACFFA004D8FA2 /* MessageBackupCallLinkRecipientArchiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageBackupCallLinkRecipientArchiver.swift; sourceTree = ""; }; E14EDF6D2A71AFDF00F0FD7C /* RecipientContextMenuHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientContextMenuHelper.swift; sourceTree = ""; }; + E15066C22CED498600F6F9AF /* RegistrationQuickRestoreQRCodeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationQuickRestoreQRCodeViewController.swift; sourceTree = ""; }; E16025C02CE7D2490032EA77 /* chat_item_group_change_chat_update_00.binproto */ = {isa = PBXFileReference; lastKnownFileType = file; path = chat_item_group_change_chat_update_00.binproto; sourceTree = ""; }; E16025C12CE7D2490032EA77 /* chat_item_group_change_chat_update_00.txtproto */ = {isa = PBXFileReference; lastKnownFileType = text; path = chat_item_group_change_chat_update_00.txtproto; sourceTree = ""; }; E16025C22CE7D2490032EA77 /* chat_item_group_change_chat_update_01.binproto */ = {isa = PBXFileReference; lastKnownFileType = file; path = chat_item_group_change_chat_update_01.binproto; sourceTree = ""; }; @@ -6584,6 +6587,7 @@ E19B35432CD2E8C40078A678 /* ad_hoc_call_01.txtproto */ = {isa = PBXFileReference; lastKnownFileType = text; path = ad_hoc_call_01.txtproto; sourceTree = ""; }; E19B35442CD2E8C40078A678 /* ad_hoc_call_02.binproto */ = {isa = PBXFileReference; lastKnownFileType = file; path = ad_hoc_call_02.binproto; sourceTree = ""; }; E19B35452CD2E8C40078A678 /* ad_hoc_call_02.txtproto */ = {isa = PBXFileReference; lastKnownFileType = text; path = ad_hoc_call_02.txtproto; sourceTree = ""; }; + E19C3D932CF6B35A00F2C496 /* SignalBrandedQRCodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalBrandedQRCodes.swift; sourceTree = ""; }; E1A090372A4B909B00F2BE8B /* RecipientHidingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientHidingManager.swift; sourceTree = ""; }; E1A0AD8B16E13FDD0071E604 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; E1B628BC2CCC59E600C4DC7F /* chat_item_view_once_00.binproto */ = {isa = PBXFileReference; lastKnownFileType = file; path = chat_item_view_once_00.binproto; sourceTree = ""; }; @@ -9586,6 +9590,7 @@ F9D47A4729D1D5DB00E6E080 /* RegistrationPinAttemptsExhaustedAndMustCreateNewPinViewController.swift */, F9E3006029A02D8800DCA219 /* RegistrationPinViewController.swift */, F9EECB00299EC9D8005FDD52 /* RegistrationProfileViewController.swift */, + E15066C22CED498600F6F9AF /* RegistrationQuickRestoreQRCodeViewController.swift */, F9440E7129C0FA490016FE95 /* RegistrationReglockTimeoutViewController.swift */, C1F09BA02BB32E5900F9E7F5 /* RegistrationRestoreFromBackupViewController.swift */, F933FC3E2992E77300D78DB0 /* RegistrationSplashViewController.swift */, @@ -11810,7 +11815,6 @@ D9C2D777299B07D300D79715 /* Usernames+BetterIdentifierChecker.swift */, D9E335A829933B1A00825677 /* Usernames+HashedUsername.swift */, D99840C3297A0ECE00F7ED6D /* Usernames+ParsedUsername.swift */, - D938307D2A70441D006CDCDE /* Usernames+QRCodeColor.swift */, D925F552298349EF00158EE4 /* Usernames+UsernameLink.swift */, D99840BE297A04EB00F7ED6D /* Usernames.swift */, C15837EE29A592BA00176927 /* UsernameValidationManager.swift */, @@ -12214,7 +12218,7 @@ D9DCFDB12A3BDAB000C73C0B /* ExportableQRCodeGenerator.swift */, D9DCFDAD2A3BB25200C73C0B /* QRCodeGenerator.swift */, 88A4CC11246CE2F50082211F /* QRCodeView.swift */, - D9DCFDAF2A3BC4A400C73C0B /* UsernameLinkQRCodeGenerator.swift */, + D9DCFDAF2A3BC4A400C73C0B /* SignalBrandedQRCodeGenerator.swift */, ); path = QRCodes; sourceTree = ""; @@ -12369,6 +12373,15 @@ path = SDSCodableModel; sourceTree = ""; }; + E19C3D922CF6B34200F2C496 /* QRCodes */ = { + isa = PBXGroup; + children = ( + D938307D2A70441D006CDCDE /* SignalBrandedQRCodes+QRCodeColor.swift */, + E19C3D932CF6B35A00F2C496 /* SignalBrandedQRCodes.swift */, + ); + path = QRCodes; + sourceTree = ""; + }; E75DD3DC2810CD3500E32C36 /* subscriptions */ = { isa = PBXGroup; children = ( @@ -12841,6 +12854,7 @@ 668A01282C2B6088007B8808 /* PromiseKit */, F9C5CA00289453B100548EEE /* Protocols */, F9C5C9A1289453B100548EEE /* Protos */, + E19C3D922CF6B34200F2C496 /* QRCodes */, 668A00D32C2B5E4C007B8808 /* Randomness */, 6600F352298C8FBB00B1EDB7 /* Registration */, F9C5C9C6289453B100548EEE /* RemoteAttestation */, @@ -16507,6 +16521,7 @@ F9D47A4829D1D5DB00E6E080 /* RegistrationPinAttemptsExhaustedAndMustCreateNewPinViewController.swift in Sources */, F9E3006129A02D8800DCA219 /* RegistrationPinViewController.swift in Sources */, F9EECB01299EC9D8005FDD52 /* RegistrationProfileViewController.swift in Sources */, + E15066C32CED49C800F6F9AF /* RegistrationQuickRestoreQRCodeViewController.swift in Sources */, F9440E7229C0FA490016FE95 /* RegistrationReglockTimeoutViewController.swift in Sources */, C1F09BA12BB32E5900F9E7F5 /* RegistrationRestoreFromBackupViewController.swift in Sources */, F933FC3F2992E77300D78DB0 /* RegistrationSplashViewController.swift in Sources */, @@ -16543,6 +16558,7 @@ 886BB3D325BA0CA400079781 /* SetWallpaperViewController.swift in Sources */, F915A77029CB6D4C00EB6F68 /* ShareActivityUtil.swift in Sources */, 880D90302481E617003D2B14 /* SignalApp.swift in Sources */, + D9DCFDB02A3BC4A400C73C0B /* SignalBrandedQRCodeGenerator.swift in Sources */, D9E43C2D2CC194140001536E /* SignalCall.swift in Sources */, 8822558D26B9D1D7001A33C4 /* SignalDotMePhoneNumberLink.swift in Sources */, D9E43C0F2CC194140001536E /* SimulatorCallUIAdaptee.swift in Sources */, @@ -16611,7 +16627,6 @@ D9DCFDA52A37D12100C73C0B /* UsernameLinkPresentQRCodeViewController.swift in Sources */, D9317FDC2A4CE48D00075A92 /* UsernameLinkQRCodeColorPickerViewController.swift in Sources */, D9CAFAE62A538CA200B32BDE /* UsernameLinkQRCodeContentController.swift in Sources */, - D9DCFDB02A3BC4A400C73C0B /* UsernameLinkQRCodeGenerator.swift in Sources */, B9FF37362B9286C6005ADDB8 /* UsernameLinkScanQRCodeSheet.swift in Sources */, D9CAFAE42A538BDF00B32BDE /* UsernameLinkScanQRCodeViewController.swift in Sources */, D99840CE2981A09900F7ED6D /* UsernameLinkShareSheetViewController.swift in Sources */, @@ -17601,6 +17616,8 @@ 7255A4C62B98DEFB00E95368 /* SignalAttachment+VideoSegmenting.swift in Sources */, 7255A4C72B98DEFB00E95368 /* SignalAttachment.swift in Sources */, 664E8D882BD6D87700C4968A /* SignalAttachmentCloner.swift in Sources */, + D938307E2A70441D006CDCDE /* SignalBrandedQRCodes+QRCodeColor.swift in Sources */, + E19C3D942CF6B36500F2C496 /* SignalBrandedQRCodes.swift in Sources */, F9C5CC8F289453B300548EEE /* SignalIOS.pb.swift in Sources */, F9C5CC9E289453B300548EEE /* SignalIOSProto.swift in Sources */, 725465382BA01FAA00EABFD2 /* SignalMessagingJobQueues.swift in Sources */, @@ -17853,7 +17870,6 @@ 7255A4C42B98D81000E95368 /* Usernames+BetterIdentifierChecker.swift in Sources */, D9E335A929933B1A00825677 /* Usernames+HashedUsername.swift in Sources */, D925F561298D8F9400158EE4 /* Usernames+ParsedUsername.swift in Sources */, - D938307E2A70441D006CDCDE /* Usernames+QRCodeColor.swift in Sources */, D925F560298D8F9400158EE4 /* Usernames+UsernameLink.swift in Sources */, D925F563298D8F9400158EE4 /* Usernames.swift in Sources */, C15837EF29A592BA00176927 /* UsernameValidationManager.swift in Sources */, diff --git a/Signal/Registration/RegistrationStep.swift b/Signal/Registration/RegistrationStep.swift index c8db3e1007..58318b00f6 100644 --- a/Signal/Registration/RegistrationStep.swift +++ b/Signal/Registration/RegistrationStep.swift @@ -11,6 +11,7 @@ public enum RegistrationStep: Equatable { case registrationSplash case changeNumberSplash case permissions + case scanQuickRegistrationQrCode(RegistrationQuickRestoreQRCodeState) // MARK: - Actually registering @@ -117,6 +118,7 @@ public enum RegistrationStep: Equatable { case .registrationSplash: return "registrationSplash" case .changeNumberSplash: return "changeNumberSplash" case .permissions: return "permissions" + case .scanQuickRegistrationQrCode: return "scanQuickRegistrationQrCode" case .phoneNumberEntry: return "phoneNumberEntry" case .verificationCodeEntry: return "verificationCodeEntry" case .transferSelection: return "transferSelection" diff --git a/Signal/Registration/UserInterface/RegistrationNavigationController.swift b/Signal/Registration/UserInterface/RegistrationNavigationController.swift index afbf00710f..3d814e3165 100644 --- a/Signal/Registration/UserInterface/RegistrationNavigationController.swift +++ b/Signal/Registration/UserInterface/RegistrationNavigationController.swift @@ -160,6 +160,18 @@ public class RegistrationNavigationController: OWSNavigationController { // but its overkill so we have not. update: nil ) + case .scanQuickRegistrationQrCode(let state): + return Controller( + type: RegistrationQuickRestoreQRCodeViewController.self, + make: { presenter in + return RegistrationQuickRestoreQRCodeViewController( + state: state, + presenter: presenter + ) + }, + // State never changes. + update: nil + ) case .phoneNumberEntry(let state): switch state { case .registration(let registrationMode): @@ -404,7 +416,7 @@ extension RegistrationNavigationController: RegistrationSplashPresenter { } public func restoreOrTransfer() { - // TODO: Enter "Restore or Transfer" flow. + // TODO [Quick Restore]: Enter "Restore or Transfer" flow. } public func switchToDeviceLinkingMode() { @@ -591,6 +603,12 @@ extension RegistrationNavigationController: RegistrationRestoreFromBackupPresent } } +extension RegistrationNavigationController: RegistrationQuickRestoreQRCodePresenter { + func cancel() { + // TODO [Quick Restore]: Pop back to the very first screen in the flow (splash). + } +} + private protocol AnyController { var viewType: UIViewController.Type { get } diff --git a/Signal/Registration/UserInterface/RegistrationQuickRestoreQRCodeViewController.swift b/Signal/Registration/UserInterface/RegistrationQuickRestoreQRCodeViewController.swift new file mode 100644 index 0000000000..400e2efe66 --- /dev/null +++ b/Signal/Registration/UserInterface/RegistrationQuickRestoreQRCodeViewController.swift @@ -0,0 +1,163 @@ +// +// Copyright 2024 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +// + +import SignalServiceKit +import SignalUI +import SwiftUI + +protocol RegistrationQuickRestoreQRCodePresenter: AnyObject { + func cancel() +} + +public struct RegistrationQuickRestoreQRCodeState: Equatable { + let url: URL +} + +class RegistrationQuickRestoreQRCodeViewController: OWSViewController, OWSNavigationChildController { + private let state: RegistrationQuickRestoreQRCodeState + private weak var presenter: RegistrationQuickRestoreQRCodePresenter? + + init( + state: RegistrationQuickRestoreQRCodeState, + presenter: RegistrationQuickRestoreQRCodePresenter + ) { + self.state = state + self.presenter = presenter + super.init() + + self.addChild(hostingController) + self.view.addSubview(hostingController.view) + hostingController.view.autoPinEdgesToSuperviewEdges() + hostingController.didMove(toParent: self) + } + + private lazy var hostingController = UIHostingController(rootView: ContentStack( + url: self.state.url, + cancelAction: { [weak self] in + self?.presenter?.cancel() + } + )) + + // MARK: OWSNavigationChildController + + public var preferredNavigationBarStyle: OWSNavigationBarStyle { .solid } + + public var navbarBackgroundColorOverride: UIColor? { .clear } + + public var prefersNavigationBarHidden: Bool { true } +} + +// MARK: - SwiftUI + +private struct ContentStack: View { + let url: URL + let cancelAction: () -> Void + + var body: some View { + VStack { + Spacer() + Text(OWSLocalizedString( + "REGISTRATION_SCAN_QR_CODE_TITLE", + comment: "Title for screen containing QR code that users scan with their old phone when they want to transfer/restore their message history to a new device." + )) + .font(.title) + .fontWeight(.semibold) + .padding(.horizontal, 8) + .multilineTextAlignment(.center) + Spacer() + QRCode(url: url) + Spacer() + TutorialStack() + Spacer() + Spacer() + Button(CommonStrings.cancelButton, action: self.cancelAction) + .font(.body.weight(.bold)) + .tint(Color.Signal.ultramarine) + .padding(.vertical, 14) + Spacer() + } + } +} + +private struct TutorialStack: View { + var body: some View { + VStack(alignment: .leading, spacing: 24) { + Label( + OWSLocalizedString( + "REGISTRATION_SCAN_QR_CODE_TUTORIAL_OPEN_SIGNAL", + comment: "Tutorial text describing the first step to scanning the restore/transfer QR code with your old phone: opening Signal" + ), + image: "device-phone" + ) + Label( + OWSLocalizedString( + "REGISTRATION_SCAN_QR_CODE_TUTORIAL_TAP_CAMERA", + comment: "Tutorial text describing the second step to scanning the restore/transfer QR code with your old phone: tap the camera icon" + ), + image: "camera" + ) + Label( + OWSLocalizedString( + "REGISTRATION_SCAN_QR_CODE_TUTORIAL_SCAN", + comment: "Tutorial text describing the third step to scanning the restore/transfer QR code with your old phone: scan the code" + ), + image: "qr_code" + ) + } + .foregroundStyle(.secondary) + .padding(.horizontal, 8) + } +} + +private struct QRCode: View { + let url: URL + + var body: some View { + ZStack { + Color(.ows_gray02) + .frame(width: 296, height: 296) + .cornerRadius(24) + Color(.ows_white) + .frame(width: 216, height: 216) + .cornerRadius(12) + QRCodeViewRepresentable(url: url) + .frame(width: 212, height: 212) + } + } +} + +private struct QRCodeViewRepresentable: UIViewRepresentable { + var url: URL + private let qrCodeColor = SignalBrandedQRCodes.QRCodeColor.blue.foreground + + func makeUIView(context: Context) -> QRCodeView { + let view = QRCodeView(useCircularWrapper: false) + view.setContentHuggingPriority(.required, for: .vertical) + + if + let qrCodeImage = SignalBrandedQRCodeGenerator( + foregroundColor: qrCodeColor, + backgroundColor: .clear + ).generateQRCode(url: url) + { + let templateImage = qrCodeImage.withRenderingMode(.alwaysTemplate) + view.setQR(templateImage: templateImage, tintColor: qrCodeColor) + } + + return view + } + + func updateUIView(_ qrCodeView: QRCodeView, context: Context) { + // The url will never change, so there's no need to implement this. + } +} + +#if DEBUG + +#Preview() { + ContentStack(url: URL(string: "www.signal.org")!, cancelAction: {}) +} + +#endif diff --git a/Signal/Symbols.xcassets/device/Contents.json b/Signal/Symbols.xcassets/device/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/Signal/Symbols.xcassets/device/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Signal/Symbols.xcassets/device/device-phone.imageset/Contents.json b/Signal/Symbols.xcassets/device/device-phone.imageset/Contents.json new file mode 100644 index 0000000000..185ed76241 --- /dev/null +++ b/Signal/Symbols.xcassets/device/device-phone.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "device-phone.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Signal/Symbols.xcassets/device/device-phone.imageset/device-phone.pdf b/Signal/Symbols.xcassets/device/device-phone.imageset/device-phone.pdf new file mode 100644 index 0000000000000000000000000000000000000000..720e8c3a387294e592b36b00915296a13e9910da GIT binary patch literal 2542 zcmai0c|4SB8~zeu_)<|J%UdF28#9b7QTB*12%pFpFGgc#%#2}164}dA*|OwJNR()? zbVACm4rMFTu{(tpEh-J8Z(gCJ^ZkC`^T+$%?{z=V^*;A~Kfn8W6z$C{)R7u{VK5}1 z36Q)4U;wahAAm3>&_D_iO9KIf8A!+DK#Zjc&&3-E3q0iGy$L+G8HgkKfXf~mkmyJA z2eh>HmVv{77SA#=f>CJ{5E}>!%?(biJJe_|(QJ1O^F%*>qpS=n!L+vSZ<9BKO|wPftG&*~Por-lK0CusfRB zsgX&)#OD~n_2|oQ&z9y6_ZlZjZ5uh4kREtOct}wW=?@<(9jSfP8r7qbZ*VEyCwDHx zwHp=?TVthGY%qI5Ff$P>t33UDD8J7ovsq@^;W1WRNixyiA(CHUG-9DAd4IAx#l_2B zBZW_`!^~>4_^qZ-PgvM3s30NZ>C_tP>yu(-^X-9wGh4F)$(;x`+ho0N9_vEi3w9{K zr1Zat(>7=)%W2k^mz0KiVa+VQ*cs*9*q0A?hJ;0kPKJ#x;6&fc^3l^jl`C|TcK%&obo_Q8jN*HRjrcg~*P_0$e9Y9!_nwns#pbr4m9|L%-&eC3;1)T>| z5`jcyDp-Y> zQxK8!nKRDea_C&nu*gK5p4xX@ijMnhu@=CJ+PrY-*DeK#+4l1(sZvH zQx)Xo|@%L4@IdX^V#|wrDm3wEm;WXzS#` zmb8m!Usbec$!O^~thZ{B^dUB(oCpeMq)_^O?`qGxGA_m{e=S4^yGS?|vAm9n6w0Ik zRUV0A>$OMcr7hr($&Dt-Wz21f#eXW)o{LCKx=zbajb^WJ=^~1wl7_m+Ed6qT8|8*~ z(urGA$cK@qn(7}ift%yIw<}}QE0Vp390R7!yCRQBG?;kcJw}B3FBDBUFK8*)vkuiT zQ<}nS74V9TJkBY7!_4<2ws4U_cg`KOZ)X32$E6QqnQ8n^lQfRSN4LQP=@L=a2?Y+G z#!9Ur6PT>XjGVU9g(DS8O$#~EJ6#)gbiPw)E2+AeQj^hliLJ$JZ+$loBBQP zif%YU4@>nrw4vja|C{mIei403aUC#RY3`}~m$Ukb-g#=53`R@#5Ikio+(IRVlMQ_7 zLbyHFRr{)q#=coFA9NF$&9-Lur?@H(aTkO?qeQBu<3rn((lVaRn1;ArGv<3Leitk~ z7|U`2#~pGd46pWIpAuK$-^u8f^|pV@ANH)F^r2Zt%*5N+R;>rFH#Zi-gZ4Kfl?;0# z#nNE)M`ojK7|(sMmi=euk`I*Ql#wj zFuK=lf`%lg(85UZsywOXA%pUgds=q)&7S9-7kg-K!hvV;VgvhB5a(Ilnqx^eg!|%p z_96y@?V_@*WN#Hp$7Old;P9>lxp3Dy;XViL!zBIaWDc3}+t%H$nFF2{1O9thn>&>e zdN?uNF}c80A$oC~Teg7tfkT35=cWs?9#IbHRQ$f=3rVknTdRYfrIOY*k zWukD|jOfd^+(OO6Bs5K?WvnKd()i8An@hY(+>6yv{9}ejT?v2mn@avpXdEbTBoFNW z4}}rN}LlWNUR*Mc+)tn<6G}Sb3OVy-|>#jx&P6v zp?3H~fsrV*?rKxry9zG}Gm%K5Q2}?4Wr=lSka-$ykM&y-VO!7#k2N8M0`7pOhUU`v zX`r-Mpr6(X69%M`f+;wV3P7zN>dTPYo05n$kjVQZ)Z14;dn|>A0lLf3-xL6Xe%>Mu z;eB{p1)vBZX<1JM7xR82i zUJBPhC?x7vE)+`h=Rz6r8Z07}(TX%LQh aCJ4p7bmhWQXiJ$up>&WiMMZNvi~j;6ME+<1 literal 0 HcmV?d00001 diff --git a/Signal/Usernames/Links/UsernameLinkPresentQRCodeViewController.swift b/Signal/Usernames/Links/UsernameLinkPresentQRCodeViewController.swift index c642f137c1..8db33b3bf2 100644 --- a/Signal/Usernames/Links/UsernameLinkPresentQRCodeViewController.swift +++ b/Signal/Usernames/Links/UsernameLinkPresentQRCodeViewController.swift @@ -28,7 +28,7 @@ class UsernameLinkPresentQRCodeViewController: OWSTableViewController2 { usernameLink: Usernames.UsernameLink ) -> UsernameLinkState { if - let qrCodeImage = UsernameLinkQRCodeGenerator( + let qrCodeImage = SignalBrandedQRCodeGenerator( foregroundColor: .ows_black, backgroundColor: .clear ).generateQRCode(url: usernameLink.url) @@ -55,7 +55,7 @@ class UsernameLinkPresentQRCodeViewController: OWSTableViewController2 { private weak var usernameChangeDelegate: UsernameChangeDelegate? - private var qrCodeColor: Usernames.QRCodeColor! + private var qrCodeColor: SignalBrandedQRCodes.QRCodeColor! private var _usernameLinkState: UsernameLinkState! /// A layer of indirection to avoid needing to handle `nil` in switches, @@ -312,7 +312,7 @@ class UsernameLinkPresentQRCodeViewController: OWSTableViewController2 { guard let (usernameLink, _) = self.usernameLinkState.linkParams, - let qrCode = UsernameLinkQRCodeGenerator( + let qrCode = SignalBrandedQRCodeGenerator( foregroundColor: self.qrCodeColor.foreground, backgroundColor: qrCodeBackgroundColor ).generateQRCode(url: usernameLink.url) @@ -698,7 +698,7 @@ extension UsernameLinkPresentQRCodeViewController: SheetDismissalDelegate { } extension UsernameLinkPresentQRCodeViewController: UsernameLinkQRCodeColorPickerDelegate { - func didFinalizeSelectedColor(color: Usernames.QRCodeColor) { + func didFinalizeSelectedColor(color: SignalBrandedQRCodes.QRCodeColor) { db.write { tx in localUsernameManager.setUsernameLinkQRCodeColor( color: color, diff --git a/Signal/Usernames/Links/UsernameLinkQRCodeColorPickerViewController.swift b/Signal/Usernames/Links/UsernameLinkQRCodeColorPickerViewController.swift index 7fac5a9f84..1b5928e985 100644 --- a/Signal/Usernames/Links/UsernameLinkQRCodeColorPickerViewController.swift +++ b/Signal/Usernames/Links/UsernameLinkQRCodeColorPickerViewController.swift @@ -7,12 +7,12 @@ import SignalServiceKit import SignalUI protocol UsernameLinkQRCodeColorPickerDelegate: SheetDismissalDelegate { - func didFinalizeSelectedColor(color: Usernames.QRCodeColor) + func didFinalizeSelectedColor(color: SignalBrandedQRCodes.QRCodeColor) } class UsernameLinkQRCodeColorPickerViewController: OWSTableViewController2 { - private let startingColor: Usernames.QRCodeColor - private var currentColor: Usernames.QRCodeColor + private let startingColor: SignalBrandedQRCodes.QRCodeColor + private var currentColor: SignalBrandedQRCodes.QRCodeColor private let username: String private let qrCodeTemplateImage: UIImage @@ -20,7 +20,7 @@ class UsernameLinkQRCodeColorPickerViewController: OWSTableViewController2 { private weak var colorPickerDelegate: UsernameLinkQRCodeColorPickerDelegate? init( - currentColor: Usernames.QRCodeColor, + currentColor: SignalBrandedQRCodes.QRCodeColor, username: String, qrCodeTemplateImage: UIImage, delegate: UsernameLinkQRCodeColorPickerDelegate @@ -99,8 +99,8 @@ class UsernameLinkQRCodeColorPickerViewController: OWSTableViewController2 { } private func buildColorOptionsView() -> UIView { - let colorOptionButtons: [Usernames.QRCodeColor: ColorOptionButton] = { - return Usernames.QRCodeColor.allCases.reduce(into: [:]) { partial, color in + let colorOptionButtons: [SignalBrandedQRCodes.QRCodeColor: ColorOptionButton] = { + return SignalBrandedQRCodes.QRCodeColor.allCases.reduce(into: [:]) { partial, color in let button = ColorOptionButton( size: 56, color: color.background, @@ -113,7 +113,7 @@ class UsernameLinkQRCodeColorPickerViewController: OWSTableViewController2 { } }() - func stack(colors: [Usernames.QRCodeColor]) -> UIStackView { + func stack(colors: [SignalBrandedQRCodes.QRCodeColor]) -> UIStackView { let stack = UIStackView(arrangedSubviews: colors.map { color in return colorOptionButtons[color]! }) @@ -211,7 +211,7 @@ class UsernameLinkQRCodeColorPickerViewController: OWSTableViewController2 { dismiss(animated: true) } - private func didSelectColor(color selectedColor: Usernames.QRCodeColor) { + private func didSelectColor(color selectedColor: SignalBrandedQRCodes.QRCodeColor) { currentColor = selectedColor reloadTableContents() } diff --git a/Signal/src/QRCodes/UsernameLinkQRCodeGenerator.swift b/Signal/src/QRCodes/SignalBrandedQRCodeGenerator.swift similarity index 98% rename from Signal/src/QRCodes/UsernameLinkQRCodeGenerator.swift rename to Signal/src/QRCodes/SignalBrandedQRCodeGenerator.swift index 96d1242c20..0553244a0e 100644 --- a/Signal/src/QRCodes/UsernameLinkQRCodeGenerator.swift +++ b/Signal/src/QRCodes/SignalBrandedQRCodeGenerator.swift @@ -6,12 +6,12 @@ import SignalServiceKit import SignalUI -/// A generator producing styled QR codes for username links. +/// A generator producing styled QR codes. /// /// The QR codes have a configurable foreground and background, and contain /// aesthetic features such as an overlaid Signal logo and rounded "pixels". /// They are scaled up so as to appropriately render the rounded shapes. -class UsernameLinkQRCodeGenerator: QRCodeGenerator { +class SignalBrandedQRCodeGenerator: QRCodeGenerator { /// For the following constants: /// - "Point" refers to a coordinate ("pixel") in the QR code. /// - "Pixel" refers to a pixel in the image returned by the generator. diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 9d20c94eeb..dee781e7dc 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -6133,6 +6133,18 @@ /* No comment provided by engineer. */ "REGISTRATION_RESTRICTED_MESSAGE" = "You need to register before you can send a message."; +/* Title for screen containing QR code that users scan with their old phone when they want to transfer/restore their message history to a new device. */ +"REGISTRATION_SCAN_QR_CODE_TITLE" = "Scan this code with your old phone"; + +/* Tutorial text describing the first step to scanning the restore/transfer QR code with your old phone: opening Signal */ +"REGISTRATION_SCAN_QR_CODE_TUTORIAL_OPEN_SIGNAL" = "Open Signal on your old device"; + +/* Tutorial text describing the third step to scanning the restore/transfer QR code with your old phone: scan the code */ +"REGISTRATION_SCAN_QR_CODE_TUTORIAL_SCAN" = "Scan this code with the camera"; + +/* Tutorial text describing the second step to scanning the restore/transfer QR code with your old phone: tap the camera icon */ +"REGISTRATION_SCAN_QR_CODE_TUTORIAL_TAP_CAMERA" = "Tap the camera icon"; + /* Button when sending a verification code via sms failed, but resending via voice call might succeed. */ "REGISTRATION_SMS_CODE_FAILED_TRY_VOICE_BUTTON" = "Voice Call"; diff --git a/SignalServiceKit/MessageBackup/Archivers/AccountData/MessageBackupAccountDataArchiver.swift b/SignalServiceKit/MessageBackup/Archivers/AccountData/MessageBackupAccountDataArchiver.swift index 8e16e6dbaa..92ac5f8ee0 100644 --- a/SignalServiceKit/MessageBackup/Archivers/AccountData/MessageBackupAccountDataArchiver.swift +++ b/SignalServiceKit/MessageBackup/Archivers/AccountData/MessageBackupAccountDataArchiver.swift @@ -426,7 +426,7 @@ public class MessageBackupAccountDataArchiverImpl: MessageBackupAccountDataArchi } } -private extension Usernames.QRCodeColor { +private extension SignalBrandedQRCodes.QRCodeColor { var backupProtoColor: BackupProto_AccountData.UsernameLink.Color { switch self { case .blue: return .blue @@ -442,7 +442,7 @@ private extension Usernames.QRCodeColor { } private extension BackupProto_AccountData.UsernameLink.Color { - var qrCodeColor: Usernames.QRCodeColor { + var qrCodeColor: SignalBrandedQRCodes.QRCodeColor { switch self { case .blue: return .blue case .white: return .white diff --git a/SignalServiceKit/Mocks/Usernames/MockLocalUsernameManager.swift b/SignalServiceKit/Mocks/Usernames/MockLocalUsernameManager.swift index 0b6e8a431f..a79e30225d 100644 --- a/SignalServiceKit/Mocks/Usernames/MockLocalUsernameManager.swift +++ b/SignalServiceKit/Mocks/Usernames/MockLocalUsernameManager.swift @@ -25,8 +25,8 @@ public class MockLocalUsernameManager: LocalUsernameManager { public func setLocalUsername(username: String, usernameLink: Usernames.UsernameLink, tx: DBWriteTransaction) { owsFail("Not implemented!") } public func clearLocalUsername(tx: DBWriteTransaction) { owsFail("Not implemented!") } - public func usernameLinkQRCodeColor(tx: DBReadTransaction) -> Usernames.QRCodeColor { owsFail("Not implemented!") } - public func setUsernameLinkQRCodeColor(color: Usernames.QRCodeColor, tx: DBWriteTransaction) { owsFail("Not implemented!") } + public func usernameLinkQRCodeColor(tx: DBReadTransaction) -> SignalBrandedQRCodes.QRCodeColor { owsFail("Not implemented!") } + public func setUsernameLinkQRCodeColor(color: SignalBrandedQRCodes.QRCodeColor, tx: DBWriteTransaction) { owsFail("Not implemented!") } public func reserveUsername(usernameCandidates: Usernames.HashedUsername.GeneratedCandidates) -> Guarantee> { owsFail("Not implemented!") } public func confirmUsername(reservedUsername: Usernames.HashedUsername, tx: DBWriteTransaction) -> Guarantee> { owsFail("Not implemented!") } public func deleteUsername(tx: DBWriteTransaction) -> Guarantee> { owsFail("Not implemented!") } diff --git a/SignalServiceKit/Usernames/Usernames+QRCodeColor.swift b/SignalServiceKit/QRCodes/SignalBrandedQRCodes+QRCodeColor.swift similarity index 94% rename from SignalServiceKit/Usernames/Usernames+QRCodeColor.swift rename to SignalServiceKit/QRCodes/SignalBrandedQRCodes+QRCodeColor.swift index 8ba01bbf73..21d830dfed 100644 --- a/SignalServiceKit/Usernames/Usernames+QRCodeColor.swift +++ b/SignalServiceKit/QRCodes/SignalBrandedQRCodes+QRCodeColor.swift @@ -3,10 +3,10 @@ // SPDX-License-Identifier: AGPL-3.0-only // -/// Preset color options for the username link QR code. +/// Preset color options for the Signal-branded QR code. /// /// Exposes a set of colors to use for various parts of the QR code rendering. -public extension Usernames { +public extension SignalBrandedQRCodes { enum QRCodeColor: String, UnknownEnumCodable, CaseIterable { case blue case white @@ -17,7 +17,7 @@ public extension Usernames { case pink case purple - public static var unknown: Usernames.QRCodeColor { .blue } + public static var unknown: SignalBrandedQRCodes.QRCodeColor { .blue } /// Background color for the QR code. public var background: UIColor { diff --git a/SignalServiceKit/QRCodes/SignalBrandedQRCodes.swift b/SignalServiceKit/QRCodes/SignalBrandedQRCodes.swift new file mode 100644 index 0000000000..adc6105406 --- /dev/null +++ b/SignalServiceKit/QRCodes/SignalBrandedQRCodes.swift @@ -0,0 +1,7 @@ +// +// Copyright 2024 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only +// + +/// A namespace for Signal-branded QR code related models. +public enum SignalBrandedQRCodes {} diff --git a/SignalServiceKit/StorageService/StorageServiceProto+Sync.swift b/SignalServiceKit/StorageService/StorageServiceProto+Sync.swift index 6b6bf4e433..7197e851bc 100644 --- a/SignalServiceKit/StorageService/StorageServiceProto+Sync.swift +++ b/SignalServiceKit/StorageService/StorageServiceProto+Sync.swift @@ -1411,7 +1411,7 @@ class StorageServiceAccountRecordUpdater: StorageServiceRecordUpdater { ) localUsernameManager.setUsernameLinkQRCodeColor( - color: Usernames.QRCodeColor(proto: remoteUsernameLinkProto.color), + color: SignalBrandedQRCodes.QRCodeColor(proto: remoteUsernameLinkProto.color), tx: transaction.asV2Write ) } else { @@ -1990,7 +1990,7 @@ extension StorageServiceProtoOptionalBool { } } -private extension Usernames.QRCodeColor { +private extension SignalBrandedQRCodes.QRCodeColor { var asProto: StorageServiceProtoAccountRecordUsernameLinkColor { switch self { case .blue: return .blue diff --git a/SignalServiceKit/Usernames/LocalUsernameManager.swift b/SignalServiceKit/Usernames/LocalUsernameManager.swift index 5bd21ccda0..c4a8aa50b0 100644 --- a/SignalServiceKit/Usernames/LocalUsernameManager.swift +++ b/SignalServiceKit/Usernames/LocalUsernameManager.swift @@ -45,11 +45,11 @@ public protocol LocalUsernameManager { func clearLocalUsername(tx: DBWriteTransaction) /// Returns the color to be used for the local user's username link QR code. - func usernameLinkQRCodeColor(tx: DBReadTransaction) -> Usernames.QRCodeColor + func usernameLinkQRCodeColor(tx: DBReadTransaction) -> SignalBrandedQRCodes.QRCodeColor /// Sets the color to be used for the local user's username link QR code. func setUsernameLinkQRCodeColor( - color: Usernames.QRCodeColor, + color: SignalBrandedQRCodes.QRCodeColor, tx: DBWriteTransaction ) @@ -236,7 +236,7 @@ class LocalUsernameManagerImpl: LocalUsernameManager { return nil } - func usernameLinkColor(tx: DBReadTransaction) -> Usernames.QRCodeColor { + func usernameLinkColor(tx: DBReadTransaction) -> SignalBrandedQRCodes.QRCodeColor { return (try? kvStore.getCodableValue( forKey: Constants.usernameLinkQRCodeColorKey, transaction: tx @@ -252,7 +252,7 @@ class LocalUsernameManagerImpl: LocalUsernameManager { kvStore.setData(usernameLink?.entropy, key: Constants.usernameLinkEntropyKey, transaction: tx) } - func setUsernameLinkColor(color: Usernames.QRCodeColor, tx: DBWriteTransaction) { + func setUsernameLinkColor(color: SignalBrandedQRCodes.QRCodeColor, tx: DBWriteTransaction) { try? kvStore.setCodable(color, key: Constants.usernameLinkQRCodeColorKey, transaction: tx) } } @@ -366,12 +366,12 @@ class LocalUsernameManagerImpl: LocalUsernameManager { func usernameLinkQRCodeColor( tx: DBReadTransaction - ) -> Usernames.QRCodeColor { + ) -> SignalBrandedQRCodes.QRCodeColor { return usernameStore.usernameLinkColor(tx: tx) } func setUsernameLinkQRCodeColor( - color: Usernames.QRCodeColor, + color: SignalBrandedQRCodes.QRCodeColor, tx: DBWriteTransaction ) { usernameStore.setUsernameLinkColor(color: color, tx: tx) diff --git a/SignalServiceKit/tests/Usernames/LocalUsernameManagerTests.swift b/SignalServiceKit/tests/Usernames/LocalUsernameManagerTests.swift index 0c20da157f..42cce3a795 100644 --- a/SignalServiceKit/tests/Usernames/LocalUsernameManagerTests.swift +++ b/SignalServiceKit/tests/Usernames/LocalUsernameManagerTests.swift @@ -92,7 +92,7 @@ class LocalUsernameManagerTests: XCTestCase { } func testUsernameQRCodeColorChanges() { - func color() -> Usernames.QRCodeColor { + func color() -> SignalBrandedQRCodes.QRCodeColor { return mockDB.read { tx in return localUsernameManager.usernameLinkQRCodeColor(tx: tx) }