diff --git a/.gitignore b/.gitignore index 15d22de..f6b09aa 100644 --- a/.gitignore +++ b/.gitignore @@ -71,9 +71,10 @@ iOSInjectionProject/ #ignore Pods directory for example project Pods +# do not commit Google Firebase config PLIST file +GoogleService-info.plist + # do not commit generated libraries to this repo lib *.a *.generated.swift -env-vars.sh -wallet/wallet/Generated/Constants.generated.swift diff --git a/secant.xcodeproj/project.pbxproj b/secant.xcodeproj/project.pbxproj index 72a4a9e..4f77db6 100644 --- a/secant.xcodeproj/project.pbxproj +++ b/secant.xcodeproj/project.pbxproj @@ -12,8 +12,13 @@ 0D185819272723FF0046B928 /* ColoredChip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D185818272723FF0046B928 /* ColoredChip.swift */; }; 0D18581B272728D60046B928 /* PhraseChip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D18581A272728D60046B928 /* PhraseChip.swift */; }; 0D1C1AA327611EFD0004AF6A /* RecoveryPhraseDisplayReducerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1C1AA227611EFD0004AF6A /* RecoveryPhraseDisplayReducerTests.swift */; }; + 0D26103A298C3DCD00CC9DE9 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 0D261039298C3DCD00CC9DE9 /* FirebaseCrashlytics */; }; + 0D26103C298C3E4800CC9DE9 /* CrashReportingInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D26103B298C3E4800CC9DE9 /* CrashReportingInterface.swift */; }; + 0D26103E298C3FA600CC9DE9 /* CrashReporterLiveKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D26103D298C3FA600CC9DE9 /* CrashReporterLiveKey.swift */; }; + 0D261040298C406F00CC9DE9 /* CrashReporterTestKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D26103F298C406F00CC9DE9 /* CrashReporterTestKey.swift */; }; 0D2ACE8026C2C67100D62E3C /* Zboto.otf in Resources */ = {isa = PBXBuildFile; fileRef = 0D2ACE7F26C2C67100D62E3C /* Zboto.otf */; }; 0D35CC46277A36E00074316A /* ScrollableWhenScaled.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D35CC45277A36E00074316A /* ScrollableWhenScaled.swift */; }; + 0D3B01EC298DAF89007EBCDA /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0D3B01EB298DAF89007EBCDA /* GoogleService-Info.plist */; }; 0D3D04082728B3440032ABC1 /* RecoveryPhraseDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D3D04072728B3440032ABC1 /* RecoveryPhraseDisplayView.swift */; }; 0D3D040A2728B3A10032ABC1 /* RecoveryPhraseDisplayStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D3D04092728B3A10032ABC1 /* RecoveryPhraseDisplayStore.swift */; }; 0D4E7A0926B364170058B01E /* SecantApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4E7A0826B364170058B01E /* SecantApp.swift */; }; @@ -24,6 +29,7 @@ 0D535FDF271F4214009A9E3E /* Rubik-VariableFont_wght.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0D535FDD271F4214009A9E3E /* Rubik-VariableFont_wght.ttf */; }; 0D535FE2271F9476009A9E3E /* EnumeratedChip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D535FE1271F9476009A9E3E /* EnumeratedChip.swift */; }; 0D5D9B8F2914620700DBD03F /* URLRouting in Frameworks */ = {isa = PBXBuildFile; productRef = 0D5D9B8E2914620700DBD03F /* URLRouting */; }; + 0D63170029919970007D873F /* UserPreferencesStorageInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D6316FF29919970007D873F /* UserPreferencesStorageInterface.swift */; }; 0D6D628B276A528E002FB4CC /* DropDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D6D628A276A528D002FB4CC /* DropDelegate.swift */; }; 0D7CE63427349B5D0020E050 /* View+WhenDraggable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7CE63327349B5D0020E050 /* View+WhenDraggable.swift */; }; 0D7DF08C271DCC0E00530046 /* ScreenBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7DF08B271DCC0E00530046 /* ScreenBackground.swift */; }; @@ -315,8 +321,12 @@ 0D185818272723FF0046B928 /* ColoredChip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColoredChip.swift; sourceTree = ""; }; 0D18581A272728D60046B928 /* PhraseChip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhraseChip.swift; sourceTree = ""; }; 0D1C1AA227611EFD0004AF6A /* RecoveryPhraseDisplayReducerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseDisplayReducerTests.swift; sourceTree = ""; }; + 0D26103B298C3E4800CC9DE9 /* CrashReportingInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportingInterface.swift; sourceTree = ""; }; + 0D26103D298C3FA600CC9DE9 /* CrashReporterLiveKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReporterLiveKey.swift; sourceTree = ""; }; + 0D26103F298C406F00CC9DE9 /* CrashReporterTestKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReporterTestKey.swift; sourceTree = ""; }; 0D2ACE7F26C2C67100D62E3C /* Zboto.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Zboto.otf; sourceTree = ""; }; 0D35CC45277A36E00074316A /* ScrollableWhenScaled.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollableWhenScaled.swift; sourceTree = ""; }; + 0D3B01EB298DAF89007EBCDA /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 0D3D04072728B3440032ABC1 /* RecoveryPhraseDisplayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseDisplayView.swift; sourceTree = ""; }; 0D3D04092728B3A10032ABC1 /* RecoveryPhraseDisplayStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseDisplayStore.swift; sourceTree = ""; }; 0D4E7A0526B364170058B01E /* secant-testnet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "secant-testnet.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -333,6 +343,7 @@ 0D535FDC271F4214009A9E3E /* Rubik-Italic-VariableFont_wght.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Rubik-Italic-VariableFont_wght.ttf"; sourceTree = ""; }; 0D535FDD271F4214009A9E3E /* Rubik-VariableFont_wght.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Rubik-VariableFont_wght.ttf"; sourceTree = ""; }; 0D535FE1271F9476009A9E3E /* EnumeratedChip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnumeratedChip.swift; sourceTree = ""; }; + 0D6316FF29919970007D873F /* UserPreferencesStorageInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreferencesStorageInterface.swift; sourceTree = ""; }; 0D6D628A276A528D002FB4CC /* DropDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDelegate.swift; sourceTree = ""; }; 0D7CE63327349B5D0020E050 /* View+WhenDraggable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+WhenDraggable.swift"; sourceTree = ""; }; 0D7DF08B271DCC0E00530046 /* ScreenBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenBackground.swift; sourceTree = ""; }; @@ -603,6 +614,7 @@ 9E6612312878337F00C75B70 /* Lottie in Frameworks */, 0D5D9B8F2914620700DBD03F /* URLRouting in Frameworks */, 0DB4E0B42881FD9100947B78 /* ZcashLightClientKit in Frameworks */, + 0D26103A298C3DCD00CC9DE9 /* FirebaseCrashlytics in Frameworks */, 9E2AC0FF27D8EC120042AA47 /* MnemonicSwift in Frameworks */, 6654C73A2715A38000901167 /* ComposableArchitecture in Frameworks */, 9EAB466D285A0468002904A0 /* Parsing in Frameworks */, @@ -766,6 +778,16 @@ path = Chips; sourceTree = ""; }; + 0D767873298C374F0047E085 /* CrashReporter */ = { + isa = PBXGroup; + children = ( + 0D26103B298C3E4800CC9DE9 /* CrashReportingInterface.swift */, + 0D26103D298C3FA600CC9DE9 /* CrashReporterLiveKey.swift */, + 0D26103F298C406F00CC9DE9 /* CrashReporterTestKey.swift */, + ); + path = CrashReporter; + sourceTree = ""; + }; 0D8A43C2272AEEA7005A6414 /* FontStyles */ = { isa = PBXGroup; children = ( @@ -1267,6 +1289,7 @@ children = ( 9E6612342878341F00C75B70 /* Lotties */, 0D4E7A0C26B364180058B01E /* Assets.xcassets */, + 0D3B01EB298DAF89007EBCDA /* GoogleService-Info.plist */, 660558E8270C7A54009D6954 /* Colors.xcassets */, 9E37A2B727C8F59F00AE57B3 /* Localizable.strings */, 0D2ACE7E26C2C65E00D62E3C /* Fonts */, @@ -1315,6 +1338,7 @@ 9EBDF978291F7E85000A1A05 /* AppVersion */, 9EBDF962291ECD42000A1A05 /* AudioServices */, 9EBDF969291ECEAC000A1A05 /* CaptureDevice */, + 0D767873298C374F0047E085 /* CrashReporter */, 9EBDF94E291E5E5F000A1A05 /* DatabaseFiles */, 9EBDF959291E654F000A1A05 /* Deeplink */, 9EBDF971291F79C9000A1A05 /* DerivationTool */, @@ -1614,6 +1638,7 @@ 9E3911442848EEB90073DD9A /* UserPreferencesStorage.swift */, 9EB863C62923C93B003D0F8B /* UserPreferencesStorageLive.swift */, 9EB863C82923C953003D0F8B /* UserPreferencesStorageMocks.swift */, + 0D6316FF29919970007D873F /* UserPreferencesStorageInterface.swift */, ); path = UserPreferencesStorage; sourceTree = ""; @@ -1834,11 +1859,13 @@ isa = PBXNativeTarget; buildConfigurationList = 0D4E7A2A26B364180058B01E /* Build configuration list for PBXNativeTarget "secant-testnet" */; buildPhases = ( + 0D3B01ED298DB0FE007EBCDA /* ShellScript */, 664E39ED270C693C0044AD7E /* SwiftGen */, 6696BA8726F0B1D200D5C875 /* SwiftLint */, 0D4E7A0126B364170058B01E /* Sources */, 0D4E7A0226B364170058B01E /* Frameworks */, 0D4E7A0326B364170058B01E /* Resources */, + 0D300FA72996EAF200576003 /* ShellScript */, ); buildRules = ( ); @@ -1852,6 +1879,7 @@ 9E6612302878337F00C75B70 /* Lottie */, 0DB4E0B32881FD9100947B78 /* ZcashLightClientKit */, 0D5D9B8E2914620700DBD03F /* URLRouting */, + 0D261039298C3DCD00CC9DE9 /* FirebaseCrashlytics */, ); productName = secant; productReference = 0D4E7A0526B364170058B01E /* secant-testnet.app */; @@ -1933,6 +1961,7 @@ 9E66122F2878337F00C75B70 /* XCRemoteSwiftPackageReference "lottie-ios" */, 0DB4E0B22881FD9100947B78 /* XCRemoteSwiftPackageReference "ZcashLightClientKit" */, 0D5D9B8D2914620700DBD03F /* XCRemoteSwiftPackageReference "swift-url-routing" */, + 0D261038298C3DCD00CC9DE9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, ); productRefGroup = 0D4E7A0626B364170058B01E /* Products */; projectDirPath = ""; @@ -1969,6 +1998,7 @@ 0D4E7A0D26B364180058B01E /* Assets.xcassets in Resources */, 0DACFA9727209FA70039EEA5 /* Roboto-Black.ttf in Resources */, 0DACFA9C27209FA70039EEA5 /* Roboto-ThinItalic.ttf in Resources */, + 0D3B01EC298DAF89007EBCDA /* GoogleService-Info.plist in Resources */, 9E37A2B827C8F59F00AE57B3 /* Localizable.strings in Resources */, 0DACFA9627209FA70039EEA5 /* Roboto-Thin.ttf in Resources */, 0D2ACE8026C2C67100D62E3C /* Zboto.otf in Resources */, @@ -1992,6 +2022,43 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 0D300FA72996EAF200576003 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 12; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nif [[ $UPLOAD_CRASHLYTICS_SYMBOLS = \"NO\" ]]; then\n echo \"DEBUG BUILD: SKIPPING UPLOAD SYMBOLS STEP\"\nelse\n${BUILD_DIR%/Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run\nfi\n"; + }; + 0D3B01ED298DB0FE007EBCDA /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Resources/GoogleService-Info.plist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/zsh; + shellScript = "# this creates an empty file for the firebase SDK\nCRASH_REPORTER_FILE=\"secant/Resources/GoogleService-Info.plist\"\nif [[ -f $CRASH_REPORTER_FILE ]]; then\n echo \"$CRASH_REPORTER_FILE Exists. Not doing anything.\"\nelse \n echo \"$CRASH_REPORTER_FILE does not exist. Will insert a DUMMY FILE\"\n\n echo \"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8ZGljdD4KICAgIDxrZXk+SVNfRFVNTVlfRklMRTwva2V5PgogICAgPHRydWU+PC90cnVlPgo8L2RpY3Q+CjwvcGxpc3Q+Cg==\" | base64 --decode > $CRASH_REPORTER_FILE\nfi\n"; + }; 664E39ED270C693C0044AD7E /* SwiftGen */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -2042,6 +2109,7 @@ files = ( 2EB660E02747EAB900A06A07 /* OnboardingFlowView.swift in Sources */, 9E7FE0DF282D2DD600C374E8 /* ZcashBadge.swift in Sources */, + 0D261040298C406F00CC9DE9 /* CrashReporterTestKey.swift in Sources */, 9EBDF975291F79F9000A1A05 /* DerivationToolInterface.swift in Sources */, 660558F8270C862F009D6954 /* XCAssets+Generated.swift in Sources */, 9EAFEB902808183D00199FC9 /* SandboxStore.swift in Sources */, @@ -2054,6 +2122,7 @@ 9EBDF96E291ECED4000A1A05 /* CaptureDeviceLiveKey.swift in Sources */, 9EBDF968291ECDA2000A1A05 /* AudioServicesInterface.swift in Sources */, 9EB863BD2923C704003D0F8B /* NotificationCenterTest.swift in Sources */, + 0D26103E298C3FA600CC9DE9 /* CrashReporterLiveKey.swift in Sources */, 9EB863A829239DCB003D0F8B /* RecoveryPhraseRandomizerLiveKey.swift in Sources */, 2EDA07A027EDE18C00D6F09B /* TCATextField.swift in Sources */, 9EBDF961291E657B000A1A05 /* DeeplinkInterface.swift in Sources */, @@ -2097,6 +2166,7 @@ 9E66122C2877188700C75B70 /* SyncStatusSnapshot.swift in Sources */, 9E4DC6E227C4C6B700E657F4 /* SecantButtonStyles.swift in Sources */, 0DDB6A5127737D4A0012A410 /* RecoveryPhraseBackupFailedView.swift in Sources */, + 0D63170029919970007D873F /* UserPreferencesStorageInterface.swift in Sources */, 9EBDF94D291D773A000A1A05 /* DiskSpaceCheckerMocks.swift in Sources */, 0D6D628B276A528E002FB4CC /* DropDelegate.swift in Sources */, 9EBDF986291F91EF000A1A05 /* LocalAuthenticationLiveKey.swift in Sources */, @@ -2222,6 +2292,7 @@ 9EB863D02923D3FC003D0F8B /* SDKSynchronizerMocks.swift in Sources */, 9E612C7629880FC900D09B09 /* LogsHandlerTest.swift in Sources */, 2EDA07A227EDE1AE00D6F09B /* TextFieldFooter.swift in Sources */, + 0D26103C298C3E4800CC9DE9 /* CrashReportingInterface.swift in Sources */, F9971A5427680DD000A2DB75 /* ProfileView.swift in Sources */, F9971A6027680DF600A2DB75 /* ScanStore.swift in Sources */, 9EB863952922D036003D0F8B /* NumberFormatterTestKey.swift in Sources */, @@ -2452,7 +2523,8 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 37; + CURRENT_PROJECT_VERSION = 39; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = "\"secant/Preview Content\""; DEVELOPMENT_TEAM = RLPRR8CPQG; ENABLE_BITCODE = NO; @@ -2469,6 +2541,7 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG UNREDACTED"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; + UPLOAD_CRASHLYTICS_SYMBOLS = NO; }; name = Debug; }; @@ -2478,7 +2551,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 37; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_ASSET_PATHS = "\"secant/Preview Content\""; DEVELOPMENT_TEAM = RLPRR8CPQG; ENABLE_BITCODE = NO; @@ -2494,6 +2567,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; + UPLOAD_CRASHLYTICS_SYMBOLS = YES; }; name = Release; }; @@ -2626,6 +2700,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 0D261038298C3DCD00CC9DE9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 9.6.0; + }; + }; 0D5D9B8D2914620700DBD03F /* XCRemoteSwiftPackageReference "swift-url-routing" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/pointfreeco/swift-url-routing"; @@ -2677,6 +2759,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 0D261039298C3DCD00CC9DE9 /* FirebaseCrashlytics */ = { + isa = XCSwiftPackageProductDependency; + package = 0D261038298C3DCD00CC9DE9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; + productName = FirebaseCrashlytics; + }; 0D5D9B8E2914620700DBD03F /* URLRouting */ = { isa = XCSwiftPackageProductDependency; package = 0D5D9B8D2914620700DBD03F /* XCRemoteSwiftPackageReference "swift-url-routing" */; diff --git a/secant.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/secant.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3ae7882..8f25fd0 100644 --- a/secant.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/secant.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,23 @@ { "pins" : [ + { + "identity" : "abseil-cpp-swiftpm", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/abseil-cpp-SwiftPM.git", + "state" : { + "revision" : "583de9bd60f66b40e78d08599cc92036c2e7e4e1", + "version" : "0.20220203.2" + } + }, + { + "identity" : "boringssl-swiftpm", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/boringssl-SwiftPM.git", + "state" : { + "revision" : "dd3eda2b05a3f459fc3073695ad1b28659066eab", + "version" : "0.9.1" + } + }, { "identity" : "combine-schedulers", "kind" : "remoteSourceControl", @@ -9,6 +27,51 @@ "version" : "0.9.1" } }, + { + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk.git", + "state" : { + "revision" : "7e80c25b51c2ffa238879b07fbfc5baa54bb3050", + "version" : "9.6.0" + } + }, + { + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "c1cfde8067668027b23a42c29d11c246152fe046", + "version" : "9.6.0" + } + }, + { + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "f6b558e3f801f2cac336b04f615ce111fa9ddaa0", + "version" : "9.2.1" + } + }, + { + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "0543562f85620b5b7c510c6bcbef75b562a5127b", + "version" : "7.11.0" + } + }, + { + "identity" : "grpc-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/grpc/grpc-ios.git", + "state" : { + "revision" : "8440b914756e0d26d4f4d054a1c1581daedfc5b6", + "version" : "1.44.3-grpc" + } + }, { "identity" : "grpc-swift", "kind" : "remoteSourceControl", @@ -18,6 +81,24 @@ "version" : "1.14.0" } }, + { + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "5ccda3981422a84186387dbb763ba739178b529c", + "version" : "2.3.0" + } + }, + { + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "0706abcc6b0bd9cedfbb015ba840e4a780b5159b", + "version" : "1.22.2" + } + }, { "identity" : "lottie-ios", "kind" : "remoteSourceControl", @@ -36,6 +117,24 @@ "version" : "2.2.4" } }, + { + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", + "version" : "2.30909.0" + } + }, + { + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "3e4e743631e86c8c70dbc6efdc7beaa6e90fd3bb", + "version" : "2.1.1" + } + }, { "identity" : "sqlite.swift", "kind" : "remoteSourceControl", diff --git a/secant/Dependencies/CrashReporter/CrashReporterLiveKey.swift b/secant/Dependencies/CrashReporter/CrashReporterLiveKey.swift new file mode 100644 index 0000000..ccde58d --- /dev/null +++ b/secant/Dependencies/CrashReporter/CrashReporterLiveKey.swift @@ -0,0 +1,41 @@ +// +// CrashReporterLiveKey.swift +// secant-testnet +// +// Created by Francisco Gindre on 2/2/23. +// +import ComposableArchitecture +import FirebaseCore +import FirebaseCrashlytics +extension CrashReporterClient: DependencyKey { + static let liveValue: CrashReporterClient = CrashReporterClient( + configure: { canConfigure in + let fileName = "GoogleService-Info.plist" + + // checks whether the crash reporter's config file is a dummy_file purposedly placed by the build job or the real one. + // this does not check the integrity of the Plist file for Firebase. + // that's a problem for the library itself. + guard + let configFile = Bundle.main.url(forResource: fileName, withExtension: nil), + let properties = NSDictionary(contentsOf: configFile), + properties["IS_DUMMY_FILE"] == nil, + canConfigure + else { + return + } + + FirebaseApp.configure() + Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true) + }, + testCrash: { + fatalError("Crash was triggered to test the crash reporter") + }, + optIn: { + Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true) + }, + optOut: { + Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(false) + + } + ) +} diff --git a/secant/Dependencies/CrashReporter/CrashReporterTestKey.swift b/secant/Dependencies/CrashReporter/CrashReporterTestKey.swift new file mode 100644 index 0000000..295b757 --- /dev/null +++ b/secant/Dependencies/CrashReporter/CrashReporterTestKey.swift @@ -0,0 +1,16 @@ +// +// CrashReporterTestKey.swift +// secant-testnet +// +// Created by Francisco Gindre on 2/2/23. +// + +import ComposableArchitecture +extension CrashReporterClient: TestDependencyKey { + static let testValue: CrashReporterClient = CrashReporterClient( + configure: { _ in }, + testCrash: {}, + optIn: {}, + optOut: {} + ) +} diff --git a/secant/Dependencies/CrashReporter/CrashReportingInterface.swift b/secant/Dependencies/CrashReporter/CrashReportingInterface.swift new file mode 100644 index 0000000..9d85c54 --- /dev/null +++ b/secant/Dependencies/CrashReporter/CrashReportingInterface.swift @@ -0,0 +1,31 @@ +// +// CrashReportingInterface.swift +// secant-testnet +// +// Created by Francisco Gindre on 2/2/23. +// +import ComposableArchitecture +import Foundation + +extension DependencyValues { + var crashReporter: CrashReporterClient { + get { self[CrashReporterClient.self] } + set { self[CrashReporterClient.self] = newValue } + } +} + +struct CrashReporterClient { + /// Configures the crash reporter if possible. + /// if it can't be configured this will fail silently + var configure: (Bool) -> Void + + /// this will test the crash reporter + /// - Note: depending of the crash reporter this may or may not crash your app. + var testCrash: () -> Void + + /// this will tell the crash reporter that the user a has decided to opt-in crash reporting + var optIn: () -> Void + + /// this will tell the crash reporter that the user has decided to opt-out of crash reporting + var optOut: () -> Void +} diff --git a/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorage.swift b/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorage.swift index ac31974..7f11cb9 100644 --- a/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorage.swift +++ b/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorage.swift @@ -17,6 +17,7 @@ struct UserPreferencesStorage { case zcashFiatConverted case zcashRecoveryPhraseTestCompleted case zcashSessionAutoshielded + case zcashUserOptedOutOfCrashReporting } /// Default values for all preferences in case there is no value stored (counterparts to `Constants`) @@ -25,6 +26,7 @@ struct UserPreferencesStorage { private let fiatConvertion: Bool private let recoveryPhraseTestCompleted: Bool private let sessionAutoshielded: Bool + private let userOptedOutOfCrashReporting: Bool private let userDefaults: UserDefaultsClient @@ -34,6 +36,7 @@ struct UserPreferencesStorage { fiatConvertion: Bool, recoveryPhraseTestCompleted: Bool, sessionAutoshielded: Bool, + userOptedOutOfCrashReporting: Bool, userDefaults: UserDefaultsClient ) { self.appSessionFrom = appSessionFrom @@ -41,6 +44,7 @@ struct UserPreferencesStorage { self.fiatConvertion = fiatConvertion self.recoveryPhraseTestCompleted = recoveryPhraseTestCompleted self.sessionAutoshielded = sessionAutoshielded + self.userOptedOutOfCrashReporting = userOptedOutOfCrashReporting self.userDefaults = userDefaults } @@ -89,6 +93,15 @@ struct UserPreferencesStorage { await setValue(bool, forKey: Constants.zcashSessionAutoshielded.rawValue) } + /// Whether the user has opted out of crash reporting + var isUserOptedOutOfCrashReporting: Bool { + getValue(forKey: Constants.zcashUserOptedOutOfCrashReporting.rawValue, default: false) + } + + func setIsUserOptedOutOfCrashReporting(_ bool: Bool) async { + await setValue(bool, forKey: Constants.zcashUserOptedOutOfCrashReporting.rawValue) + } + /// Use carefully: Deletes all user preferences from the User Defaults func removeAll() async { for key in Constants.allCases { diff --git a/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageInterface.swift b/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageInterface.swift new file mode 100644 index 0000000..9148449 --- /dev/null +++ b/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageInterface.swift @@ -0,0 +1,38 @@ +// +// UserPreferencesStorageInterface.swift +// secant-testnet +// +// Created by Francisco Gindre on 2/6/23. +// + +import Foundation +import ComposableArchitecture + +extension DependencyValues { + var userStoredPreferences: UserPreferencesStorageClient { + get { self [UserPreferencesStorageClient.self] } + set { self[UserPreferencesStorageClient.self] = newValue } + } +} + +struct UserPreferencesStorageClient { + var activeAppSessionFrom: () -> TimeInterval + var setActiveAppSessionFrom: (TimeInterval) async -> Void + + var currency: () -> String + var setCurrenty: (String) async -> Void + + var isFiatConverted: () -> Bool + var setIsFiatConverted: (Bool) async -> Void + + var isRecoveryPhraseTestCompleted: () -> Bool + var setIsRecoveryPhraseTestCompleted: (Bool) async -> Void + + var isSessionAutoshielded: () -> Bool + var setIsSessionAutoshielded: (Bool) async -> Void + + var isUserOptedOutOfCrashReporting: () -> Bool + var setIsUserOptedOutOfCrashReporting: (Bool) async -> Void + + var removeAll: () async -> Void +} diff --git a/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageLive.swift b/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageLive.swift index 5bd5a90..f43b1b7 100644 --- a/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageLive.swift +++ b/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageLive.swift @@ -6,6 +6,34 @@ // import Foundation +import ComposableArchitecture + +extension UserPreferencesStorageClient: DependencyKey { + static var liveValue: UserPreferencesStorageClient = { + let live = UserPreferencesStorage.live + + return UserPreferencesStorageClient( + activeAppSessionFrom: { live.activeAppSessionFrom }, + setActiveAppSessionFrom: live.setActiveAppSessionFrom(_:), + currency: { live.currency }, + setCurrenty: live.setCurrency(_:), + isFiatConverted: { live.isFiatConverted }, + setIsFiatConverted: live.setIsFiatConverted(_:), + isRecoveryPhraseTestCompleted: { + live.isRecoveryPhraseTestCompleted + }, + setIsRecoveryPhraseTestCompleted: live.setIsRecoveryPhraseTestCompleted(_:), + isSessionAutoshielded: { live.isSessionAutoshielded }, + setIsSessionAutoshielded: live.setIsSessionAutoshielded(_:), + isUserOptedOutOfCrashReporting: { + live.isUserOptedOutOfCrashReporting + }, + setIsUserOptedOutOfCrashReporting: live.setIsUserOptedOutOfCrashReporting(_:), + removeAll: live.removeAll + ) + }() +} + extension UserPreferencesStorage { static let live = UserPreferencesStorage( @@ -14,6 +42,7 @@ extension UserPreferencesStorage { fiatConvertion: true, recoveryPhraseTestCompleted: false, sessionAutoshielded: true, + userOptedOutOfCrashReporting: false, userDefaults: .live() ) } diff --git a/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageMocks.swift b/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageMocks.swift index 0b5d38e..28d58e8 100644 --- a/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageMocks.swift +++ b/secant/Dependencies/UserPreferencesStorage/UserPreferencesStorageMocks.swift @@ -6,6 +6,33 @@ // import Foundation +import ComposableArchitecture + +extension UserPreferencesStorageClient: TestDependencyKey { + static var testValue = { + let mock = UserPreferencesStorage.mock + + return UserPreferencesStorageClient( + activeAppSessionFrom: { mock.activeAppSessionFrom }, + setActiveAppSessionFrom: mock.setActiveAppSessionFrom(_:), + currency: { mock.currency }, + setCurrenty: mock.setCurrency(_:), + isFiatConverted: { mock.isFiatConverted }, + setIsFiatConverted: mock.setIsFiatConverted(_:), + isRecoveryPhraseTestCompleted: { + mock.isRecoveryPhraseTestCompleted + }, + setIsRecoveryPhraseTestCompleted: mock.setIsRecoveryPhraseTestCompleted(_:), + isSessionAutoshielded: { mock.isSessionAutoshielded }, + setIsSessionAutoshielded: mock.setIsSessionAutoshielded(_:), + isUserOptedOutOfCrashReporting: { + mock.isUserOptedOutOfCrashReporting + }, + setIsUserOptedOutOfCrashReporting: mock.setIsUserOptedOutOfCrashReporting(_:), + removeAll: mock.removeAll + ) + }() +} extension UserPreferencesStorage { static let mock = UserPreferencesStorage( @@ -14,6 +41,7 @@ extension UserPreferencesStorage { fiatConvertion: true, recoveryPhraseTestCompleted: false, sessionAutoshielded: true, + userOptedOutOfCrashReporting: false, userDefaults: .noOp ) } diff --git a/secant/Features/Root/RootInitialization.swift b/secant/Features/Root/RootInitialization.swift index d6c9d12..0a05bb3 100644 --- a/secant/Features/Root/RootInitialization.swift +++ b/secant/Features/Root/RootInitialization.swift @@ -14,6 +14,7 @@ extension RootReducer { case appDelegate(AppDelegateAction) case checkBackupPhraseValidation case checkWalletInitialization + case configureCrashReporter case createNewWallet case initializeSDK case nukeWallet @@ -27,10 +28,13 @@ extension RootReducer { case .initialization(.appDelegate(.didFinishLaunching)): // TODO: [#524] finish all the wallet events according to definition, https://github.com/zcash/secant-ios-wallet/issues/524 LoggerProxy.event(".appDelegate(.didFinishLaunching)") - /// We need to fetch data from keychain, in order to be 100% sure the kecyhain can be read we delay the check a bit - return EffectTask(value: .initialization(.checkWalletInitialization)) - .delay(for: 0.02, scheduler: mainQueue) - .eraseToEffect() + /// We need to fetch data from keychain, in order to be 100% sure the keychain can be read we delay the check a bit + return .concatenate( + EffectTask(value: .initialization(.configureCrashReporter)), + EffectTask(value: .initialization(.checkWalletInitialization)) + .delay(for: 0.02, scheduler: mainQueue) + .eraseToEffect() + ) /// Evaluate the wallet's state based on keychain keys and database files presence case .initialization(.checkWalletInitialization): @@ -193,6 +197,12 @@ extension RootReducer { case .home, .destination, .onboarding, .phraseDisplay, .phraseValidation, .sandbox, .welcome: return .none + + case .initialization(.configureCrashReporter): + crashReporter.configure( + !userStoredPreferences.isUserOptedOutOfCrashReporting() + ) + return .none } } } diff --git a/secant/Features/Root/RootStore.swift b/secant/Features/Root/RootStore.swift index 1af2ecf..db599b6 100644 --- a/secant/Features/Root/RootStore.swift +++ b/secant/Features/Root/RootStore.swift @@ -29,7 +29,8 @@ struct RootReducer: ReducerProtocol { case sandbox(SandboxReducer.Action) case welcome(WelcomeReducer.Action) } - + + @Dependency(\.crashReporter) var crashReporter @Dependency(\.databaseFiles) var databaseFiles @Dependency(\.deeplink) var deeplink @Dependency(\.derivationTool) var derivationTool @@ -37,6 +38,7 @@ struct RootReducer: ReducerProtocol { @Dependency(\.mnemonic) var mnemonic @Dependency(\.randomRecoveryPhrase) var randomRecoveryPhrase @Dependency(\.sdkSynchronizer) var sdkSynchronizer + @Dependency(\.userStoredPreferences) var userStoredPreferences @Dependency(\.walletStorage) var walletStorage @Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment diff --git a/secant/Features/Settings/SettingsStore.swift b/secant/Features/Settings/SettingsStore.swift index 62d1587..6228322 100644 --- a/secant/Features/Settings/SettingsStore.swift +++ b/secant/Features/Settings/SettingsStore.swift @@ -15,7 +15,9 @@ struct SettingsReducer: ReducerProtocol { var isSharingLogs = false var phraseDisplayState: RecoveryPhraseDisplayReducer.State var rescanDialog: ConfirmationDialogState? - + + @BindableState var isCrashReportingOn: Bool + var tempSDKDir: URL { let tempDir = FileManager.default.temporaryDirectory let sdkFileName = "sdkLogs.txt" @@ -35,18 +37,21 @@ struct SettingsReducer: ReducerProtocol { } } - enum Action: Equatable { + enum Action: BindableAction, Equatable { case backupWallet case backupWalletAccessRequest + case binding(BindingAction) case cancelRescan case exportLogs case fullRescan case logsExported case logsShareFinished + case onAppear case phraseDisplay(RecoveryPhraseDisplayReducer.Action) case quickRescan case rescanBlockchain case updateDestination(SettingsReducer.State.Destination?) + case testCrashReporter // this will crash the app if live. } @Dependency(\.localAuthentication) var localAuthentication @@ -54,10 +59,15 @@ struct SettingsReducer: ReducerProtocol { @Dependency(\.sdkSynchronizer) var sdkSynchronizer @Dependency(\.logsHandler) var logsHandler @Dependency(\.walletStorage) var walletStorage + @Dependency(\.userStoredPreferences) var userStoredPreferences + @Dependency(\.crashReporter) var crashReporter var body: some ReducerProtocol { Reduce { state, action in switch action { + case .onAppear: + state.isCrashReportingOn = !userStoredPreferences.isUserOptedOutOfCrashReporting() + return .none case .backupWalletAccessRequest: return .run { send in if await localAuthentication.authenticate() { @@ -76,6 +86,17 @@ struct SettingsReducer: ReducerProtocol { // TODO: [#221] - merge with issue 221 (https://github.com/zcash/secant-ios-wallet/issues/221) and its Error States return .none } + + case .binding(\.$isCrashReportingOn): + if state.isCrashReportingOn { + crashReporter.optOut() + } else { + crashReporter.optIn() + } + + return .run { [state] send in + await userStoredPreferences.setIsUserOptedOutOfCrashReporting(state.isCrashReportingOn) + } case .cancelRescan, .quickRescan, .fullRescan: state.rescanDialog = nil @@ -112,7 +133,7 @@ struct SettingsReducer: ReducerProtocol { ] ) return .none - + case .phraseDisplay: state.destination = nil return .none @@ -120,6 +141,13 @@ struct SettingsReducer: ReducerProtocol { case .updateDestination(let destination): state.destination = destination return .none + + case .testCrashReporter: + crashReporter.testCrash() + return .none + + case .binding: + return .none } } @@ -164,7 +192,8 @@ extension SettingsReducer.State { static let placeholder = SettingsReducer.State( phraseDisplayState: RecoveryPhraseDisplayReducer.State( phrase: .placeholder - ) + ), + isCrashReportingOn: true ) } diff --git a/secant/Features/Settings/SettingsView.swift b/secant/Features/Settings/SettingsView.swift index 3ac1ff2..d16609a 100644 --- a/secant/Features/Settings/SettingsView.swift +++ b/secant/Features/Settings/SettingsView.swift @@ -6,14 +6,16 @@ struct SettingsView: View { var body: some View { WithViewStore(store) { viewStore in - VStack { + VStack(spacing: 40) { + Toggle("Enable Crash Reporting", + isOn: viewStore.binding(\.$isCrashReportingOn) + ) Button( action: { viewStore.send(.backupWalletAccessRequest) }, label: { Text("Backup Wallet") } ) .activeButtonStyle .frame(height: 50) - .padding(30) Button( action: { viewStore.send(.rescanBlockchain) }, @@ -21,7 +23,6 @@ struct SettingsView: View { ) .primaryButtonStyle .frame(height: 50) - .padding(.horizontal, 30) Button( action: { viewStore.send(.exportLogs) }, @@ -38,12 +39,17 @@ struct SettingsView: View { ) .primaryButtonStyle .frame(height: 50) - .padding(.horizontal, 30) - .padding(.top, 30) .disabled(viewStore.exportLogsDisabled) + Button( + action: { viewStore.send(.testCrashReporter) }, + label: { Text("Test Crash Reporter") } + ) + .primaryButtonStyle + .frame(height: 50) Spacer() } + .padding(.horizontal, 30) .navigationTitle("Settings") .applyScreenBackground() .confirmationDialog( @@ -56,6 +62,7 @@ struct SettingsView: View { RecoveryPhraseDisplayView(store: store.backupPhraseStore()) } ) + .onAppear { viewStore.send(.onAppear) } if viewStore.isSharingLogs { UIShareDialogView( diff --git a/secant/Info.plist b/secant/Info.plist index 4de661d..34d813c 100644 --- a/secant/Info.plist +++ b/secant/Info.plist @@ -86,12 +86,7 @@ UIInterfaceOrientationPortrait - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - + FirebaseCrashlyticsCollectionEnabled + diff --git a/secantTests/RootTests/AppInitializationTests.swift b/secantTests/RootTests/AppInitializationTests.swift index 7c9e2e2..aa7454b 100644 --- a/secantTests/RootTests/AppInitializationTests.swift +++ b/secantTests/RootTests/AppInitializationTests.swift @@ -105,16 +105,19 @@ class AppInitializationTests: XCTestCase { await testScheduler.advance(by: 0.02) // ad 1. - await store.receive(.initialization(.checkWalletInitialization)) + await store.receive(.initialization(.configureCrashReporter)) // ad 2. - await store.receive(.initialization(.respondToWalletInitializationState(.initialized))) + await store.receive(.initialization(.checkWalletInitialization)) // ad 3. + await store.receive(.initialization(.respondToWalletInitializationState(.initialized))) + + // ad 4. await store.receive(.initialization(.initializeSDK)) { state in state.storedWallet = .placeholder } - // ad 4. + // ad 5. await store.receive(.initialization(.checkBackupPhraseValidation)) { state in state.appInitializationState = .initialized } @@ -153,9 +156,12 @@ class AppInitializationTests: XCTestCase { testScheduler.advance(by: 0.02) // ad 1. + store.receive(.initialization(.configureCrashReporter)) + + // ad 2 store.receive(.initialization(.checkWalletInitialization)) - // ad 2. + // ad 3. store.receive(.initialization(.respondToWalletInitializationState(.keysMissing))) { state in state.appInitializationState = .keysMissing } @@ -184,14 +190,17 @@ class AppInitializationTests: XCTestCase { // the 0.02 delay ensures keychain is ready // the 3.0 delay ensures the welcome screen is visible till the initialization check is done testScheduler.advance(by: 3.02) - + // ad 1. - store.receive(.initialization(.checkWalletInitialization)) + store.receive(.initialization(.configureCrashReporter)) // ad 2. + store.receive(.initialization(.checkWalletInitialization)) + + // ad 3. store.receive(.initialization(.respondToWalletInitializationState(.uninitialized))) - // ad 3. + // ad 4. store.receive(.destination(.updateDestination(.onboarding))) { state in state.destinationState.previousDestination = .welcome state.destinationState.internalDestination = .onboarding diff --git a/secantTests/SettingsTests/SettingsTests.swift b/secantTests/SettingsTests/SettingsTests.swift index c8f9dfe..a328de4 100644 --- a/secantTests/SettingsTests/SettingsTests.swift +++ b/secantTests/SettingsTests/SettingsTests.swift @@ -45,7 +45,10 @@ class SettingsTests: XCTestCase { ) let store = TestStore( - initialState: SettingsReducer.State(phraseDisplayState: RecoveryPhraseDisplayReducer.State(phrase: nil)), + initialState: SettingsReducer.State( + phraseDisplayState: RecoveryPhraseDisplayReducer.State(phrase: nil), + isCrashReportingOn: false + ), reducer: SettingsReducer() ) { dependencies in dependencies.localAuthentication = .mockAuthenticationSucceeded @@ -109,7 +112,8 @@ class SettingsTests: XCTestCase { .default(TextState("Full rescan"), action: .send(.fullRescan)), .cancel(TextState("Cancel")) ] - ) + ), + isCrashReportingOn: false ), reducer: SettingsReducer() ) @@ -132,7 +136,8 @@ class SettingsTests: XCTestCase { .default(TextState("Full rescan"), action: .send(.fullRescan)), .cancel(TextState("Cancel")) ] - ) + ), + isCrashReportingOn: false ), reducer: SettingsReducer() ) @@ -155,7 +160,8 @@ class SettingsTests: XCTestCase { .default(TextState("Full rescan"), action: .send(.fullRescan)), .cancel(TextState("Cancel")) ] - ) + ), + isCrashReportingOn: false ), reducer: SettingsReducer() ) @@ -178,7 +184,8 @@ class SettingsTests: XCTestCase { .default(TextState("Full rescan"), action: .send(.fullRescan)), .cancel(TextState("Cancel")) ] - ) + ), + isCrashReportingOn: false ), reducer: SettingsReducer() ) @@ -209,7 +216,8 @@ class SettingsTests: XCTestCase { .default(TextState("Full rescan"), action: .send(.fullRescan)), .cancel(TextState("Cancel")) ] - ) + ), + isCrashReportingOn: false ), reducer: SettingsReducer() ) diff --git a/secantTests/UtilTests/UserPreferencesStorageTests.swift b/secantTests/UtilTests/UserPreferencesStorageTests.swift index 6b666b8..a518cd0 100644 --- a/secantTests/UtilTests/UserPreferencesStorageTests.swift +++ b/secantTests/UtilTests/UserPreferencesStorageTests.swift @@ -26,6 +26,7 @@ class UserPreferencesStorageTests: XCTestCase { fiatConvertion: true, recoveryPhraseTestCompleted: true, sessionAutoshielded: false, + userOptedOutOfCrashReporting: true, userDefaults: .live(userDefaults: userDefaults) ) await storage.removeAll() @@ -107,6 +108,7 @@ class UserPreferencesStorageTests: XCTestCase { fiatConvertion: true, recoveryPhraseTestCompleted: true, sessionAutoshielded: false, + userOptedOutOfCrashReporting: true, userDefaults: mockedUD ) @@ -127,6 +129,7 @@ class UserPreferencesStorageTests: XCTestCase { fiatConvertion: true, recoveryPhraseTestCompleted: true, sessionAutoshielded: false, + userOptedOutOfCrashReporting: true, userDefaults: mockedUD ) @@ -147,6 +150,7 @@ class UserPreferencesStorageTests: XCTestCase { fiatConvertion: true, recoveryPhraseTestCompleted: true, sessionAutoshielded: false, + userOptedOutOfCrashReporting: true, userDefaults: mockedUD ) @@ -167,6 +171,7 @@ class UserPreferencesStorageTests: XCTestCase { fiatConvertion: true, recoveryPhraseTestCompleted: true, sessionAutoshielded: false, + userOptedOutOfCrashReporting: true, userDefaults: mockedUD ) @@ -187,6 +192,7 @@ class UserPreferencesStorageTests: XCTestCase { fiatConvertion: true, recoveryPhraseTestCompleted: true, sessionAutoshielded: false, + userOptedOutOfCrashReporting: true, userDefaults: mockedUD )