diff --git a/TwoFAS/Content/Assets/Assets.car b/TwoFAS/Content/Assets/Assets.car index 9f9ea1f0..c4a99c38 100644 Binary files a/TwoFAS/Content/Assets/Assets.car and b/TwoFAS/Content/Assets/Assets.car differ diff --git a/TwoFAS/Content/AssetsWatch/Assets.car b/TwoFAS/Content/AssetsWatch/Assets.car index 34768edb..1f76abaf 100644 Binary files a/TwoFAS/Content/AssetsWatch/Assets.car and b/TwoFAS/Content/AssetsWatch/Assets.car differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database0.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database0.swift index 9f74157f..d9bcde5a 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database0.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database0.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database1.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database1.swift index 6ad8ac20..18fa8f0f 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database1.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database1.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database2.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database2.swift index 83a2e498..06c88ac1 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database2.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database2.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database3.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database3.swift index 917cc474..74147b8a 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database3.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database3.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database4.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database4.swift index e741985e..6fc9b148 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database4.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database4.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database5.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database5.swift index 21ea1664..d9a27db2 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database5.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database5.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database6.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database6.swift index ff407070..b9df5562 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database6.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database6.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database7.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database7.swift index ae13ca5f..7452ff6d 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database7.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database7.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database8.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database8.swift index 20e6047e..58243a78 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database8.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database8.swift differ diff --git a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database9.swift b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database9.swift index 26df0eda..c454c01a 100644 Binary files a/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database9.swift and b/TwoFAS/Content/Sources/IconDescriptionDatabaseImpl+Database9.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database0.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database0.swift index 81de442f..5effef7c 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database0.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database0.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database1.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database1.swift index ed5f1e14..b7342f05 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database1.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database1.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database2.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database2.swift index 24c5c0da..1cf28da4 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database2.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database2.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database3.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database3.swift index 557b0f9c..27a8469b 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database3.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database3.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database4.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database4.swift index 099597d6..c53639dd 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database4.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database4.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database5.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database5.swift index 51375adb..4af673b9 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database5.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database5.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database6.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database6.swift index 0d070a9f..40d9832f 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database6.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database6.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database7.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database7.swift index e3163ae9..3ffe5007 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database7.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database7.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database8.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database8.swift index 8fe76cc4..a4559c5c 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database8.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database8.swift differ diff --git a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database9.swift b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database9.swift index 67dd5540..d6d127a8 100644 Binary files a/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database9.swift and b/TwoFAS/Content/Sources/ServiceDefinitionDatabaseImpl+Database9.swift differ diff --git a/TwoFAS/TwoFAS.xcodeproj/project.pbxproj b/TwoFAS/TwoFAS.xcodeproj/project.pbxproj index 086e4610..cd3b3a3e 100644 --- a/TwoFAS/TwoFAS.xcodeproj/project.pbxproj +++ b/TwoFAS/TwoFAS.xcodeproj/project.pbxproj @@ -8,6 +8,10 @@ /* Begin PBXBuildFile section */ 8F00E46A2C23953B001F15AD /* SortTokensView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F00E4692C23953B001F15AD /* SortTokensView.swift */; }; + 8F0FFF002D04D73E0064B0D3 /* RevealTokenImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0FFEFF2D04D73D0064B0D3 /* RevealTokenImage.swift */; }; + 8F0FFF022D04D74E0064B0D3 /* CountdownTimerText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0FFF012D04D74D0064B0D3 /* CountdownTimerText.swift */; }; + 8F0FFF052D0514B80064B0D3 /* RevealTokenIntentButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0FFF042D0514B60064B0D3 /* RevealTokenIntentButton.swift */; }; + 8F0FFF072D051AD40064B0D3 /* RevealTokenOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0FFF062D051AD10064B0D3 /* RevealTokenOverlayView.swift */; }; 8F43E7002C4C50DD0006D380 /* AppleWatchPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F43E6FF2C4C50DD0006D380 /* AppleWatchPresenter.swift */; }; 8F43E7032C4C511A0006D380 /* AppleWatchFlowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F43E7022C4C511A0006D380 /* AppleWatchFlowController.swift */; }; 8F594C422C3027160066562F /* AppleWatchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F594C412C3027160066562F /* AppleWatchView.swift */; }; @@ -17,6 +21,7 @@ 8F7952532C01D1940053F776 /* KeyboardButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F7952522C01D1940053F776 /* KeyboardButtonStyle.swift */; }; 8F872DE92C24EE2600160D14 /* SortTokensPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F872DE82C24EE2600160D14 /* SortTokensPresenter.swift */; }; 8F872DEB2C24EE5500160D14 /* SortTokensInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F872DEA2C24EE5500160D14 /* SortTokensInteractor.swift */; }; + 8FF1CC7F2D09030000428BB4 /* T.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = C24AEDBF291BD119005F59CB /* T.generated.swift */; }; C200E49E1FB3911B00D7C748 /* Storage.h in Headers */ = {isa = PBXBuildFile; fileRef = C200E49C1FB3911B00D7C748 /* Storage.h */; settings = {ATTRIBUTES = (Public, ); }; }; C200E4A11FB3911B00D7C748 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C200E49A1FB3911B00D7C748 /* Storage.framework */; }; C200E4A21FB3911B00D7C748 /* Storage.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C200E49A1FB3911B00D7C748 /* Storage.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -1888,6 +1893,10 @@ /* Begin PBXFileReference section */ 8F00E4692C23953B001F15AD /* SortTokensView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortTokensView.swift; sourceTree = ""; }; + 8F0FFEFF2D04D73D0064B0D3 /* RevealTokenImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RevealTokenImage.swift; sourceTree = ""; }; + 8F0FFF012D04D74D0064B0D3 /* CountdownTimerText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountdownTimerText.swift; sourceTree = ""; }; + 8F0FFF042D0514B60064B0D3 /* RevealTokenIntentButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RevealTokenIntentButton.swift; sourceTree = ""; }; + 8F0FFF062D051AD10064B0D3 /* RevealTokenOverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RevealTokenOverlayView.swift; sourceTree = ""; }; 8F1077252C8C80310031448C /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/LaunchScreen.strings; sourceTree = ""; }; 8F1077262C8C80310031448C /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/TwoFASWidget.strings; sourceTree = ""; }; 8F1077272C8C80310031448C /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; @@ -3346,6 +3355,25 @@ path = SortTokens; sourceTree = ""; }; + 8F0FFEFE2D04D7220064B0D3 /* Components */ = { + isa = PBXGroup; + children = ( + 8F0FFF062D051AD10064B0D3 /* RevealTokenOverlayView.swift */, + 8F0FFF012D04D74D0064B0D3 /* CountdownTimerText.swift */, + 8F0FFEFF2D04D73D0064B0D3 /* RevealTokenImage.swift */, + ); + path = Components; + sourceTree = ""; + }; + 8F0FFF032D0514AA0064B0D3 /* IntentButtons */ = { + isa = PBXGroup; + children = ( + C248DDAE2B799CD3004712E3 /* CopyIntentButton.swift */, + 8F0FFF042D0514B60064B0D3 /* RevealTokenIntentButton.swift */, + ); + path = IntentButtons; + sourceTree = ""; + }; 8F43E6FD2C4C50A60006D380 /* View */ = { isa = PBXGroup; children = ( @@ -7203,27 +7231,28 @@ C2C3AE12269E224A00506ACF /* TwoFASWidget */ = { isa = PBXGroup; children = ( - C2BBD2332B81308C009A91FB /* Localizable.strings */, - C25228ED2B72E44C00F40C86 /* AppIntent */, - C2C3AE13269E224A00506ACF /* TwoFASWidget.swift */, - C2A7B99226B706B000055738 /* TwoFASWidget.intentdefinition */, + C2C3AE18269E224B00506ACF /* Info.plist */, + C25DCB2D2B8030B200871035 /* AccessManager.swift */, C2D07EE926A475F400AF8E7B /* CodeEntry.swift */, - C248DDAE2B799CD3004712E3 /* CopyIntentButton.swift */, - C254D11B26ACB71B005FEBD4 /* TwoFASWidgetSquareView.swift */, - C29787DD27341FF600C67CE0 /* TwoFASWidgetLineViewGrid.swift */, + C254D12126ACB7D8005FEBD4 /* CodeRedaction.swift */, + C2C8F92E2CD6CB62001179C0 /* CommonKeys.swift */, + C2A57C5826ACAAD000D3B344 /* Extensions.swift */, + C2C32A302AB7198C00DDB944 /* IconRenderer.swift */, + C254D11F26ACB777005FEBD4 /* Provider.swift */, + C2C3AE13269E224A00506ACF /* TwoFASWidget.swift */, + C2BBD1D52B8120F4009A91FB /* TwoFASWidgetCircular.swift */, + C2BBD1D22B81127C009A91FB /* TwoFASWidgetInline.swift */, C254D11D26ACB73D005FEBD4 /* TwoFASWidgetLineView.swift */, + C29787DD27341FF600C67CE0 /* TwoFASWidgetLineViewGrid.swift */, C28AB9322B76970D009E3601 /* TwoFASWidgetRectangular.swift */, - C2BBD1D22B81127C009A91FB /* TwoFASWidgetInline.swift */, - C2BBD1D52B8120F4009A91FB /* TwoFASWidgetCircular.swift */, - C254D11F26ACB777005FEBD4 /* Provider.swift */, - C2A57C5826ACAAD000D3B344 /* Extensions.swift */, + C254D11B26ACB71B005FEBD4 /* TwoFASWidgetSquareView.swift */, C248DDA72B794A69004712E3 /* WidgetContentMargins.swift */, - C2C8F92E2CD6CB62001179C0 /* CommonKeys.swift */, C2C3AE16269E224B00506ACF /* Assets.xcassets */, - C2C3AE18269E224B00506ACF /* Info.plist */, - C254D12126ACB7D8005FEBD4 /* CodeRedaction.swift */, - C2C32A302AB7198C00DDB944 /* IconRenderer.swift */, - C25DCB2D2B8030B200871035 /* AccessManager.swift */, + C25228ED2B72E44C00F40C86 /* AppIntent */, + 8F0FFEFE2D04D7220064B0D3 /* Components */, + 8F0FFF032D0514AA0064B0D3 /* IntentButtons */, + C2BBD2332B81308C009A91FB /* Localizable.strings */, + C2A7B99226B706B000055738 /* TwoFASWidget.intentdefinition */, ); path = TwoFASWidget; sourceTree = ""; @@ -10506,14 +10535,19 @@ C254D12226ACB7D8005FEBD4 /* CodeRedaction.swift in Sources */, C254D12026ACB777005FEBD4 /* Provider.swift in Sources */, C254D11C26ACB71B005FEBD4 /* TwoFASWidgetSquareView.swift in Sources */, + 8F0FFF072D051AD40064B0D3 /* RevealTokenOverlayView.swift in Sources */, C29787DE27341FF600C67CE0 /* TwoFASWidgetLineViewGrid.swift in Sources */, C25DCB2E2B8030B200871035 /* AccessManager.swift in Sources */, C2C3AE14269E224A00506ACF /* TwoFASWidget.swift in Sources */, C2D07EEB26A47B8100AF8E7B /* CodeEntry.swift in Sources */, + 8F0FFF002D04D73E0064B0D3 /* RevealTokenImage.swift in Sources */, C248DDA82B794A69004712E3 /* WidgetContentMargins.swift in Sources */, C2C8F92F2CD6CB67001179C0 /* CommonKeys.swift in Sources */, + 8FF1CC7F2D09030000428BB4 /* T.generated.swift in Sources */, C2404F782B72E61B00EBD8DC /* ServiceAppEntity.swift in Sources */, + 8F0FFF022D04D74E0064B0D3 /* CountdownTimerText.swift in Sources */, C28AB9332B76970D009E3601 /* TwoFASWidgetRectangular.swift in Sources */, + 8F0FFF052D0514B80064B0D3 /* RevealTokenIntentButton.swift in Sources */, C2A57C5A26ACAB2800D3B344 /* Extensions.swift in Sources */, C2404F7C2B72E8D000EBD8DC /* AppIntentProvider.swift in Sources */, C2404F792B72E61B00EBD8DC /* SelectService.swift in Sources */, @@ -11282,12 +11316,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = Storage/Info.plist; @@ -11326,12 +11360,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = Storage/Info.plist; @@ -11368,12 +11402,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; GENERATE_INFOPLIST_FILE = YES; @@ -11414,12 +11448,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; GENERATE_INFOPLIST_FILE = YES; @@ -11458,12 +11492,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = ""; @@ -11503,12 +11537,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = ""; @@ -11546,12 +11580,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; FRAMEWORK_SEARCH_PATHS = ""; @@ -11595,12 +11629,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; FRAMEWORK_SEARCH_PATHS = ""; @@ -11770,7 +11804,7 @@ CODE_SIGN_ENTITLEMENTS = TwoFAS/Other/TwoFAS.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEPLOYMENT_POSTPROCESSING = NO; DEVELOPMENT_TEAM = ZY8UR5ADFW; @@ -11815,7 +11849,7 @@ CODE_SIGN_ENTITLEMENTS = TwoFAS/Other/TwoFAS.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEPLOYMENT_POSTPROCESSING = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; ENABLE_BITCODE = NO; @@ -11859,12 +11893,12 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; GENERATE_INFOPLIST_FILE = YES; @@ -11907,12 +11941,12 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; GENERATE_INFOPLIST_FILE = YES; @@ -11951,12 +11985,12 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = Sync/Other/Info.plist; @@ -11996,12 +12030,12 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = Sync/Other/Info.plist; @@ -12040,11 +12074,11 @@ CLANG_WARN_PRIVATE_MODULE = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -12086,11 +12120,11 @@ CLANG_WARN_PRIVATE_MODULE = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -12130,12 +12164,12 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; GENERATE_INFOPLIST_FILE = YES; @@ -12177,12 +12211,12 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; GENERATE_INFOPLIST_FILE = YES; @@ -12225,7 +12259,7 @@ CODE_SIGN_ENTITLEMENTS = "TwoFASWatch Watch App/TwoFASWatch Watch App.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_ASSET_PATHS = "\"TwoFASWatch Watch App/Preview Content\""; DEVELOPMENT_TEAM = ZY8UR5ADFW; ENABLE_PREVIEWS = YES; @@ -12268,7 +12302,7 @@ CODE_SIGN_ENTITLEMENTS = "TwoFASWatch Watch App/TwoFASWatch Watch App.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_ASSET_PATHS = "\"TwoFASWatch Watch App/Preview Content\""; DEVELOPMENT_TEAM = ZY8UR5ADFW; ENABLE_PREVIEWS = YES; @@ -12306,11 +12340,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -12355,11 +12389,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -12402,11 +12436,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -12451,11 +12485,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -12498,12 +12532,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = ""; @@ -12545,12 +12579,12 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; FRAMEWORK_SEARCH_PATHS = ""; @@ -12590,7 +12624,7 @@ CODE_SIGN_ENTITLEMENTS = TwoFASAuth/TwoFASAuth.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = ZY8UR5ADFW; FRAMEWORK_SEARCH_PATHS = ""; @@ -12624,7 +12658,7 @@ CODE_SIGN_ENTITLEMENTS = TwoFASAuth/TwoFASAuth.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ZY8UR5ADFW; FRAMEWORK_SEARCH_PATHS = ""; @@ -12659,12 +12693,12 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = TimeVerification/Info.plist; @@ -12705,12 +12739,12 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; INFOPLIST_FILE = TimeVerification/Info.plist; @@ -12748,11 +12782,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -12796,11 +12830,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = NO; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -12842,7 +12876,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = ZY8UR5ADFW; INFOPLIST_FILE = TwoFASTests/Info.plist; @@ -12872,7 +12906,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = ZY8UR5ADFW; INFOPLIST_FILE = TwoFASTests/Info.plist; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Two Factor Authentication Service, Inc. All rights reserved."; @@ -12904,7 +12938,7 @@ CODE_SIGN_ENTITLEMENTS = TwoFAS/Other/TwoFASWidgetExtension.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = ZY8UR5ADFW; INFOPLIST_FILE = TwoFASWidget/Info.plist; @@ -12940,7 +12974,7 @@ CODE_SIGN_ENTITLEMENTS = TwoFAS/Other/TwoFASWidgetExtension.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ZY8UR5ADFW; INFOPLIST_FILE = TwoFASWidget/Info.plist; @@ -12973,7 +13007,7 @@ CODE_SIGN_ENTITLEMENTS = TwoFASServiceIntent/TwoFASServiceIntent.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = ZY8UR5ADFW; INFOPLIST_FILE = TwoFASServiceIntent/Info.plist; @@ -13007,7 +13041,7 @@ CODE_SIGN_ENTITLEMENTS = TwoFASServiceIntent/TwoFASServiceIntent.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ZY8UR5ADFW; INFOPLIST_FILE = TwoFASServiceIntent/Info.plist; @@ -13039,7 +13073,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = ZY8UR5ADFW; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -13068,7 +13102,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = ZY8UR5ADFW; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -13096,11 +13130,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -13143,11 +13177,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -13188,11 +13222,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -13235,11 +13269,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -13280,11 +13314,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -13328,11 +13362,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -13374,11 +13408,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -13422,11 +13456,11 @@ CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ZY8UR5ADFW; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 4; + DYLIB_CURRENT_VERSION = 7; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_MODULE_VERIFIER = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -13466,7 +13500,7 @@ buildSettings = { CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = ZY8UR5ADFW; INFOPLIST_FILE = ProtectionTests/Info.plist; @@ -13497,7 +13531,7 @@ buildSettings = { CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = ZY8UR5ADFW; INFOPLIST_FILE = ProtectionTests/Info.plist; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Two Factor Authentication Service, Inc. All rights reserved."; diff --git a/TwoFAS/TwoFAS/Other/Generated/T.generated.swift b/TwoFAS/TwoFAS/Other/Generated/T.generated.swift index ae0a2009..50a99662 100644 --- a/TwoFAS/TwoFAS/Other/Generated/T.generated.swift +++ b/TwoFAS/TwoFAS/Other/Generated/T.generated.swift @@ -860,7 +860,7 @@ internal enum T { internal static let backupIcloudCta = T.tr("Localizable", "introduction__backup_icloud_cta", fallback: "Learn more about backup") /// 2FAS uses iCloud for secure backup and sync of your 2FA tokens. The **encrypted** backup data is stored in iCloud, accessible **only by the 2FAS app**. Additionally, this feature aids with token **recovery and syncing** across iOS devices. /// - /// It's enabled by default and can disabled at any time in the app's backup settings. + /// It's enabled by default and can be disabled at any time in the app's backup settings. internal static let backupIcloudDescription = T.tr("Localizable", "introduction__backup_icloud_description", fallback: "2FAS uses iCloud for secure backup and sync of your 2FA tokens. The **encrypted** backup data is stored in iCloud, accessible **only by the 2FAS app**. Additionally, this feature aids with token **recovery and syncing** across iOS devices.\n\nIt's enabled by default and can be disabled at any time in the app's backup settings.") /// Secure sync and backup internal static let backupIcloudTitle = T.tr("Localizable", "introduction__backup_icloud_title", fallback: "Secure sync and backup") @@ -912,8 +912,8 @@ internal enum T { internal enum NewVersion { /// A new version of 2FAS is available on Google Store. Update now! internal static let newVersionMessageAndroid = T.tr("Localizable", "new_version__new_version_message_android", fallback: "A new version of 2FAS is available on Google Store. Update now!") - /// A new version of 2FAS is available on AppStore. Update now! - internal static let newVersionMessageIos = T.tr("Localizable", "new_version__new_version_message_ios", fallback: "A new version of 2FAS is available on AppStore. Update now!") + /// A new version of 2FAS is available on App Store. Update now! + internal static let newVersionMessageIos = T.tr("Localizable", "new_version__new_version_message_ios", fallback: "A new version of 2FAS is available on App Store. Update now!") /// New version internal static let newVersionTitle = T.tr("Localizable", "new_version__new_version_title", fallback: "New version") /// Skip this version @@ -1626,6 +1626,8 @@ internal enum T { internal enum Widget { /// My secured account internal static let mySecuredAccount = T.tr("Localizable", "widget__my_secured_account", fallback: "My secured account") + /// Hold and select service to activate widget... + internal static let noSelectedServices = T.tr("Localizable", "widget__no_selected_services", fallback: "Hold and select service to activate widget...") /// There are no services in the app available for selection internal static let noServices = T.tr("Localizable", "widget__no_services", fallback: "There are no services in the app available for selection") /// Widget functionality is not enabled in 2FAS Settings section @@ -1634,6 +1636,10 @@ internal enum T { internal static let notEnabledNoServices = T.tr("Localizable", "widget__not_enabled_no_services", fallback: "Widget functionality is not enabled in 2FAS Settings section and there are no services in the app available for selection") /// Placeholder internal static let placeholder = T.tr("Localizable", "widget__placeholder", fallback: "Placeholder") + /// Reveal your 2FAS tokens for 60 seconds + internal static let revealTokensLongMessage = T.tr("Localizable", "widget__reveal_tokens_long_message", fallback: "Reveal your 2FAS tokens for 60 seconds") + /// Reveal for 60 seconds + internal static let revealTokensShortMessage = T.tr("Localizable", "widget__reveal_tokens_short_message", fallback: "Reveal for 60 seconds") /// Select Service you want to show on your 2FAS Widget internal static let selectServiceIntentDescription = T.tr("Localizable", "widget__select_service_intent_description", fallback: "Select Service you want to show on your 2FAS Widget") /// Service icon diff --git a/TwoFAS/TwoFAS/Other/de.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/de.lproj/Localizable.strings index 7fdb282f..3a490946 100644 Binary files a/TwoFAS/TwoFAS/Other/de.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/de.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/el.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/el.lproj/Localizable.strings index 4f365976..223f974e 100644 Binary files a/TwoFAS/TwoFAS/Other/el.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/el.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/en.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/en.lproj/Localizable.strings index daf70550..c58c826f 100644 Binary files a/TwoFAS/TwoFAS/Other/en.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/en.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/es.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/es.lproj/Localizable.strings index 308ac120..07f7927e 100644 Binary files a/TwoFAS/TwoFAS/Other/es.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/es.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/fr.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/fr.lproj/Localizable.strings index 4924fc4b..183784ad 100644 Binary files a/TwoFAS/TwoFAS/Other/fr.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/fr.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/id.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/id.lproj/Localizable.strings index 44bff7b7..23463b1b 100644 Binary files a/TwoFAS/TwoFAS/Other/id.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/id.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/it.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/it.lproj/Localizable.strings index 06a167ea..ed1a6fcb 100644 Binary files a/TwoFAS/TwoFAS/Other/it.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/it.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/ja.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/ja.lproj/Localizable.strings index 28c7ede1..b3822c21 100644 Binary files a/TwoFAS/TwoFAS/Other/ja.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/ja.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/nl.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/nl.lproj/Localizable.strings index 2ccd2800..e4cafbfa 100644 Binary files a/TwoFAS/TwoFAS/Other/nl.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/nl.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/pl.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/pl.lproj/Localizable.strings index 90717935..2f58061c 100644 Binary files a/TwoFAS/TwoFAS/Other/pl.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/pl.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/pt-PT.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/pt-PT.lproj/Localizable.strings index 603f5c4c..b597e3d4 100644 Binary files a/TwoFAS/TwoFAS/Other/pt-PT.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/pt-PT.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/tr.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/tr.lproj/Localizable.strings index 1fbcd3ab..3354d79a 100644 Binary files a/TwoFAS/TwoFAS/Other/tr.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/tr.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/uk.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/uk.lproj/Localizable.strings index c31fe89d..899130ea 100644 Binary files a/TwoFAS/TwoFAS/Other/uk.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/uk.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFAS/Other/zh-Hans.lproj/Localizable.strings b/TwoFAS/TwoFAS/Other/zh-Hans.lproj/Localizable.strings index 0c1afbae..8d469efd 100644 Binary files a/TwoFAS/TwoFAS/Other/zh-Hans.lproj/Localizable.strings and b/TwoFAS/TwoFAS/Other/zh-Hans.lproj/Localizable.strings differ diff --git a/TwoFAS/TwoFASAuth/Generated/T.generated.swift b/TwoFAS/TwoFASAuth/Generated/T.generated.swift index ca14ad67..50a99662 100644 --- a/TwoFAS/TwoFASAuth/Generated/T.generated.swift +++ b/TwoFAS/TwoFASAuth/Generated/T.generated.swift @@ -860,8 +860,8 @@ internal enum T { internal static let backupIcloudCta = T.tr("Localizable", "introduction__backup_icloud_cta", fallback: "Learn more about backup") /// 2FAS uses iCloud for secure backup and sync of your 2FA tokens. The **encrypted** backup data is stored in iCloud, accessible **only by the 2FAS app**. Additionally, this feature aids with token **recovery and syncing** across iOS devices. /// - /// It's enabled by default and can disabled at any time in the app's backup settings. - internal static let backupIcloudDescription = T.tr("Localizable", "introduction__backup_icloud_description", fallback: "2FAS uses iCloud for secure backup and sync of your 2FA tokens. The **encrypted** backup data is stored in iCloud, accessible **only by the 2FAS app**. Additionally, this feature aids with token **recovery and syncing** across iOS devices.\n\nIt's enabled by default and can disabled at any time in the app's backup settings.") + /// It's enabled by default and can be disabled at any time in the app's backup settings. + internal static let backupIcloudDescription = T.tr("Localizable", "introduction__backup_icloud_description", fallback: "2FAS uses iCloud for secure backup and sync of your 2FA tokens. The **encrypted** backup data is stored in iCloud, accessible **only by the 2FAS app**. Additionally, this feature aids with token **recovery and syncing** across iOS devices.\n\nIt's enabled by default and can be disabled at any time in the app's backup settings.") /// Secure sync and backup internal static let backupIcloudTitle = T.tr("Localizable", "introduction__backup_icloud_title", fallback: "Secure sync and backup") /// Google Drive sync turned on successfully! @@ -912,8 +912,8 @@ internal enum T { internal enum NewVersion { /// A new version of 2FAS is available on Google Store. Update now! internal static let newVersionMessageAndroid = T.tr("Localizable", "new_version__new_version_message_android", fallback: "A new version of 2FAS is available on Google Store. Update now!") - /// A new version of 2FAS is available on AppStore. Update now! - internal static let newVersionMessageIos = T.tr("Localizable", "new_version__new_version_message_ios", fallback: "A new version of 2FAS is available on AppStore. Update now!") + /// A new version of 2FAS is available on App Store. Update now! + internal static let newVersionMessageIos = T.tr("Localizable", "new_version__new_version_message_ios", fallback: "A new version of 2FAS is available on App Store. Update now!") /// New version internal static let newVersionTitle = T.tr("Localizable", "new_version__new_version_title", fallback: "New version") /// Skip this version @@ -1626,6 +1626,8 @@ internal enum T { internal enum Widget { /// My secured account internal static let mySecuredAccount = T.tr("Localizable", "widget__my_secured_account", fallback: "My secured account") + /// Hold and select service to activate widget... + internal static let noSelectedServices = T.tr("Localizable", "widget__no_selected_services", fallback: "Hold and select service to activate widget...") /// There are no services in the app available for selection internal static let noServices = T.tr("Localizable", "widget__no_services", fallback: "There are no services in the app available for selection") /// Widget functionality is not enabled in 2FAS Settings section @@ -1634,6 +1636,10 @@ internal enum T { internal static let notEnabledNoServices = T.tr("Localizable", "widget__not_enabled_no_services", fallback: "Widget functionality is not enabled in 2FAS Settings section and there are no services in the app available for selection") /// Placeholder internal static let placeholder = T.tr("Localizable", "widget__placeholder", fallback: "Placeholder") + /// Reveal your 2FAS tokens for 60 seconds + internal static let revealTokensLongMessage = T.tr("Localizable", "widget__reveal_tokens_long_message", fallback: "Reveal your 2FAS tokens for 60 seconds") + /// Reveal for 60 seconds + internal static let revealTokensShortMessage = T.tr("Localizable", "widget__reveal_tokens_short_message", fallback: "Reveal for 60 seconds") /// Select Service you want to show on your 2FAS Widget internal static let selectServiceIntentDescription = T.tr("Localizable", "widget__select_service_intent_description", fallback: "Select Service you want to show on your 2FAS Widget") /// Service icon diff --git a/TwoFAS/TwoFASWidget/AppIntent/AppIntentProvider.swift b/TwoFAS/TwoFASWidget/AppIntent/AppIntentProvider.swift index b2c06f7b..77e87a21 100644 --- a/TwoFAS/TwoFASWidget/AppIntent/AppIntentProvider.swift +++ b/TwoFAS/TwoFASWidget/AppIntent/AppIntentProvider.swift @@ -29,7 +29,7 @@ import TimeVerification @available(iOS 17.0, macOS 14.0, watchOS 10.0, *) struct AppIntentProvider: AppIntentTimelineProvider { - private let defaults = UserDefaults.standard + private let defaults = UserDefaults(suiteName: "group.twofas.com") private let calendar = Calendar.current typealias Intent = SelectService @@ -129,7 +129,7 @@ struct AppIntentProvider: AppIntentTimelineProvider { guard case Values.entry(let entryDescription) = value else { return CodeEntry.Entry.placeholder() } - let showWithCode = !isLast && entryDescription.isValidSecret + let showWithCode = !isLast let secondsToNewOne: Int = { let period = entryDescription.period.rawValue let currentSeconds: Int = calendar.component(.second, from: tokenDate) @@ -204,19 +204,18 @@ struct AppIntentProvider: AppIntentTimelineProvider { @available(iOS 17.0, macOS 14.0, watchOS 10.0, *) extension AppIntentProvider { private func clearDefaults() { - defaults.removeObject(forKey: CommonKeys.tapDate) - defaults.removeObject(forKey: CommonKeys.tapSecret) - defaults.synchronize() + defaults?.removeObject(forKey: CommonKeys.tapDate) + defaults?.removeObject(forKey: CommonKeys.tapSecret) + defaults?.synchronize() } private func handleClickableWidgets() -> (validSecret: Secret?, secondsLeft: Int) { let validSecret: Secret? let secondsLeft: Int - let dateValue = defaults.double(forKey: "tapDate") - if !dateValue.isZero { + if let dateValue = defaults?.double(forKey: "tapDate"), !dateValue.isZero { let duration = Date().timeIntervalSince1970 - dateValue - if duration < 60.0, let storedSecret = defaults.string(forKey: "tapSecret") { + if duration < 60.0, let storedSecret = defaults?.string(forKey: "tapSecret") { secondsLeft = 60 - Int(duration) validSecret = storedSecret } else { diff --git a/TwoFAS/TwoFASWidget/AppIntent/RevealTokenAppIntent.swift b/TwoFAS/TwoFASWidget/AppIntent/RevealTokenAppIntent.swift index 0ebd58d0..74b3f488 100644 --- a/TwoFAS/TwoFASWidget/AppIntent/RevealTokenAppIntent.swift +++ b/TwoFAS/TwoFASWidget/AppIntent/RevealTokenAppIntent.swift @@ -39,10 +39,10 @@ struct RevealTokenAppIntent: AppIntent { @MainActor func perform() async throws -> some IntentResult { - let defaults = UserDefaults.standard - defaults.set(Date().timeIntervalSince1970, forKey: CommonKeys.tapDate) - defaults.set(secret, forKey: CommonKeys.tapSecret) - defaults.synchronize() + let defaults = UserDefaults(suiteName: "group.twofas.com") + defaults?.set(Date().timeIntervalSince1970, forKey: CommonKeys.tapDate) + defaults?.set(secret, forKey: CommonKeys.tapSecret) + defaults?.synchronize() return .result() } diff --git a/TwoFAS/TwoFASWidget/AppIntent/ServiceAppEntity.swift b/TwoFAS/TwoFASWidget/AppIntent/ServiceAppEntity.swift index 92a91fc8..0772dabf 100644 --- a/TwoFAS/TwoFASWidget/AppIntent/ServiceAppEntity.swift +++ b/TwoFAS/TwoFASWidget/AppIntent/ServiceAppEntity.swift @@ -35,7 +35,7 @@ struct ServiceAppEntity: AppEntity { SelectedItems.list = identifiers return AccessManager.serviceHandler.listAll(search: nil, exclude: []) .flatMap({ $0.services }) - .filter({ identifiers.contains($0.serviceID) && $0.period != .period10 }) + .filter({ identifiers.contains($0.serviceID) }) .map({ service in ServiceAppEntity( id: service.serviceID, @@ -57,7 +57,7 @@ struct ServiceAppEntity: AppEntity { let all: [WidgetCategory] = AccessManager.serviceHandler.listAll(search: nil, exclude: []) let sections = all.map({ category -> ItemSection in let services: [Item] = category.services - .filter({ !SelectedItems.list.contains($0.serviceID) && $0.period != .period10 }) + .filter({ !SelectedItems.list.contains($0.serviceID) }) .map({ service in let icon = service.icon.pngData() let image: DisplayRepresentation.Image? = { diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/AccentColor.colorset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/AccentColor.colorset/Contents.json similarity index 76% rename from TwoFAS/TwoFASWidget/Assets.xcassets/AccentColor.colorset/Contents.json rename to TwoFAS/TwoFASWidget/Assets.xcassets/Colors/AccentColor.colorset/Contents.json index 19533fff..4a3af36e 100644 --- a/TwoFAS/TwoFASWidget/Assets.xcassets/AccentColor.colorset/Contents.json +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/AccentColor.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.137", - "green" : "0.110", - "red" : "0.929" + "blue" : "0x22", + "green" : "0x1C", + "red" : "0xEC" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.137", - "green" : "0.110", - "red" : "0.898" + "blue" : "0x22", + "green" : "0x1C", + "red" : "0xE4" } }, "idiom" : "universal" diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/Gray5.colorset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/Gray5.colorset/Contents.json new file mode 100644 index 00000000..d4a52c11 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/Gray5.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xEA", + "green" : "0xE5", + "red" : "0xE5" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/WidgetBackground.colorset/Contents.json similarity index 100% rename from TwoFAS/TwoFASWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json rename to TwoFAS/TwoFASWidget/Assets.xcassets/Colors/WidgetBackground.colorset/Contents.json diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/gray10.colorset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/gray10.colorset/Contents.json new file mode 100644 index 00000000..f09de42a --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/gray10.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x9D", + "green" : "0x9D", + "red" : "0x9D" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x9D", + "green" : "0x9D", + "red" : "0x9D" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/gray15.colorset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/gray15.colorset/Contents.json new file mode 100644 index 00000000..d9e8dca0 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/gray15.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xED", + "green" : "0xED", + "red" : "0xED" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x35", + "green" : "0x35", + "red" : "0x35" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textAccent.colorset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textAccent.colorset/Contents.json new file mode 100644 index 00000000..a3090acb --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textAccent.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xEA", + "green" : "0xEA", + "red" : "0xEA" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textPrimary.colorset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textPrimary.colorset/Contents.json new file mode 100644 index 00000000..0c600f92 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textPrimary.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x00", + "green" : "0x00", + "red" : "0x00" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textSecondary.colorset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textSecondary.colorset/Contents.json new file mode 100644 index 00000000..796b0cf1 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Colors/textSecondary.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x4A", + "green" : "0x4A", + "red" : "0x4A" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x9D", + "green" : "0x9D", + "red" : "0x9D" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Images/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/LogoWidgetMono.imageset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/LogoWidgetMono.imageset/Contents.json similarity index 100% rename from TwoFAS/TwoFASWidget/Assets.xcassets/LogoWidgetMono.imageset/Contents.json rename to TwoFAS/TwoFASWidget/Assets.xcassets/Images/LogoWidgetMono.imageset/Contents.json diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/LogoWidgetMono.imageset/TwoFASLogoWidget.pdf b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/LogoWidgetMono.imageset/TwoFASLogoWidget.pdf similarity index 100% rename from TwoFAS/TwoFASWidget/Assets.xcassets/LogoWidgetMono.imageset/TwoFASLogoWidget.pdf rename to TwoFAS/TwoFASWidget/Assets.xcassets/Images/LogoWidgetMono.imageset/TwoFASLogoWidget.pdf diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASLogo.imageset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASLogo.imageset/Contents.json new file mode 100644 index 00000000..3c9be6d1 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASLogo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "SIGN.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASLogo.imageset/SIGN.pdf b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASLogo.imageset/SIGN.pdf new file mode 100644 index 00000000..b4e8b00c Binary files /dev/null and b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASLogo.imageset/SIGN.pdf differ diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/TwoFASMainService.imageset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASMainService.imageset/Contents.json similarity index 100% rename from TwoFAS/TwoFASWidget/Assets.xcassets/TwoFASMainService.imageset/Contents.json rename to TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASMainService.imageset/Contents.json diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/TwoFASMainService.imageset/unknown.png b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASMainService.imageset/unknown.png similarity index 100% rename from TwoFAS/TwoFASWidget/Assets.xcassets/TwoFASMainService.imageset/unknown.png rename to TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASMainService.imageset/unknown.png diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/TwoFASMainService.imageset/unknown@2x.png b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASMainService.imageset/unknown@2x.png similarity index 100% rename from TwoFAS/TwoFASWidget/Assets.xcassets/TwoFASMainService.imageset/unknown@2x.png rename to TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASMainService.imageset/unknown@2x.png diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/TwoFASMainService.imageset/unknown@3x.png b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASMainService.imageset/unknown@3x.png similarity index 100% rename from TwoFAS/TwoFASWidget/Assets.xcassets/TwoFASMainService.imageset/unknown@3x.png rename to TwoFAS/TwoFASWidget/Assets.xcassets/Images/TwoFASMainService.imageset/unknown@3x.png diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Images/eye.slash2.imageset/Contents.json b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/eye.slash2.imageset/Contents.json new file mode 100644 index 00000000..aed18b57 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/eye.slash2.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "eye.slash2.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TwoFAS/TwoFASWidget/Assets.xcassets/Images/eye.slash2.imageset/eye.slash2.pdf b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/eye.slash2.imageset/eye.slash2.pdf new file mode 100644 index 00000000..5e5fc914 Binary files /dev/null and b/TwoFAS/TwoFASWidget/Assets.xcassets/Images/eye.slash2.imageset/eye.slash2.pdf differ diff --git a/TwoFAS/TwoFASWidget/Components/CountdownTimerText.swift b/TwoFAS/TwoFASWidget/Components/CountdownTimerText.swift new file mode 100644 index 00000000..1d3c7c58 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Components/CountdownTimerText.swift @@ -0,0 +1,41 @@ +// +// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios) +// Copyright © 2024 Two Factor Authentication Service, Inc. +// Contributed by Grzegorz Machnio. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// +import SwiftUI + +struct CountdownTimerText: View { + let date: Date? + + private var timerText: some View { + if let countdownTo = date { + Text(countdownTo, style: .timer) + } else { + Text("0:00") + } + } + + var body: some View { + timerText + .frame(width: 40, height: 18) + .foregroundStyle(.textPrimary) + .multilineTextAlignment(.trailing) + .font(.caption.weight(.semibold)) + .lineLimit(1) + .contentTransition(.numericText(countsDown: true)) + } +} diff --git a/TwoFAS/TwoFASWidget/Components/RevealTokenImage.swift b/TwoFAS/TwoFASWidget/Components/RevealTokenImage.swift new file mode 100644 index 00000000..e2c7d338 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Components/RevealTokenImage.swift @@ -0,0 +1,30 @@ +// +// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios) +// Copyright © 2024 Two Factor Authentication Service, Inc. +// Contributed by Grzegorz Machnio. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// +import SwiftUI + +struct RevealTokenImage: View { + var body: some View { + Image("eye.slash2") + .background( + Circle() + .fill(Color.gray5) + .frame(width: 40, height: 40) + ) + } +} diff --git a/TwoFAS/TwoFASWidget/Components/RevealTokenOverlayView.swift b/TwoFAS/TwoFASWidget/Components/RevealTokenOverlayView.swift new file mode 100644 index 00000000..9ab00c52 --- /dev/null +++ b/TwoFAS/TwoFASWidget/Components/RevealTokenOverlayView.swift @@ -0,0 +1,79 @@ +// +// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios) +// Copyright © 2024 Two Factor Authentication Service, Inc. +// Contributed by Grzegorz Machnio. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// + +import SwiftUI +import Common + +struct RevealTokenOverlayView: View { + enum RevealTokenMessageType { + case short, long + + var message: String { + switch self { + case .short: return T.Widget.revealTokensShortMessage + case .long: return T.Widget.revealTokensLongMessage + } + } + } + + @Environment(\.widgetFamily) var family + + var body: some View { + switch family { + case .systemSmall: + VStack { + Spacer() + RevealTokenImage() + .frame(width: 40, height: 40) + Spacer() + revealText(type: .short) + } + case .systemMedium: + VStack { + Spacer() + RevealTokenImage() + .frame(width: 40, height: 40) + Spacer() + revealText(type: .long) + } + .padding(.bottom, 14) + case .systemLarge, .systemExtraLarge: + VStack(spacing: 12) { + Spacer() + RevealTokenImage() + .frame(width: 40, height: 40) + revealText(type: .long) + Spacer() + } + default: + VStack { + Spacer() + RevealTokenImage() + Spacer() + revealText(type: .short) + } + } + } + + private func revealText(type: RevealTokenMessageType) -> some View { + Text(type.message) + .foregroundStyle(.gray10) + .font(.caption2) + } +} diff --git a/TwoFAS/TwoFASWidget/IconRenderer.swift b/TwoFAS/TwoFASWidget/IconRenderer.swift index 9c24b951..dd85aadd 100644 --- a/TwoFAS/TwoFASWidget/IconRenderer.swift +++ b/TwoFAS/TwoFASWidget/IconRenderer.swift @@ -31,6 +31,7 @@ struct IconRenderer: View { case .brand: Image(uiImage: ServiceIcon.for(iconTypeID: entry.data.iconTypeID)) .resizable() + .frame(width: 24, height: 24) case .label: ZStack(alignment: .center) { Circle() diff --git a/TwoFAS/TwoFASWidget/CopyIntentButton.swift b/TwoFAS/TwoFASWidget/IntentButtons/CopyIntentButton.swift similarity index 91% rename from TwoFAS/TwoFASWidget/CopyIntentButton.swift rename to TwoFAS/TwoFASWidget/IntentButtons/CopyIntentButton.swift index 90a9ecd1..d1843b25 100644 --- a/TwoFAS/TwoFASWidget/CopyIntentButton.swift +++ b/TwoFAS/TwoFASWidget/IntentButtons/CopyIntentButton.swift @@ -23,10 +23,14 @@ import AppIntents struct CopyIntentButton: View where Content: View { private let appIntent: (any AppIntent)? private let content: () -> Content - + // TODO: Add support for NIL app intent - ios 16 - init(rawEntry: CodeEntry.EntryData.RawEntryData?, secret: String?, @ViewBuilder content: @escaping () -> Content) { + init( + rawEntry: CodeEntry.EntryData.RawEntryData?, + secret: String? = nil, + @ViewBuilder content: @escaping () -> Content + ) { if let rawEntry { self.appIntent = CopyTokenIntent( secret: rawEntry.secret, @@ -34,7 +38,7 @@ struct CopyIntentButton: View where Content: View { digits: rawEntry.digits, algorithm: rawEntry.algorithm, tokenType: rawEntry.tokenType - ) + ) } else if let secret { self.appIntent = RevealTokenAppIntent(secret: secret) } else { diff --git a/TwoFAS/TwoFASWidget/IntentButtons/RevealTokenIntentButton.swift b/TwoFAS/TwoFASWidget/IntentButtons/RevealTokenIntentButton.swift new file mode 100644 index 00000000..99cdef58 --- /dev/null +++ b/TwoFAS/TwoFASWidget/IntentButtons/RevealTokenIntentButton.swift @@ -0,0 +1,43 @@ +// +// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios) +// Copyright © 2024 Two Factor Authentication Service, Inc. +// Contributed by Grzegorz Machnio. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// + +import SwiftUI +import AppIntents + +struct RevealTokenIntentButton: View where Content: View { + private let appIntent: any AppIntent + private let content: () -> Content + + init(secret: String, @ViewBuilder content: @escaping () -> Content) { + self.appIntent = RevealTokenAppIntent(secret: secret) + self.content = content + } + + @ViewBuilder + var body: some View { + if #available(iOS 17.0, *) { + Button(intent: appIntent, label: { + content() + }) + .buttonStyle(.plain) + } else { + content() + } + } +} diff --git a/TwoFAS/TwoFASWidget/Provider.swift b/TwoFAS/TwoFASWidget/Provider.swift index ecafe2cd..f2d79171 100644 --- a/TwoFAS/TwoFASWidget/Provider.swift +++ b/TwoFAS/TwoFASWidget/Provider.swift @@ -84,7 +84,6 @@ struct Provider: IntentTimelineProvider { let selectedServices = configuration.service ?? [] let currentServices = serviceHandler.listServices(with: selectedServices.compactMap { $0.secret }) - .filter({ $0.period != .period10 }) var entries: [CodeEntry] = [] diff --git a/TwoFAS/TwoFASWidget/TwoFASWidget.swift b/TwoFAS/TwoFASWidget/TwoFASWidget.swift index 69ed30ea..765cbdbd 100644 --- a/TwoFAS/TwoFASWidget/TwoFASWidget.swift +++ b/TwoFAS/TwoFASWidget/TwoFASWidget.swift @@ -20,38 +20,65 @@ import WidgetKit import SwiftUI import Intents +import Common struct TwoFASWidgetEntryView: View { var entry: Provider.Entry @Environment(\.widgetFamily) var family + + private var noEntryView: some View { + VStack(alignment: .leading) { + Image("TwoFASLogo") + .foregroundStyle(.white) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(.widgetBackground) + .frame(width: 32, height: 32) + ) + + Spacer() + + Text(T.Widget.noSelectedServices) + .foregroundStyle(.textAccent) + .multilineTextAlignment(.leading) + .font(.system(size: 16).weight(.semibold)) + .bold() + .frame(maxWidth: 200, alignment: .leading) + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) + .padding(4) + .addWidgetContentMargins() + .widgetBackground(backgroundView: Color.accent) + } @ViewBuilder var body: some View { - Group { - switch family { - case .systemSmall: - TwoFASWidgetSquareView(entry: entry.entries.first) - case .systemMedium: - TwoFASWidgetLineView(entries: entry.entries) - case .systemLarge: - TwoFASWidgetLineView(entries: entry.entries) - case .systemExtraLarge: - TwoFASWidgetLineViewGrid(entries: entry.entries) - case .accessoryCircular: - TwoFASWidgetCircular(entry: entry.entries.first) - case .accessoryRectangular: - TwoFASWidgetRectangular(entry: entry.entries.first) - case .accessoryInline: - TwoFASWidgetInline(entry: entry.entries.first) - default: - Text("widget__size_not_supported") + if entry.entries.isEmpty || entry.entries.filter({ $0.kind != .placeholder }).isEmpty { + noEntryView + } else { + Group { + switch family { + case .systemSmall: + TwoFASWidgetSquareView(entry: entry.entries.first) + case .systemMedium: + TwoFASWidgetLineView(entries: entry.entries, isRevealTokenOverlayVisible: true) + case .systemLarge: + TwoFASWidgetLineView(entries: entry.entries, isRevealTokenOverlayVisible: true) + case .systemExtraLarge: + TwoFASWidgetLineViewGrid(entries: entry.entries) + case .accessoryCircular: + TwoFASWidgetCircular(entry: entry.entries.first) + case .accessoryRectangular: + TwoFASWidgetRectangular(entry: entry.entries.first) + case .accessoryInline: + TwoFASWidgetInline(entry: entry.entries.first) + default: + Text("widget__size_not_supported") + } } + .widgetBackground(backgroundView: Color.widgetBackground) + .addWidgetContentMargins() } - .widgetBackground(backgroundView: backgroundView) - } - - private var backgroundView: some View { - Color.clear } } @@ -119,7 +146,9 @@ struct TwoFASWidget_Previews: PreviewProvider { extension View { func widgetBackground(backgroundView: some View) -> some View { if #available(iOSApplicationExtension 17.0, *) { - return containerBackground(for: .widget) {} + return containerBackground(for: .widget) { + backgroundView + } } else { return background(backgroundView) } diff --git a/TwoFAS/TwoFASWidget/TwoFASWidgetLineView.swift b/TwoFAS/TwoFASWidget/TwoFASWidgetLineView.swift index 324a1317..41de38ab 100644 --- a/TwoFAS/TwoFASWidget/TwoFASWidgetLineView.swift +++ b/TwoFAS/TwoFASWidget/TwoFASWidgetLineView.swift @@ -24,114 +24,106 @@ import Common struct TwoFASWidgetLineView: View { @Environment(\.colorScheme) var colorScheme + private var isAnyEntryHidden: Bool { + entries.contains { $0.kind == .singleEntryHidden } + } private let spacing: CGFloat = 10 let entries: [CodeEntry.Entry] + let isRevealTokenOverlayVisible: Bool @ViewBuilder var body: some View { - ForEach(entries, id: \.self) { entry in - let kind = entry.kind - - let reason: RedactionReasons = { - switch kind { - case .placeholder: return .placeholder - default: return [] - } - }() - - let codeReason: RedactionReason = { - switch kind { - case .placeholder, .singleEntryHidden: return .codePlaceholder - default: return .noPlaceholder - } - }() - - let countDownReason: RedactionReasons = { - switch kind { - case .placeholder, .singleEntryHidden: return .placeholder - default: return [] - } - }() - - generateLine( - entry: entry, - data: entry.data, - reason: reason, - codeReason: codeReason, - countDownReason: countDownReason - ) + VStack(spacing: 0) { + ForEach(entries.filter { $0.kind != .placeholder }, id: \.self) { entry in + let kind = entry.kind + let reason: RedactionReasons = { + switch kind { + case .placeholder: return .placeholder + default: return [] + } + }() + let codeReason: RedactionReason = { + switch kind { + case .placeholder, .singleEntryHidden: return .codePlaceholder + default: return .noPlaceholder + } + }() + + generateLine( + entry: entry, + data: entry.data, + reason: reason + ) + .frame(height: 49) .accessibility(hidden: codeReason == .codePlaceholder) .overlay { - CopyIntentButton( - rawEntry: entry.data.rawEntry, - secret: kind == .singleEntryHidden ? entry.data.secret : nil - ) { + CopyIntentButton(rawEntry: entry.data.rawEntry) { Rectangle() .foregroundStyle(Color.clear) .frame(maxWidth: .infinity, maxHeight: .infinity) } } + + if entry != entries.filter({ $0.kind != .placeholder }).last { + Divider() + .foregroundStyle(.gray15) + } + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + .blur(radius: isAnyEntryHidden ? 21 : 0) + .overlay { + if isRevealTokenOverlayVisible, isAnyEntryHidden, let secret = entries.first?.data.secret { + RevealTokenIntentButton(secret: secret) { + RevealTokenOverlayView() + } + } } - .addWidgetContentMargins(standard: spacing) } @ViewBuilder private func generateLine( entry: CodeEntry.Entry, data: CodeEntry.EntryData, - reason: RedactionReasons, - codeReason: RedactionReason, - countDownReason: RedactionReasons + reason: RedactionReasons ) -> some View { - HStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) { + HStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 0) { IconRenderer(entry: entry) .frame(width: 24) + .scaledToFit() + .padding(.trailing, 12) .redacted(reason: reason) - VStack(alignment: .leading, spacing: 3) { + + VStack(alignment: .leading, spacing: 2) { Text(data.name) - .font(.caption2) - .multilineTextAlignment(.leading) + .foregroundStyle(.textPrimary) + .font(.system(size: 11).weight(.regular)) .redacted(reason: reason) - .lineLimit(1) - let info = data.info ?? "" - Text(info) - .lineLimit(1) .multilineTextAlignment(.leading) - .font(.caption2) - .foregroundColor(.gray) - .redacted(reason: reason) - }.frame( - minWidth: 0, - maxWidth: .infinity, - minHeight: 0, - maxHeight: .infinity, - alignment: .topLeading - ) + .lineLimit(1) + + if let info = data.info, !info.isEmpty { + Text(info) + .foregroundStyle(.textSecondary) + .lineLimit(1) + .font(.system(size: 11).weight(.regular)) + } + } + + Spacer() + Text(verbatim: data.code) - .font(Font.system(.title).weight(.light).monospacedDigit()) - .multilineTextAlignment(.leading) - .minimumScaleFactor(0.2) + .foregroundStyle(.textPrimary) + .font(.system(size: 27).weight(.light).monospacedDigit()) + .multilineTextAlignment(.center) + .minimumScaleFactor(0.1) .lineLimit(1) - .redacted(reason: codeReason) .contentTransition(.numericText()) - .frame(width: 100) - counterText(for: data.countdownTo) - .multilineTextAlignment(.trailing) - .font(Font.body.monospacedDigit()) - .contentTransition(.numericText(countsDown: true)) - .lineLimit(1) - .redacted(reason: countDownReason) - .frame(width: 40) - } - } - - @ViewBuilder - private func counterText(for date: Date?) -> some View { - if let countdownTo = date { - Text(countdownTo, style: .timer) - } else { - Text("0:00") + .redacted(reason: reason) + + CountdownTimerText(date: data.countdownTo) + .redacted(reason: reason) } } } diff --git a/TwoFAS/TwoFASWidget/TwoFASWidgetLineViewGrid.swift b/TwoFAS/TwoFASWidget/TwoFASWidgetLineViewGrid.swift index f42b19b5..5644a7b4 100644 --- a/TwoFAS/TwoFASWidget/TwoFASWidgetLineViewGrid.swift +++ b/TwoFAS/TwoFASWidget/TwoFASWidgetLineViewGrid.swift @@ -24,9 +24,13 @@ import Common struct TwoFASWidgetLineViewGrid: View { @Environment(\.colorScheme) var colorScheme - private let spacing: CGFloat = 8 + private let spacing: CGFloat = 16 private let minSize: CGFloat = 170 + private var isAnyEntryHidden: Bool { + entries.contains { $0.kind == .singleEntryHidden } + } + let entries: [CodeEntry.Entry] @ViewBuilder @@ -36,16 +40,24 @@ struct TwoFASWidgetLineViewGrid: View { let secondHalf = Array(entries.suffix(halfElements)) LazyVGrid( columns: [ - GridItem(.flexible(minimum: minSize)), - GridItem(.flexible(minimum: minSize)) + GridItem(.flexible(minimum: minSize), spacing: spacing), + GridItem(.flexible(minimum: minSize), spacing: spacing) ], alignment: .leading, - spacing: 2 * spacing, + spacing: spacing, pinnedViews: [], content: { - TwoFASWidgetLineView(entries: firstHalf) - TwoFASWidgetLineView(entries: secondHalf) - }) - .addWidgetContentMargins(standard: spacing) + TwoFASWidgetLineView(entries: firstHalf, isRevealTokenOverlayVisible: false) + TwoFASWidgetLineView(entries: secondHalf, isRevealTokenOverlayVisible: false) + } + ) + .overlay { + if isAnyEntryHidden, let secret = entries.first?.data.secret { + RevealTokenIntentButton(secret: secret) { + RevealTokenOverlayView() + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } + } } } diff --git a/TwoFAS/TwoFASWidget/TwoFASWidgetSquareView.swift b/TwoFAS/TwoFASWidget/TwoFASWidgetSquareView.swift index ded505a5..acc3206c 100644 --- a/TwoFAS/TwoFASWidget/TwoFASWidgetSquareView.swift +++ b/TwoFAS/TwoFASWidget/TwoFASWidgetSquareView.swift @@ -42,13 +42,6 @@ struct TwoFASWidgetSquareView: View { let entryData = entryValue.data let kind = entryValue.kind - let reason: RedactionReasons = { - switch kind { - case .placeholder: return .placeholder - default: return [] - } - }() - let codeReason: RedactionReason = { switch kind { case .placeholder, .singleEntryHidden: return .codePlaceholder @@ -56,56 +49,56 @@ struct TwoFASWidgetSquareView: View { } }() - let countDownReason: RedactionReasons = { - switch kind { - case .placeholder, .singleEntryHidden: return .placeholder - default: return [] - } - }() - if showLogo() { image() } else { - CopyIntentButton( - rawEntry: entryData.rawEntry, - secret: kind == .singleEntryHidden ? entry?.data.secret : nil - ) { - VStack(alignment: .leading, spacing: nil) { + VStack(alignment: .leading) { + HStack { + IconRenderer(entry: entryValue) + .frame(width: 32, height: 32) Spacer() - HStack(alignment: .center, spacing: nil) { - IconRenderer(entry: entryValue) - .redacted(reason: reason) - Spacer() - counterText(for: entryData.countdownTo) - .multilineTextAlignment(.trailing) - .font(Font.body.monospacedDigit()) - .lineLimit(1) - .redacted(reason: countDownReason) - .contentTransition(.numericText(countsDown: true)) - } - Spacer(minLength: spacing * 3) - VStack(alignment: .leading, spacing: 3) { - Text(entryData.name) - .font(.caption) - .multilineTextAlignment(.leading) - .redacted(reason: reason) - Text(entryData.code) - .font(Font.system(.title).weight(.light).monospacedDigit()) - .multilineTextAlignment(.leading) - .minimumScaleFactor(0.2) - .redacted(reason: codeReason) - .contentTransition(.numericText()) - let info = entryData.info ?? "" + CountdownTimerText(date: entryData.countdownTo) + .redacted(reason: codeReason) + } + + Spacer() + + VStack(alignment: .leading, spacing: 4) { + Text(entryData.name) + .foregroundStyle(.textPrimary) + .font(.system(size: 12).weight(.regular).monospacedDigit()) + .multilineTextAlignment(.leading) + .redacted(reason: codeReason) + Text(entryData.code) + .foregroundStyle(.textPrimary) + .font(.system(size: 31).weight(.light).monospacedDigit()) + .multilineTextAlignment(.leading) + .minimumScaleFactor(0.1) + .contentTransition(.numericText()) + .redacted(reason: codeReason) + + if let info = entryData.info, !info.isEmpty { Text(info) + .foregroundStyle(.textSecondary) .lineLimit(1) - .font(.caption) - .foregroundColor(.gray) - .redacted(reason: reason) + .font(.system(size: 12).weight(.regular)) + } + } + } + .blur(radius: kind == .singleEntryHidden ? 21 : 0) + .accessibility(hidden: codeReason == .codePlaceholder) + .overlay { + if kind == .singleEntry { + CopyIntentButton(rawEntry: entryData.rawEntry) { + Rectangle() + .foregroundStyle(Color.clear) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } else if kind == .singleEntryHidden { + RevealTokenIntentButton(secret: entryData.secret) { + RevealTokenOverlayView() } - Spacer() } - .addWidgetContentMargins(standard: spacing) - .accessibility(hidden: codeReason == .codePlaceholder) } } } @@ -132,13 +125,4 @@ struct TwoFASWidgetSquareView: View { return false } - - @ViewBuilder - private func counterText(for date: Date?) -> some View { - if let countdownTo = date { - Text(countdownTo, style: .timer) - } else { - Text("0:00") - } - } } diff --git a/TwoFAS/TwoFASWidget/WidgetContentMargins.swift b/TwoFAS/TwoFASWidget/WidgetContentMargins.swift index d4a939e2..2053ef49 100644 --- a/TwoFAS/TwoFASWidget/WidgetContentMargins.swift +++ b/TwoFAS/TwoFASWidget/WidgetContentMargins.swift @@ -29,7 +29,7 @@ struct WidgetContentMarginsModifier: ViewModifier { } extension View { - @ViewBuilder func addWidgetContentMargins(standard: Double = 8.0) -> some View { + @ViewBuilder func addWidgetContentMargins(standard: Double = 16.0) -> some View { if #available(iOS 17, *) { self } else { diff --git a/TwoFAS/update.swift b/TwoFAS/update.swift index 06063daa..0560b564 100755 Binary files a/TwoFAS/update.swift and b/TwoFAS/update.swift differ