diff --git a/RadixWallet.xcodeproj/project.pbxproj b/RadixWallet.xcodeproj/project.pbxproj index ae8c753d04..55dcf3f0ea 100644 --- a/RadixWallet.xcodeproj/project.pbxproj +++ b/RadixWallet.xcodeproj/project.pbxproj @@ -878,6 +878,9 @@ 5B1C4FD52BBB0B0C00B9436F /* AppsFlyerLib-Strict in Frameworks */ = {isa = PBXBuildFile; productRef = 5B1C4FD42BBB0B0C00B9436F /* AppsFlyerLib-Strict */; }; 5B1C4FD82BBB0C1E00B9436F /* AppsFlyerClient+Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B1C4FD72BBB0C1E00B9436F /* AppsFlyerClient+Interface.swift */; }; 5B1C4FDA2BBB0DCF00B9436F /* AppsFlyerClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B1C4FD92BBB0DCF00B9436F /* AppsFlyerClient+Live.swift */; }; + 5B272DD72C36E89600B74F1F /* AppEventsClient+Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B272DD62C36E89600B74F1F /* AppEventsClient+Interface.swift */; }; + 5B272DD92C36E93100B74F1F /* AppEventsClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B272DD82C36E93100B74F1F /* AppEventsClient+Live.swift */; }; + 5B272DDB2C36E9D300B74F1F /* AppEventsClient+Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B272DDA2C36E9D300B74F1F /* AppEventsClient+Test.swift */; }; 5B2A45022BD6680400AEC8AD /* ContactSupportClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2A45012BD6680400AEC8AD /* ContactSupportClient.swift */; }; 5B2A45042BD6689100AEC8AD /* ContactSupportClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2A45032BD6689100AEC8AD /* ContactSupportClient+Live.swift */; }; 5B43B08B2BDAAD4B00AA1E92 /* AddressDetails+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B43B0892BDAAD4B00AA1E92 /* AddressDetails+View.swift */; }; @@ -907,6 +910,8 @@ 5BB7C1762BC81F50001216EB /* ImportOlympiaNameLedger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB7C1752BC81F50001216EB /* ImportOlympiaNameLedger.swift */; }; 5BB7C1782BC81F61001216EB /* ImportOlympiaNameLedger+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB7C1772BC81F61001216EB /* ImportOlympiaNameLedger+View.swift */; }; 5BBC43A92BBAC6B0005747B1 /* AppTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC43A82BBAC6B0005747B1 /* AppTextEditor.swift */; }; + 5BBC7D9E2C3D390E00B04BD6 /* BootstrapClient+Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC7D9B2C3D390D00B04BD6 /* BootstrapClient+Interface.swift */; }; + 5BBC7D9F2C3D390E00B04BD6 /* BootstrapClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC7D9C2C3D390D00B04BD6 /* BootstrapClient+Live.swift */; }; 5BBC7DA42C3D442800B04BD6 /* URLRequest+Extra.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC7DA32C3D442800B04BD6 /* URLRequest+Extra.swift */; }; 5BC82B6C2BED18A1009AC162 /* FactoryReset+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC82B6A2BED18A1009AC162 /* FactoryReset+View.swift */; }; 5BC82B6D2BED18A1009AC162 /* FactoryReset+Reducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC82B6B2BED18A1009AC162 /* FactoryReset+Reducer.swift */; }; @@ -1080,6 +1085,12 @@ A4CFB55D2BA8CA3200778BDD /* TransactionHistory+TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4CFB55C2BA8CA3200778BDD /* TransactionHistory+TableView.swift */; }; A4CFB55F2BAA821E00778BDD /* HScrollBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4CFB55E2BAA821E00778BDD /* HScrollBar.swift */; }; A4CFB5612BAA826E00778BDD /* Measure+Position.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4CFB5602BAA826E00778BDD /* Measure+Position.swift */; }; + A4DBBEB32C20305000D0A59E /* CardCarousel+Reducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4DBBEB22C20305000D0A59E /* CardCarousel+Reducer.swift */; }; + A4DBBEB52C20305700D0A59E /* CardCarousel+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4DBBEB42C20305700D0A59E /* CardCarousel+View.swift */; }; + A4DCCC4B2C2DA08000438A7B /* GeometryExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4DCCC4A2C2DA08000438A7B /* GeometryExtensions.swift */; }; + A4DCCC502C2DA32C00438A7B /* HomeCardsClient+Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4DCCC4D2C2DA26100438A7B /* HomeCardsClient+Interface.swift */; }; + A4DCCC512C2DA33100438A7B /* HomeCardsClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4DCCC4E2C2DA26100438A7B /* HomeCardsClient+Live.swift */; }; + A4DCCC522C2DA33300438A7B /* HomeCardsClient+Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4DCCC4F2C2DA26200438A7B /* HomeCardsClient+Test.swift */; }; A4EB37C82B6272F3003FE31D /* TrackedValidatorInteraction.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4EB37C72B6272F3003FE31D /* TrackedValidatorInteraction.swift */; }; A4EBB5D62BD0777C00D05FDE /* ConfigurationBackup+Reducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4EBB5D52BD0777C00D05FDE /* ConfigurationBackup+Reducer.swift */; }; A4EBB5D82BD0777F00D05FDE /* ConfigurationBackup+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4EBB5D72BD0777F00D05FDE /* ConfigurationBackup+View.swift */; }; @@ -2015,6 +2026,9 @@ 48FFFAF12ADC23AC00B2B213 /* Exports.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Exports.swift; sourceTree = ""; }; 5B1C4FD72BBB0C1E00B9436F /* AppsFlyerClient+Interface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppsFlyerClient+Interface.swift"; sourceTree = ""; }; 5B1C4FD92BBB0DCF00B9436F /* AppsFlyerClient+Live.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppsFlyerClient+Live.swift"; sourceTree = ""; }; + 5B272DD62C36E89600B74F1F /* AppEventsClient+Interface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppEventsClient+Interface.swift"; sourceTree = ""; }; + 5B272DD82C36E93100B74F1F /* AppEventsClient+Live.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppEventsClient+Live.swift"; sourceTree = ""; }; + 5B272DDA2C36E9D300B74F1F /* AppEventsClient+Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppEventsClient+Test.swift"; sourceTree = ""; }; 5B2A45012BD6680400AEC8AD /* ContactSupportClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactSupportClient.swift; sourceTree = ""; }; 5B2A45032BD6689100AEC8AD /* ContactSupportClient+Live.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContactSupportClient+Live.swift"; sourceTree = ""; }; 5B43B0892BDAAD4B00AA1E92 /* AddressDetails+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AddressDetails+View.swift"; sourceTree = ""; }; @@ -2044,6 +2058,8 @@ 5BB7C1752BC81F50001216EB /* ImportOlympiaNameLedger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportOlympiaNameLedger.swift; sourceTree = ""; }; 5BB7C1772BC81F61001216EB /* ImportOlympiaNameLedger+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ImportOlympiaNameLedger+View.swift"; sourceTree = ""; }; 5BBC43A82BBAC6B0005747B1 /* AppTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTextEditor.swift; sourceTree = ""; }; + 5BBC7D9B2C3D390D00B04BD6 /* BootstrapClient+Interface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BootstrapClient+Interface.swift"; sourceTree = ""; }; + 5BBC7D9C2C3D390D00B04BD6 /* BootstrapClient+Live.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BootstrapClient+Live.swift"; sourceTree = ""; }; 5BBC7DA32C3D442800B04BD6 /* URLRequest+Extra.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLRequest+Extra.swift"; sourceTree = ""; }; 5BC82B6A2BED18A1009AC162 /* FactoryReset+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FactoryReset+View.swift"; sourceTree = ""; }; 5BC82B6B2BED18A1009AC162 /* FactoryReset+Reducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FactoryReset+Reducer.swift"; sourceTree = ""; }; @@ -2219,6 +2235,12 @@ A4CFB55C2BA8CA3200778BDD /* TransactionHistory+TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TransactionHistory+TableView.swift"; sourceTree = ""; }; A4CFB55E2BAA821E00778BDD /* HScrollBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HScrollBar.swift; sourceTree = ""; }; A4CFB5602BAA826E00778BDD /* Measure+Position.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Measure+Position.swift"; sourceTree = ""; }; + A4DBBEB22C20305000D0A59E /* CardCarousel+Reducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CardCarousel+Reducer.swift"; sourceTree = ""; }; + A4DBBEB42C20305700D0A59E /* CardCarousel+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CardCarousel+View.swift"; sourceTree = ""; }; + A4DCCC4A2C2DA08000438A7B /* GeometryExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeometryExtensions.swift; sourceTree = ""; }; + A4DCCC4D2C2DA26100438A7B /* HomeCardsClient+Interface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeCardsClient+Interface.swift"; sourceTree = ""; }; + A4DCCC4E2C2DA26100438A7B /* HomeCardsClient+Live.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeCardsClient+Live.swift"; sourceTree = ""; }; + A4DCCC4F2C2DA26200438A7B /* HomeCardsClient+Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeCardsClient+Test.swift"; sourceTree = ""; }; A4EB37C72B6272F3003FE31D /* TrackedValidatorInteraction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackedValidatorInteraction.swift; sourceTree = ""; }; A4EBB5D52BD0777C00D05FDE /* ConfigurationBackup+Reducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfigurationBackup+Reducer.swift"; sourceTree = ""; }; A4EBB5D72BD0777F00D05FDE /* ConfigurationBackup+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfigurationBackup+View.swift"; sourceTree = ""; }; @@ -2520,6 +2542,7 @@ 48CFBC602ADC10D800E77A5C /* Features */ = { isa = PBXGroup; children = ( + A4DBBEB12C20302B00D0A59E /* CardCarousel */, E7AE2D082C05F22700830BAA /* ClaimWallet */, A43F1E242BC96EF2001DD3FA /* SecurityCenterFeature */, 48D5F3972BD8DE0A000DE964 /* DebugInspectProfile */, @@ -4265,6 +4288,9 @@ 48CFBF522ADC10D900E77A5C /* Clients */ = { isa = PBXGroup; children = ( + 5BBC7D9D2C3D390D00B04BD6 /* BootstrapClient */, + 5B272DD52C36E88700B74F1F /* AppEventsClient */, + A4DCCC4C2C2DA23E00438A7B /* HomeCardsClient */, 8329ACE22BBAB9CD005FD9DC /* DeepLinkHandlerClient */, E7A5AC942C09F428006CB6EC /* ResetWalletClient */, A4ECE2782BEEB01800468BF6 /* CloudBackupClient */, @@ -5103,6 +5129,7 @@ 48CFC11A2ADC10D900E77A5C /* FixedSpacer.swift */, 5BBC43A82BBAC6B0005747B1 /* AppTextEditor.swift */, 5B6499B92BCFDB1E000F2176 /* ShareView.swift */, + A4DCCC4A2C2DA08000438A7B /* GeometryExtensions.swift */, ); path = Components; sourceTree = ""; @@ -5577,6 +5604,16 @@ path = AppsFlyerClient; sourceTree = ""; }; + 5B272DD52C36E88700B74F1F /* AppEventsClient */ = { + isa = PBXGroup; + children = ( + 5B272DD62C36E89600B74F1F /* AppEventsClient+Interface.swift */, + 5B272DD82C36E93100B74F1F /* AppEventsClient+Live.swift */, + 5B272DDA2C36E9D300B74F1F /* AppEventsClient+Test.swift */, + ); + path = AppEventsClient; + sourceTree = ""; + }; 5B2A45002BD667FB00AEC8AD /* ContactSupportClient */ = { isa = PBXGroup; children = ( @@ -5655,6 +5692,15 @@ path = SensitiveInfoClient; sourceTree = ""; }; + 5BBC7D9D2C3D390D00B04BD6 /* BootstrapClient */ = { + isa = PBXGroup; + children = ( + 5BBC7D9B2C3D390D00B04BD6 /* BootstrapClient+Interface.swift */, + 5BBC7D9C2C3D390D00B04BD6 /* BootstrapClient+Live.swift */, + ); + path = BootstrapClient; + sourceTree = ""; + }; 830E43AD2C2D8B3800B6E95F /* Mobile */ = { isa = PBXGroup; children = ( @@ -5901,6 +5947,25 @@ path = TransactionReviewDepositSetting; sourceTree = ""; }; + A4DBBEB12C20302B00D0A59E /* CardCarousel */ = { + isa = PBXGroup; + children = ( + A4DBBEB22C20305000D0A59E /* CardCarousel+Reducer.swift */, + A4DBBEB42C20305700D0A59E /* CardCarousel+View.swift */, + ); + path = CardCarousel; + sourceTree = ""; + }; + A4DCCC4C2C2DA23E00438A7B /* HomeCardsClient */ = { + isa = PBXGroup; + children = ( + A4DCCC4D2C2DA26100438A7B /* HomeCardsClient+Interface.swift */, + A4DCCC4E2C2DA26100438A7B /* HomeCardsClient+Live.swift */, + A4DCCC4F2C2DA26200438A7B /* HomeCardsClient+Test.swift */, + ); + path = HomeCardsClient; + sourceTree = ""; + }; A4ECE2712BEEAFFC00468BF6 /* SecurityCenterClient */ = { isa = PBXGroup; children = ( @@ -6809,6 +6874,7 @@ 4813AFEB2BC9AF4A0046BCAD /* RawRepresentable+Extensions.swift in Sources */, A462B5852B83672300C26D20 /* StreamTransactionsRequestAllOfManifestClassFilter.swift in Sources */, 48CFC29C2ADC10D900E77A5C /* TransactionReview+View.swift in Sources */, + A4DCCC4B2C2DA08000438A7B /* GeometryExtensions.swift in Sources */, 48CFC2A72ADC10D900E77A5C /* AuthorizedDApps+View.swift in Sources */, 83EE5EEF2BE3C16F00B1531D /* AccountAuthorizedDepositorsResourceBadge.swift in Sources */, 4855B19A2BCA557D00DD0A47 /* Stage2MigrateToSargon+Persona.swift in Sources */, @@ -6839,7 +6905,9 @@ 48D5F3982BD8DE0A000DE964 /* DebugInspectProfile.swift in Sources */, 48CFC2872ADC10D900E77A5C /* MinimumPercentageStepper+View.swift in Sources */, E76645A42C23138300065D9A /* Throwable.swift in Sources */, + 5B272DD72C36E89600B74F1F /* AppEventsClient+Interface.swift in Sources */, 48CFC2A12ADC10D900E77A5C /* PersonaFeature.swift in Sources */, + A4DCCC502C2DA32C00438A7B /* HomeCardsClient+Interface.swift in Sources */, 48CFC4162ADC10DA00E77A5C /* PasteboardClient+Test.swift in Sources */, 48CFC34E2ADC10D900E77A5C /* Login+View.swift in Sources */, 48CFC3122ADC10D900E77A5C /* AccountsToImport.swift in Sources */, @@ -6976,6 +7044,7 @@ 48CFC57C2ADC10DA00E77A5C /* NonFungibleResourcesCollectionItem.swift in Sources */, 48CFC3F92ADC10D900E77A5C /* SignalingClientFactory.swift in Sources */, 48CFC3192ADC10D900E77A5C /* CreateAccountCoordinator+View.swift in Sources */, + A4DBBEB32C20305000D0A59E /* CardCarousel+Reducer.swift in Sources */, 48CFC4CA2ADC10DA00E77A5C /* OpenISO8601DateFormatter.swift in Sources */, 48CFC2492ADC10D900E77A5C /* ResourcesList+View.swift in Sources */, 4813AFE22BC9A9AD0046BCAD /* Stage1MigrateToSargon+NetworkDefinition.swift in Sources */, @@ -7010,6 +7079,7 @@ 48CFC2C22ADC10D900E77A5C /* ChooseReceivingAccount+View.swift in Sources */, 48CFC3862ADC10D900E77A5C /* DetailsContainerWithHeaderView.swift in Sources */, 48CFC2862ADC10D900E77A5C /* SubmitTransaction.swift in Sources */, + A4DBBEB52C20305700D0A59E /* CardCarousel+View.swift in Sources */, 48CFC53B2ADC10DA00E77A5C /* ValidatorCollectionItemActiveInEpoch.swift in Sources */, E6A98FA82AE15324003953E2 /* BuildConfiguration.swift in Sources */, 48CFC2C62ADC10D900E77A5C /* MessageMode+Reducer.swift in Sources */, @@ -7056,6 +7126,7 @@ 48CFC2932ADC10D900E77A5C /* AdvancedFeesCustomization+View.swift in Sources */, 48CFC4042ADC10D900E77A5C /* KeychainHolder.swift in Sources */, 48CFC4392ADC10DA00E77A5C /* Sorted.swift in Sources */, + 5B272DD92C36E93100B74F1F /* AppEventsClient+Live.swift in Sources */, 48CFC5622ADC10DA00E77A5C /* FungibleResourcesCollectionItemGloballyAggregated.swift in Sources */, 48CFC4F62ADC10DA00E77A5C /* StateKeyValueStoreDataResponse.swift in Sources */, 48CFC34B2ADC10D900E77A5C /* OneTimePersonaData.swift in Sources */, @@ -7123,6 +7194,7 @@ 48CFC5732ADC10DA00E77A5C /* Configuration.swift in Sources */, 48CFC5A42ADC10DA00E77A5C /* PrimaryTextButtonStyle.swift in Sources */, 83EE47862AF0EE3C00155F03 /* ProgrammaticScryptoSborValueMap.swift in Sources */, + A4DCCC522C2DA33300438A7B /* HomeCardsClient+Test.swift in Sources */, A462B57D2B83656900C26D20 /* MetadataNonFungibleGlobalIdArrayValueAllOfValues.swift in Sources */, 5B80FCC72C298F13008444F5 /* ArbitraryDataField+Models.swift in Sources */, 48CFC2A92ADC10D900E77A5C /* DappDetails+View.swift in Sources */, @@ -7133,6 +7205,7 @@ 48CFC59C2ADC10DA00E77A5C /* Button+Extra.swift in Sources */, E63257652BB314F600952051 /* ExecutionSummary+Extensions.swift in Sources */, 48CFC4A72ADC10DA00E77A5C /* MetadataPublicKeyHashValue.swift in Sources */, + 5BBC7D9E2C3D390E00B04BD6 /* BootstrapClient+Interface.swift in Sources */, 48CFC4EB2ADC10DA00E77A5C /* FungibleResourcesCollectionItemVaultAggregated.swift in Sources */, 48CFC4322ADC10DA00E77A5C /* Async+Extra.swift in Sources */, 48CFC3F72ADC10D900E77A5C /* IncomingMessage.swift in Sources */, @@ -7198,6 +7271,7 @@ 483A3DE62BD2678900055932 /* Stage1MigrateToSargon+FactorSourceCryptoParameters.swift in Sources */, 83EE5EE72BE3C16F00B1531D /* PackageCodeCollection.swift in Sources */, 48CFC36B2ADC10D900E77A5C /* FungibleTokenDetails+Reducer.swift in Sources */, + 5BBC7D9F2C3D390E00B04BD6 /* BootstrapClient+Live.swift in Sources */, 4855B1C72BCAC82200DD0A47 /* Stage1MigrateToSargon+SignatureOfEntity.swift in Sources */, 83EE5EDD2BE3C16F00B1531D /* StatePackageBlueprintPageRequest.swift in Sources */, 48CFC3322ADC10D900E77A5C /* ImportMnemonic.swift in Sources */, @@ -7269,6 +7343,7 @@ 48CFC5562ADC10DA00E77A5C /* GatewayInfoResponseReleaseInfo.swift in Sources */, 48CFC47F2ADC10DA00E77A5C /* ROLAClient+Interface.swift in Sources */, 48CFC46B2ADC10DA00E77A5C /* ImportLegacyWalletClient+Interface.swift in Sources */, + A4DCCC512C2DA33100438A7B /* HomeCardsClient+Live.swift in Sources */, 48CFC4D82ADC10DA00E77A5C /* TransactionStatusResponseKnownPayloadItem.swift in Sources */, 48CFC4522ADC10DA00E77A5C /* NetworkSwitchingClient+Interface.swift in Sources */, 83AAAC6D2B483D1B00222B64 /* StakeSummaryView.swift in Sources */, @@ -7352,6 +7427,7 @@ 48CFC5F42ADC10DA00E77A5C /* L10n.generated.swift in Sources */, 48CFC4D52ADC10DA00E77A5C /* MetadataU32Value.swift in Sources */, 48CFC5992ADC10DA00E77A5C /* InfoPair.swift in Sources */, + 5B272DDB2C36E9D300B74F1F /* AppEventsClient+Test.swift in Sources */, 48CFC33F2ADC10D900E77A5C /* DappInteractionModels.swift in Sources */, 48CFC65A2ADC10DB00E77A5C /* Profile+UpdateNetwork.swift in Sources */, 48CFC49B2ADC10DA00E77A5C /* StateEntityMetadataPageRequest.swift in Sources */, @@ -8578,7 +8654,7 @@ repositoryURL = "https://github.com/radixdlt/sargon"; requirement = { kind = exactVersion; - version = 1.0.23; + version = 1.0.25; }; }; 8318BB172BC8403800057BCB /* XCRemoteSwiftPackageReference "swift-custom-dump" */ = { diff --git a/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index e83911dc18..8ef0f8fe76 100644 --- a/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/RadixWallet.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -114,8 +114,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/radixdlt/sargon", "state" : { - "revision" : "eb02bd76b1261527938aac2cd982b8e1b505acf2", - "version" : "1.0.23" + "revision" : "f04e79c75c0124218f5f3f2d5d6968bbb2ae73b4", + "version" : "1.0.25" } }, { diff --git a/RadixWallet/Clients/AppEventsClient/AppEventsClient+Interface.swift b/RadixWallet/Clients/AppEventsClient/AppEventsClient+Interface.swift new file mode 100644 index 0000000000..f7fabc8677 --- /dev/null +++ b/RadixWallet/Clients/AppEventsClient/AppEventsClient+Interface.swift @@ -0,0 +1,30 @@ +// MARK: - AppEventsClient +public struct AppEventsClient: Sendable { + public var handleEvent: HandleEvent + public var events: Events + + init(handleEvent: @escaping HandleEvent, events: @escaping Events) { + self.handleEvent = handleEvent + self.events = events + } +} + +// MARK: AppEventsClient.HandleEvent +extension AppEventsClient { + public typealias HandleEvent = @Sendable (AppEvent) -> Void + public typealias Events = @Sendable () -> AnyAsyncSequence +} + +extension DependencyValues { + public var appEventsClient: AppEventsClient { + get { self[AppEventsClient.self] } + set { self[AppEventsClient.self] = newValue } + } +} + +// MARK: - AppEvent +public enum AppEvent: Sendable, Hashable { + case appStarted + case walletCreated + case deferredDeepLinkReceived(String) +} diff --git a/RadixWallet/Clients/AppEventsClient/AppEventsClient+Live.swift b/RadixWallet/Clients/AppEventsClient/AppEventsClient+Live.swift new file mode 100644 index 0000000000..74803a264a --- /dev/null +++ b/RadixWallet/Clients/AppEventsClient/AppEventsClient+Live.swift @@ -0,0 +1,14 @@ +extension AppEventsClient: DependencyKey { + public static let liveValue: AppEventsClient = { + let eventsSubject = AsyncReplaySubject(bufferSize: 10) + + return .init( + handleEvent: { event in + eventsSubject.send(event) + }, + events: { + eventsSubject.eraseToAnyAsyncSequence() + } + ) + }() +} diff --git a/RadixWallet/Clients/AppEventsClient/AppEventsClient+Test.swift b/RadixWallet/Clients/AppEventsClient/AppEventsClient+Test.swift new file mode 100644 index 0000000000..fa7b8b170b --- /dev/null +++ b/RadixWallet/Clients/AppEventsClient/AppEventsClient+Test.swift @@ -0,0 +1,16 @@ +// MARK: - AppEventsClient + TestDependencyKey +extension AppEventsClient: TestDependencyKey { + public static let previewValue = Self.noop + + public static let testValue = Self( + handleEvent: unimplemented("\(Self.self).handleEvent"), + events: unimplemented("\(Self.self).events") + ) +} + +extension AppEventsClient { + public static let noop = Self( + handleEvent: { _ in }, + events: { AsyncLazySequence([]).eraseToAnyAsyncSequence() } + ) +} diff --git a/RadixWallet/Clients/AppsFlyerClient/AppsFlyerClient+Live.swift b/RadixWallet/Clients/AppsFlyerClient/AppsFlyerClient+Live.swift index 1628b8999f..4bcd3c08e1 100644 --- a/RadixWallet/Clients/AppsFlyerClient/AppsFlyerClient+Live.swift +++ b/RadixWallet/Clients/AppsFlyerClient/AppsFlyerClient+Live.swift @@ -37,16 +37,13 @@ extension AppsFlyerClient: DependencyKey { } private class Delegate: NSObject, DeepLinkDelegate, @unchecked Sendable { + @Dependency(\.appEventsClient) var appEventsClient + func didResolveDeepLink(_ result: DeepLinkResult) { if let deepLink = result.deepLink { loggerGlobal.info("did resolve deep link. Is deferred: \(deepLink.isDeferred). Click events: \(deepLink.clickEvent)") - if deepLink.isDeferred { - let message = if let deepLinkValue = deepLink.clickEvent["deep_link_value"] as? String { - "Resolved deferred DL with value \(deepLinkValue)" - } else { - "Resolved deferred DL without value" - } - AppsFlyerLib.shared().logEvent(message, withValues: deepLink.clickEvent) + if deepLink.isDeferred, let value = deepLink.clickEvent["deep_link_value"] as? String { + appEventsClient.handleEvent(.deferredDeepLinkReceived(value)) } } else if let error = result.error { loggerGlobal.info("failed to resolve deep link. Status: \(result.status), Error: \(error.localizedDescription)") diff --git a/RadixWallet/Clients/BootstrapClient/BootstrapClient+Interface.swift b/RadixWallet/Clients/BootstrapClient/BootstrapClient+Interface.swift new file mode 100644 index 0000000000..f6d713ff7b --- /dev/null +++ b/RadixWallet/Clients/BootstrapClient/BootstrapClient+Interface.swift @@ -0,0 +1,16 @@ +// MARK: - BootstrapClient +struct BootstrapClient: Sendable { + var bootstrap: Bootstrap +} + +// MARK: BootstrapClient.Bootstrap +extension BootstrapClient { + typealias Bootstrap = @Sendable () -> Void +} + +extension DependencyValues { + var bootstrapClient: BootstrapClient { + get { self[BootstrapClient.self] } + set { self[BootstrapClient.self] = newValue } + } +} diff --git a/RadixWallet/Clients/BootstrapClient/BootstrapClient+Live.swift b/RadixWallet/Clients/BootstrapClient/BootstrapClient+Live.swift new file mode 100644 index 0000000000..d7728ed4a0 --- /dev/null +++ b/RadixWallet/Clients/BootstrapClient/BootstrapClient+Live.swift @@ -0,0 +1,13 @@ +extension BootstrapClient: DependencyKey { + static var liveValue: BootstrapClient { + @Dependency(\.appsFlyerClient) var appsFlyerClient + @Dependency(\.homeCardsClient) var homeCardsClient + + return .init( + bootstrap: { + appsFlyerClient.start() + homeCardsClient.bootstrap() + } + ) + } +} diff --git a/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Interface.swift b/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Interface.swift new file mode 100644 index 0000000000..a35eb3b500 --- /dev/null +++ b/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Interface.swift @@ -0,0 +1,32 @@ +// MARK: - HomeCardsClient +public struct HomeCardsClient: Sendable { + public var cards: Cards + public var removeCard: RemoveCard + + init( + cards: @escaping Cards, + removeCard: @escaping RemoveCard + ) { + self.cards = cards + self.removeCard = removeCard + } +} + +extension HomeCardsClient { + public typealias Cards = @Sendable () -> AnyAsyncSequence<[HomeCard]> + public typealias RemoveCard = @Sendable (HomeCard) -> Void +} + +extension DependencyValues { + public var homeCardsClient: HomeCardsClient { + get { self[HomeCardsClient.self] } + set { self[HomeCardsClient.self] = newValue } + } +} + +extension HomeCardsClient { + /// An empty method to be called when the app starts, so that the client gets initialized before being used for the first time. + /// This is necessary to monitor events that need to be delivered to Sargon before the client is used from its respective UI. + /// Should be removed once SargonOS is integrated. + func bootstrap() {} +} diff --git a/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Live.swift b/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Live.swift new file mode 100644 index 0000000000..5cc8171a43 --- /dev/null +++ b/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Live.swift @@ -0,0 +1,70 @@ +import ComposableArchitecture + +// MARK: - HomeCardsClient + DependencyKey +extension HomeCardsClient: DependencyKey { + public static let liveValue: Self = { + @Dependency(\.appEventsClient) var appEventsClient + + let observer = HomeCardsObserver() + + // We are hardcoding to `.mainnet` because the cards are currently gateway agnostic. In the future, when Profile is integrated into Sargon, it will be Sargon + // observing the current gateway and defining the networkId to use. + let manager = HomeCardsManager(networkAntenna: URLSession.shared, networkId: .mainnet, cardsStorage: HomeCardsStorage(), observer: observer) + + Task { + for try await event in appEventsClient.events() { + guard !Task.isCancelled else { return } + await handle(event: event) + } + } + + @Sendable + func handle(event: AppEvent) async { + switch event { + case .appStarted: + try? await manager.bootstrap() + case .walletCreated: + try? await manager.walletCreated() + case let .deferredDeepLinkReceived(value): + try? await manager.deferredDeepLinkReceived(encodedValue: value) + } + } + + return Self( + cards: { + observer.subject.eraseToAnyAsyncSequence() + }, + removeCard: { card in + Task { + try? await manager.cardDismissed(card: card) + } + } + ) + }() +} + +// MARK: - HomeCardsManager + Sendable +extension HomeCardsManager: @unchecked Sendable {} + +// MARK: - HomeCardsStorage +private final class HomeCardsStorage: Sargon.HomeCardsStorage { + private let userDefaults = UserDefaults.Dependency.radix + + func saveCards(encodedCards: Data) async throws { + userDefaults.setHomeCards(encodedCards) + } + + func loadCards() async throws -> Data? { + userDefaults.getHomeCards() + } +} + +// MARK: - HomeCardsObserver +private final class HomeCardsObserver: Sargon.HomeCardsObserver, Sendable { + let subject: AsyncCurrentValueSubject<[HomeCard]> = .init([]) + + func handleCardsUpdate(cards: [HomeCard]) { + print("M- Received cards from Sargon \(cards)") + subject.send(cards) + } +} diff --git a/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Test.swift b/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Test.swift new file mode 100644 index 0000000000..b69288bb1d --- /dev/null +++ b/RadixWallet/Clients/HomeCardsClient/HomeCardsClient+Test.swift @@ -0,0 +1,16 @@ +// MARK: - HomeCardsClient + TestDependencyKey +extension HomeCardsClient: TestDependencyKey { + public static let previewValue = Self.noop + + public static let testValue = Self( + cards: unimplemented("\(Self.self).cards"), + removeCard: unimplemented("\(Self.self).removeCard") + ) +} + +extension HomeCardsClient { + public static let noop = Self( + cards: { AsyncLazySequence([]).eraseToAnyAsyncSequence() }, + removeCard: { _ in } + ) +} diff --git a/RadixWallet/Clients/UserDefaults+Dependency+Extension/UserDefaults+Dependency+Extension.swift b/RadixWallet/Clients/UserDefaults+Dependency+Extension/UserDefaults+Dependency+Extension.swift index 3aff79a557..7eaa82cbfb 100644 --- a/RadixWallet/Clients/UserDefaults+Dependency+Extension/UserDefaults+Dependency+Extension.swift +++ b/RadixWallet/Clients/UserDefaults+Dependency+Extension/UserDefaults+Dependency+Extension.swift @@ -5,7 +5,6 @@ import Sargon // MARK: - UserDefaultsKey public enum UserDefaultsKey: String, Sendable, Hashable, CaseIterable { case hideMigrateOlympiaButton - case showRadixBanner case epochForWhenLastUsedByAccountAddress case transactionsCompletedCounter case dateOfLastSubmittedNPSSurvey @@ -16,6 +15,7 @@ public enum UserDefaultsKey: String, Sendable, Hashable, CaseIterable { case lastSyncedAccountsWithCE case showRelinkConnectorsAfterUpdate case showRelinkConnectorsAfterProfileRestore + case homeCards /// DO NOT CHANGE THIS KEY case activeProfileID @@ -97,14 +97,6 @@ extension UserDefaults.Dependency { set(value, forKey: Key.hideMigrateOlympiaButton.rawValue) } - public var showRadixBanner: Bool { - bool(key: .showRadixBanner) - } - - public func setShowRadixBanner(_ value: Bool) { - set(value, forKey: Key.showRadixBanner.rawValue) - } - public func getActiveProfileID() -> ProfileID? { string(forKey: Key.activeProfileID.rawValue).flatMap(UUID.init(uuidString:)) } @@ -233,6 +225,14 @@ extension UserDefaults.Dependency { public func setShowRelinkConnectorsAfterProfileRestore(_ value: Bool) { set(value, forKey: Key.showRelinkConnectorsAfterProfileRestore.rawValue) } + + public func getHomeCards() -> Data? { + data(key: .homeCards) + } + + public func setHomeCards(_ value: Data) { + set(data: value, key: .homeCards) + } } // MARK: - BackupResult diff --git a/RadixWallet/Core/DesignSystem/Components/CloseButton.swift b/RadixWallet/Core/DesignSystem/Components/CloseButton.swift index b08d9def1f..79d2c8512a 100644 --- a/RadixWallet/Core/DesignSystem/Components/CloseButton.swift +++ b/RadixWallet/Core/DesignSystem/Components/CloseButton.swift @@ -17,21 +17,59 @@ public struct CloseButtonBar: View { // MARK: - CloseButton public struct CloseButton: View { + let kind: Kind let action: () -> Void - public init(action: @escaping () -> Void) { + public init(kind: Kind = .toolbar, action: @escaping () -> Void) { + self.kind = kind self.action = action } -} -extension CloseButton { public var body: some View { Button(action: action) { Image(.close) - .foregroundColor(.app.gray1) - .tint(.app.gray1) + .resizable() + .frame(kind.size) + .tint(kind.tint) + .padding(kind.padding) + } + .frame(.small, alignment: kind.alignment) + } +} + +// MARK: CloseButton.Kind +extension CloseButton { + public enum Kind { + case toolbar + case homeCard + + var size: CGFloat { + switch self { + case .toolbar: .medium1 + case .homeCard: .medium3 + } + } + + var tint: Color { + switch self { + case .toolbar: .app.gray1 + case .homeCard: .app.gray2 + } + } + + var padding: CGFloat { + switch self { + case .toolbar: .zero + case .homeCard: .small2 + } + } + + var alignment: Alignment { + switch self { + case .toolbar: .center + case .homeCard: .topTrailing + } } - .frame(.small) } } diff --git a/RadixWallet/Core/DesignSystem/Components/GeometryExtensions.swift b/RadixWallet/Core/DesignSystem/Components/GeometryExtensions.swift new file mode 100644 index 0000000000..02ae7b9d7c --- /dev/null +++ b/RadixWallet/Core/DesignSystem/Components/GeometryExtensions.swift @@ -0,0 +1,11 @@ +import Foundation + +extension CGRect { + public subscript(unitPoint: UnitPoint) -> CGPoint { + .init(x: minX + unitPoint.x * width, y: minY + unitPoint.y * height) + } + + public var center: CGPoint { + .init(x: midX, y: midY) + } +} diff --git a/RadixWallet/Core/DesignSystem/Components/JaggedEdge.swift b/RadixWallet/Core/DesignSystem/Components/JaggedEdge.swift index 27f927db42..7acd310798 100644 --- a/RadixWallet/Core/DesignSystem/Components/JaggedEdge.swift +++ b/RadixWallet/Core/DesignSystem/Components/JaggedEdge.swift @@ -62,9 +62,3 @@ struct JaggedEdgeShape: Shape { } } } - -extension CGRect { - subscript(unitPoint: UnitPoint) -> CGPoint { - .init(x: minX + unitPoint.x * width, y: minY + unitPoint.y * height) - } -} diff --git a/RadixWallet/Core/DesignSystem/HitTargetSize.swift b/RadixWallet/Core/DesignSystem/HitTargetSize.swift index 0b523b29b3..c1ab2f1a26 100644 --- a/RadixWallet/Core/DesignSystem/HitTargetSize.swift +++ b/RadixWallet/Core/DesignSystem/HitTargetSize.swift @@ -1,5 +1,8 @@ // MARK: - HitTargetSize public enum HitTargetSize: CGFloat { + //// 18 + case icon = 18 + /// 24 case smallest = 24 @@ -36,6 +39,8 @@ public enum HitTargetSize: CGFloat { public var cornerRadius: CGFloat { switch self { + case .icon: + .small3 case .smallest: .small3 case .verySmall: @@ -65,6 +70,11 @@ extension View { public func frame(_ size: HitTargetSize, alignment: Alignment = .center) -> some View { frame(width: size.frame.width, height: size.frame.height, alignment: alignment) } + + @inlinable + public func frame(_ size: CGFloat, alignment: Alignment = .center) -> some View { + frame(width: size, height: size, alignment: alignment) + } } // MARK: - Screen diff --git a/RadixWallet/Core/Resources/Generated/AssetResource.generated.swift b/RadixWallet/Core/Resources/Generated/AssetResource.generated.swift index 214ec0cf33..28027465d4 100644 --- a/RadixWallet/Core/Resources/Generated/AssetResource.generated.swift +++ b/RadixWallet/Core/Resources/Generated/AssetResource.generated.swift @@ -53,6 +53,8 @@ public enum AssetResource { public static let supplyFlexible = ImageAsset(name: "supply-flexible") public static let supplyIncreasableByAnyone = ImageAsset(name: "supply-increasable-by-anyone") public static let supplyIncreasable = ImageAsset(name: "supply-increasable") + public static let carouselBackgroundConnect = ImageAsset(name: "carousel_background_connect") + public static let carouselBackgroundRadquest = ImageAsset(name: "carousel_background_radquest") public static let arrowBack = ImageAsset(name: "arrow-back") public static let check = ImageAsset(name: "check") public static let checkmarkBig = ImageAsset(name: "checkmark-big") diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/Contents.json b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/Contents.json b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/Contents.json new file mode 100644 index 0000000000..871a2c87be --- /dev/null +++ b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "carousel_background_connect.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "carousel_background_connect@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "carousel_background_connect@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect.png b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect.png new file mode 100644 index 0000000000..8c97ec2e63 Binary files /dev/null and b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect.png differ diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect@2x.png b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect@2x.png new file mode 100644 index 0000000000..8862dfd2f7 Binary files /dev/null and b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect@2x.png differ diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect@3x.png b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect@3x.png new file mode 100644 index 0000000000..79833dfc12 Binary files /dev/null and b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_connect.imageset/carousel_background_connect@3x.png differ diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/Contents.json b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/Contents.json new file mode 100644 index 0000000000..9fbcc9edc8 --- /dev/null +++ b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "carousel_background_radquest.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "carousel_background_radquest@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "carousel_background_radquest@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest.png b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest.png new file mode 100644 index 0000000000..564a5efe85 Binary files /dev/null and b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest.png differ diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest@2x.png b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest@2x.png new file mode 100644 index 0000000000..827a476647 Binary files /dev/null and b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest@2x.png differ diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest@3x.png b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest@3x.png new file mode 100644 index 0000000000..bc5ae98f2a Binary files /dev/null and b/RadixWallet/Core/Resources/Resources/Assets.xcassets/CardCarousel/carousel_background_radquest.imageset/carousel_background_radquest@3x.png differ diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/Home/radix-banner.imageset/Contents.json b/RadixWallet/Core/Resources/Resources/Assets.xcassets/Home/radix-banner.imageset/Contents.json deleted file mode 100644 index fd72ecb71d..0000000000 --- a/RadixWallet/Core/Resources/Resources/Assets.xcassets/Home/radix-banner.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "radix-banner.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/Home/radix-banner.imageset/radix-banner.pdf b/RadixWallet/Core/Resources/Resources/Assets.xcassets/Home/radix-banner.imageset/radix-banner.pdf deleted file mode 100644 index e4310e540d..0000000000 Binary files a/RadixWallet/Core/Resources/Resources/Assets.xcassets/Home/radix-banner.imageset/radix-banner.pdf and /dev/null differ diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/Settings/connector-browsers-icon.imageset/Contents.json b/RadixWallet/Core/Resources/Resources/Assets.xcassets/Settings/connector-browsers-icon.imageset/Contents.json deleted file mode 100644 index 554d278bf7..0000000000 --- a/RadixWallet/Core/Resources/Resources/Assets.xcassets/Settings/connector-browsers-icon.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "connector-browsers-icon.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/RadixWallet/Core/Resources/Resources/Assets.xcassets/Settings/connector-browsers-icon.imageset/connector-browsers-icon.pdf b/RadixWallet/Core/Resources/Resources/Assets.xcassets/Settings/connector-browsers-icon.imageset/connector-browsers-icon.pdf deleted file mode 100644 index 0035165de2..0000000000 Binary files a/RadixWallet/Core/Resources/Resources/Assets.xcassets/Settings/connector-browsers-icon.imageset/connector-browsers-icon.pdf and /dev/null differ diff --git a/RadixWallet/Features/AppFeature/App+Reducer.swift b/RadixWallet/Features/AppFeature/App+Reducer.swift index 4b2f2194ad..2cc30f099c 100644 --- a/RadixWallet/Features/AppFeature/App+Reducer.swift +++ b/RadixWallet/Features/AppFeature/App+Reducer.swift @@ -58,6 +58,8 @@ public struct App: Sendable, FeatureReducer { @Dependency(\.deepLinkHandlerClient) var deepLinkHandlerClient @Dependency(\.overlayWindowClient) var overlayWindowClient @Dependency(\.resetWalletClient) var resetWalletClient + @Dependency(\.homeCardsClient) var homeCardsClient + @Dependency(\.appEventsClient) var appEventsClient public init() {} @@ -91,6 +93,7 @@ public struct App: Sendable, FeatureReducer { } return .none case .task: + appEventsClient.handleEvent(.appStarted) return didResetWalletEffect() } } diff --git a/RadixWallet/Features/AppFeature/AppDelegate.swift b/RadixWallet/Features/AppFeature/AppDelegate.swift index 4d49989af0..50ef778919 100644 --- a/RadixWallet/Features/AppFeature/AppDelegate.swift +++ b/RadixWallet/Features/AppFeature/AppDelegate.swift @@ -3,6 +3,7 @@ import SwiftUI // MARK: - AppDelegate public final class AppDelegate: NSObject, UIApplicationDelegate { + @Dependency(\.bootstrapClient) var bootstrapClient @Dependency(\.appsFlyerClient) var appsFlyerClient public func application( @@ -16,7 +17,7 @@ public final class AppDelegate: NSObject, UIApplicationDelegate { } public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { - appsFlyerClient.start() + bootstrapClient.bootstrap() return true } diff --git a/RadixWallet/Features/CardCarousel/CardCarousel+Reducer.swift b/RadixWallet/Features/CardCarousel/CardCarousel+Reducer.swift new file mode 100644 index 0000000000..bdcb706f9a --- /dev/null +++ b/RadixWallet/Features/CardCarousel/CardCarousel+Reducer.swift @@ -0,0 +1,83 @@ +import ComposableArchitecture + +// MARK: - CardCarousel +@Reducer +public struct CardCarousel: FeatureReducer, Sendable { + @ObservableState + public struct State: Hashable, Sendable { + public var cards: [HomeCard] = [] + } + + public typealias Action = FeatureAction + + @CasePathable + public enum ViewAction: Equatable, Sendable { + case task + case cardTapped(HomeCard) + case closeTapped(HomeCard) + } + + @CasePathable + public enum InternalAction: Equatable, Sendable { + case setCards([HomeCard]) + } + + public enum DelegateAction: Sendable, Equatable { + case addConnector + } + + @Dependency(\.homeCardsClient) var homeCardsClient + @Dependency(\.openURL) var openURL + + public var body: some ReducerOf { + Reduce(core) + } + + public func reduce(into state: inout State, viewAction: ViewAction) -> Effect { + switch viewAction { + case .task: + .run { send in + do { + for try await cards in homeCardsClient.cards() { + await send(.internal(.setCards(cards))) + } + } catch {} + } + case let .cardTapped(card): + cardTappedEffect(card) + .merge(with: removeCardEffect(card)) + case let .closeTapped(card): + removeCardEffect(card) + } + } + + public func reduce(into state: inout State, internalAction: InternalAction) -> Effect { + switch internalAction { + case let .setCards(cards): + state.cards = cards + return .none + } + } + + private func removeCardEffect(_ card: HomeCard) -> Effect { + homeCardsClient.removeCard(card) + return .none + } + + private func cardTappedEffect(_ card: HomeCard) -> Effect { + switch card { + case .continueRadQuest, .dapp: + .none + case .startRadQuest: + .run { _ in + await openURL(Constants.radquestURL) + } + case .connector: + .send(.delegate(.addConnector)) + } + } + + private enum Constants { + static let radquestURL = URL(string: "https://radquest.io")! + } +} diff --git a/RadixWallet/Features/CardCarousel/CardCarousel+View.swift b/RadixWallet/Features/CardCarousel/CardCarousel+View.swift new file mode 100644 index 0000000000..19b0fe2657 --- /dev/null +++ b/RadixWallet/Features/CardCarousel/CardCarousel+View.swift @@ -0,0 +1,188 @@ +import Foundation +import SwiftUI + +// MARK: - CardCarousel.View +extension CardCarousel { + public struct View: SwiftUI.View { + public let store: StoreOf + + private let margin: CGFloat = .medium1 + private let spacing: CGFloat = .small1 * 0.5 + @ScaledMetric private var height: CGFloat = 105 + @SwiftUI.State private var selectedCardIndex = 0 + + public var body: some SwiftUI.View { + WithPerceptionTracking { + VStack(spacing: .small2) { + coreView + .frame(height: store.cards.isEmpty ? 0 : height) + + positionIndicator + } + } + .task { + store.send(.view(.task)) + } + } + + @MainActor + private var coreView: some SwiftUI.View { + TabView(selection: $selectedCardIndex) { + ForEach(Array(store.cards.enumerated()), id: \.element) { index, card in + CarouselCardView(card: card) { + store.send(.view(.cardTapped(card))) + } closeAction: { + store.send(.view(.closeTapped(card)), animation: .default) + } + .tag(index) + .padding(.horizontal, margin - spacing) + .transition(.scale(scale: 0.8).combined(with: .opacity)) + } + } + .tabViewStyle(.page(indexDisplayMode: .never)) + .animation(.default, value: store.cards) + } + + @ViewBuilder + private var positionIndicator: some SwiftUI.View { + if store.cards.count > 1 { + HStack(spacing: spacing) { + ForEach(0 ..< store.cards.count, id: \.self) { index in + let isSelected = selectedCardIndex == index + Capsule() + .fill(isSelected ? .app.gray2 : .app.gray4) + .frame(isSelected ? spacing : .small3) + } + } + } + } + } +} + +// MARK: - CarouselCardView +public struct CarouselCardView: View { + public let card: HomeCard + public let action: () -> Void + public let closeAction: () -> Void + + public var body: some View { + ZStack(alignment: .topTrailing) { + Button(action: action) { + VStack(alignment: .leading, spacing: .small2) { + HStack(spacing: .small3 * 0.5) { + Text(title) + .textStyle(.body1Header) + .minimumScaleFactor(0.8) + + if showLinkIcon { + Image(.iconLinkOut) + .resizable() + .frame(.icon) + .foregroundStyle(.app.gray2) + } + } + + Text(text) + .lineSpacing(-20) + .lineLimit(nil) + .minimumScaleFactor(0.8) + .textStyle(.body2Regular) + } + .multilineTextAlignment(.leading) + .foregroundStyle(.app.gray1) + .padding([.top, .leading], .medium2) + .padding(.trailing, trailingPadding) + .padding(.bottom, .small1) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + .background(alignment: .trailing) { + background + } + .background(.app.gray5) + .cornerRadius(.small1) + } + + CloseButton(kind: .homeCard, action: closeAction) + } + } + + private var trailingPadding: CGFloat { + switch card { + case .continueRadQuest, .startRadQuest: + 95 + case .dapp: + 85 + case .connector: + 106 + } + } + + private var title: String { + switch card { + case .continueRadQuest: + L10n.HomePageCarousel.RejoinRadquest.title + case .startRadQuest: + L10n.HomePageCarousel.DiscoverRadix.title + case .dapp: + L10n.HomePageCarousel.ContinueOnDapp.title + case .connector: + L10n.HomePageCarousel.UseDappsOnDesktop.title + } + } + + private var text: String { + switch card { + case .continueRadQuest: + L10n.HomePageCarousel.RejoinRadquest.text + case .startRadQuest: + L10n.HomePageCarousel.DiscoverRadix.text + case .dapp: + L10n.HomePageCarousel.ContinueOnDapp.text + case .connector: + L10n.HomePageCarousel.UseDappsOnDesktop.text + } + } + + private var background: some View { + switch card { + case .continueRadQuest: + cardBackground(.gradient(.carouselBackgroundRadquest)) + case .startRadQuest: + cardBackground(.gradient(.carouselBackgroundRadquest)) + case let .dapp(url): + cardBackground(.thumbnail(.dapp, url)) + case .connector: + cardBackground(.gradient(.carouselBackgroundConnect)) + } + } + + private var showLinkIcon: Bool { + switch card { + case .startRadQuest: + true + case .continueRadQuest, .dapp, .connector: + false + } + } + + @ViewBuilder + private func cardBackground(_ type: BackgroundType) -> some View { + switch type { + case let .thumbnail(type, url): + Thumbnail(type, url: url, size: .smallish) + .padding(.trailing, .medium2) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .trailing) + case let .gradient(imageResource): + Image(imageResource) + .resizable() + .aspectRatio(contentMode: .fill) + .mask { + LinearGradient(colors: [.clear, .white, .white], startPoint: .leading, endPoint: .trailing) + } + } + } + + private enum BackgroundType { + case thumbnail(Thumbnail.ContentType, URL?) + case gradient(ImageResource) + } +} diff --git a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift index 0f95b3f375..24440bc6e0 100644 --- a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift +++ b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Models.swift @@ -35,8 +35,7 @@ extension CreateAccountConfig { self.init( isFirstAccount: true, canBeDismissed: false, - navigationButtonCTA: .goHome, - specificNetworkID: nil + navigationButtonCTA: .goHome ) case let .firstAccountOnNewNetwork(specificNetworkID): self.init( @@ -49,15 +48,13 @@ extension CreateAccountConfig { self.init( isFirstAccount: false, canBeDismissed: true, - navigationButtonCTA: .goBackToChooseAccounts, - specificNetworkID: nil + navigationButtonCTA: .goBackToChooseAccounts ) case .newAccountFromHome: self.init( isFirstAccount: false, canBeDismissed: true, - navigationButtonCTA: .goHome, - specificNetworkID: nil + navigationButtonCTA: .goHome ) } } diff --git a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift index 244e2e95c5..3f33201c62 100644 --- a/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift +++ b/RadixWallet/Features/CreateAccount/Coordinator/CreateAccountCoordinator+Reducer.swift @@ -99,6 +99,7 @@ public struct CreateAccountCoordinator: Sendable, FeatureReducer { public enum DelegateAction: Sendable, Equatable { case dismissed + case accountCreated case completed } @@ -196,7 +197,7 @@ extension CreateAccountCoordinator { account: account, config: state.config ))) - return .none + return .send(.delegate(.accountCreated)) } } diff --git a/RadixWallet/Features/HomeFeature/Coordinator/Home+View.swift b/RadixWallet/Features/HomeFeature/Coordinator/Home+View.swift index 417f6f115c..72b4cf24cc 100644 --- a/RadixWallet/Features/HomeFeature/Coordinator/Home+View.swift +++ b/RadixWallet/Features/HomeFeature/Coordinator/Home+View.swift @@ -3,17 +3,13 @@ import SwiftUI extension Home.State { var viewState: Home.ViewState { - .init( - showRadixBanner: showRadixBanner, - totalFiatWorth: showFiatWorth ? totalFiatWorth : nil - ) + .init(totalFiatWorth: showFiatWorth ? totalFiatWorth : nil) } } // MARK: - Home.View extension Home { public struct ViewState: Equatable { - let showRadixBanner: Bool let totalFiatWorth: Loadable? } @@ -29,7 +25,7 @@ extension Home { WithViewStore(store, observe: \.viewState) { viewStore in ScrollView { VStack(spacing: .medium1) { - HeaderView() + HeaderView(store: store) if let fiatWorth = viewStore.totalFiatWorth { VStack(spacing: .small2) { @@ -64,19 +60,9 @@ extension Home { store.send(.view(.createAccountButtonTapped)) } .buttonStyle(.secondaryRectangular()) - - if viewStore.showRadixBanner { - RadixBanner { - store.send(.view(.radixBannerButtonTapped)) - } dismiss: { - store.send(.view(.radixBannerDismissButtonTapped)) - } - .transition(.scale(scale: 0.8).combined(with: .opacity)) - } } .padding(.bottom, .medium3) } - .animation(.default, value: viewStore.showRadixBanner) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { @@ -102,23 +88,19 @@ extension Home { } } - private struct HeaderView: SwiftUI.View { + struct HeaderView: SwiftUI.View { + let store: StoreOf + var body: some SwiftUI.View { - VStack(alignment: .leading, spacing: .small2) { + VStack(spacing: .small2) { Text(L10n.HomePage.title) .foregroundColor(.app.gray1) .textStyle(.sheetTitle) + .flushedLeft + .padding(.horizontal, .medium1) - HStack { - Text(L10n.HomePage.subtitle) - .foregroundColor(.app.gray2) - .textStyle(.body1HighImportance) - .lineLimit(2) - - Spacer(minLength: 2 * .large1) - } + CardCarousel.View(store: store.scope(state: \.carousel, action: \.child.carousel)) } - .padding(.leading, .medium1) .padding(.top, .small3) } } @@ -144,6 +126,7 @@ private extension View { .userFeedback(with: destinationStore) .relinkConnector(with: destinationStore) .securityCenter(with: destinationStore) + .p2pLinks(with: destinationStore) } private func accountDetails(with destinationStore: PresentationStoreOf) -> some View { @@ -179,6 +162,12 @@ private extension View { SecurityCenter.View(store: $0) } } + + private func p2pLinks(with destinationStore: PresentationStoreOf) -> some View { + navigationDestination(store: destinationStore.scope(state: \.p2pLinks, action: \.p2pLinks)) { + P2PLinksFeature.View(store: $0) + } + } } extension View { @@ -194,45 +183,6 @@ extension View { } } -// MARK: - RadixBanner -struct RadixBanner: View { - let action: () -> Void - let dismiss: () -> Void - - var body: some View { - VStack(spacing: 0) { - Image(asset: AssetResource.radixBanner) - .padding(.top, .medium1) - - Text(L10n.HomePage.RadixBanner.title) - .textStyle(.body1Header) - .foregroundColor(.app.gray1) - .padding(.bottom, .small2) - - Text(L10n.HomePage.RadixBanner.subtitle) - .multilineTextAlignment(.center) - .textStyle(.body2Regular) - .foregroundColor(.app.gray2) - .padding(.horizontal, .huge3) - .padding(.bottom, .medium3) - - Button(L10n.HomePage.RadixBanner.action, action: action) - .buttonStyle(.secondaryRectangular( - shouldExpand: true, - trailingImage: .init(asset: AssetResource.iconLinkOut) - )) - .padding([.horizontal, .bottom], .medium3) - } - .background(Color.app.gray5) - .cornerRadius(.medium3) - .overlay(alignment: .topTrailing) { - CloseButton(action: dismiss) - .padding(.small3) - } - .padding([.horizontal, .bottom], .medium3) - } -} - #if DEBUG import ComposableArchitecture import SwiftUI diff --git a/RadixWallet/Features/HomeFeature/Coordinator/Home.swift b/RadixWallet/Features/HomeFeature/Coordinator/Home.swift index aff2cae33e..bd68b8769e 100644 --- a/RadixWallet/Features/HomeFeature/Coordinator/Home.swift +++ b/RadixWallet/Features/HomeFeature/Coordinator/Home.swift @@ -4,18 +4,17 @@ import SwiftUI // MARK: - Home public struct Home: Sendable, FeatureReducer { - public static let radixBannerURL = URL(string: "https://wallet.radixdlt.com/?wallet=downloaded")! - private enum CancellableId: Hashable { case fetchAccountPortfolios } public struct State: Sendable, Hashable { // MARK: - Components + public var carousel: CardCarousel.State = .init() + public var accountRows: IdentifiedArrayOf = [] fileprivate var problems: [SecurityProblem] = [] - public var showRadixBanner: Bool = false public var showFiatWorth: Bool = true public var totalFiatWorth: Loadable = .idle @@ -54,13 +53,10 @@ public struct Home: Sendable, FeatureReducer { case pullToRefreshStarted case createAccountButtonTapped case settingsButtonTapped - case radixBannerButtonTapped - case radixBannerDismissButtonTapped case showFiatWorthToggled } public enum InternalAction: Sendable, Equatable { - public typealias HasAccessToMnemonic = Bool case accountsLoadedResult(TaskResult) case currentGatewayChanged(to: Gateway) case shouldShowNPSSurvey(Bool) @@ -70,7 +66,9 @@ public struct Home: Sendable, FeatureReducer { case setSecurityProblems([SecurityProblem]) } + @CasePathable public enum ChildAction: Sendable, Equatable { + case carousel(CardCarousel.Action) case account(id: Home.AccountRow.State.ID, action: Home.AccountRow.Action) } @@ -87,6 +85,7 @@ public struct Home: Sendable, FeatureReducer { case npsSurvey(NPSSurvey.State) case relinkConnector(NewConnection.State) case securityCenter(SecurityCenter.State) + case p2pLinks(P2PLinksFeature.State) } @CasePathable @@ -97,6 +96,7 @@ public struct Home: Sendable, FeatureReducer { case npsSurvey(NPSSurvey.Action) case relinkConnector(NewConnection.Action) case securityCenter(SecurityCenter.Action) + case p2pLinks(P2PLinksFeature.Action) public enum AcknowledgeJailbreakAlert: Sendable, Hashable {} } @@ -117,10 +117,12 @@ public struct Home: Sendable, FeatureReducer { Scope(state: \.securityCenter, action: \.securityCenter) { SecurityCenter() } + Scope(state: \.p2pLinks, action: \.p2pLinks) { + P2PLinksFeature() + } } } - @Dependency(\.openURL) var openURL @Dependency(\.errorQueue) var errorQueue @Dependency(\.userDefaults) var userDefaults @Dependency(\.accountsClient) var accountsClient @@ -139,6 +141,10 @@ public struct Home: Sendable, FeatureReducer { public init() {} public var body: some ReducerOf { + Scope(state: \.carousel, action: \.child.carousel) { + CardCarousel() + } + Reduce(core) .forEach(\.accountRows, action: /Action.child .. ChildAction.account) { Home.AccountRow() @@ -167,8 +173,6 @@ public struct Home: Sendable, FeatureReducer { return .none case .task: - state.showRadixBanner = userDefaults.showRadixBanner - return .run { send in for try await accounts in await accountsClient.accountsOnCurrentNetwork() { guard !Task.isCancelled else { return } @@ -199,16 +203,6 @@ public struct Home: Sendable, FeatureReducer { case .pullToRefreshStarted: return fetchAccountPortfolios(state) - case .radixBannerButtonTapped: - return .run { _ in - await openURL(Home.radixBannerURL) - } - - case .radixBannerDismissButtonTapped: - userDefaults.setShowRadixBanner(false) - state.showRadixBanner = false - return .none - case .settingsButtonTapped: return .send(.delegate(.displaySettings)) @@ -310,6 +304,10 @@ public struct Home: Sendable, FeatureReducer { return .none } + case .carousel(.delegate(.addConnector)): + state.destination = .p2pLinks(.init(destination: .newConnection(.init()))) + return .none + default: return .none } diff --git a/RadixWallet/Features/OnboardingFeature/Children/Startup/OnboardingStartup+Reducer.swift b/RadixWallet/Features/OnboardingFeature/Children/Startup/OnboardingStartup+Reducer.swift index c2af8581f1..cf4d1530f3 100644 --- a/RadixWallet/Features/OnboardingFeature/Children/Startup/OnboardingStartup+Reducer.swift +++ b/RadixWallet/Features/OnboardingFeature/Children/Startup/OnboardingStartup+Reducer.swift @@ -50,11 +50,9 @@ public struct OnboardingStartup: Sendable, FeatureReducer { public func reduce(into state: inout State, viewAction: ViewAction) -> Effect { switch viewAction { case .selectedNewWalletUser: - userDefaults.setShowRadixBanner(true) return .send(.delegate(.setupNewUser)) case .selectedRestoreFromBackup: - userDefaults.setShowRadixBanner(false) state.destination = .restoreFromBackup(.init()) return .none } diff --git a/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift b/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift index c71a8dce66..f9b762382d 100644 --- a/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift +++ b/RadixWallet/Features/OnboardingFeature/Coordinator/OnboardingCoordinator+Reducer.swift @@ -25,12 +25,9 @@ public struct OnboardingCoordinator: Sendable, FeatureReducer { case completed } - public enum InternalAction: Sendable, Equatable { - case finishedOnboarding - } - @Dependency(\.onboardingClient) var onboardingClient @Dependency(\.radixConnectClient) var radixConnectClient + @Dependency(\.appEventsClient) var appEventsClient public init() {} @@ -48,13 +45,6 @@ public struct OnboardingCoordinator: Sendable, FeatureReducer { Reduce(core) } - public func reduce(into state: inout State, internalAction: InternalAction) -> Effect { - switch internalAction { - case .finishedOnboarding: - sendDelegateCompleted(state: state) - } - } - public func reduce(into state: inout State, childAction: ChildAction) -> Effect { switch childAction { case .startup(.delegate(.setupNewUser)): @@ -71,13 +61,16 @@ public struct OnboardingCoordinator: Sendable, FeatureReducer { case .startup(.delegate(.completed)): return sendDelegateCompleted(state: state) - case .createAccountCoordinator(.delegate(.completed)): - return .run { send in + case .createAccountCoordinator(.delegate(.accountCreated)): + appEventsClient.handleEvent(.walletCreated) + return .run { _ in _ = await onboardingClient.finishOnboarding() _ = await radixConnectClient.loadP2PLinksAndConnectAll() - await send(.internal(.finishedOnboarding)) } + case .createAccountCoordinator(.delegate(.completed)): + return sendDelegateCompleted(state: state) + default: return .none } diff --git a/RadixWallet/Features/SettingsFeature/DebugSettings/Children/DebugUserDefaultsContents/DebugUserDefaultsContents.swift b/RadixWallet/Features/SettingsFeature/DebugSettings/Children/DebugUserDefaultsContents/DebugUserDefaultsContents.swift index 1277a2f3db..6a7c506ace 100644 --- a/RadixWallet/Features/SettingsFeature/DebugSettings/Children/DebugUserDefaultsContents/DebugUserDefaultsContents.swift +++ b/RadixWallet/Features/SettingsFeature/DebugSettings/Children/DebugUserDefaultsContents/DebugUserDefaultsContents.swift @@ -98,8 +98,6 @@ extension UserDefaults.Dependency.Key { return userDefaults.loadEpochForWhenLastUsedByAccountAddress().epochForAccounts.map { "epoch: \($0.epoch) account: \($0.accountAddress)" } case .hideMigrateOlympiaButton: return [userDefaults.hideMigrateOlympiaButton].map(String.init(describing:)) - case .showRadixBanner: - return [userDefaults.showRadixBanner].map(String.init(describing:)) case .mnemonicsUserClaimsToHaveBackedUp: return userDefaults.getFactorSourceIDOfBackedUpMnemonics().map(String.init(describing:)) case .transactionsCompletedCounter: @@ -120,6 +118,8 @@ extension UserDefaults.Dependency.Key { return [userDefaults.showRelinkConnectorsAfterUpdate].map(String.init(describing:)) case .showRelinkConnectorsAfterProfileRestore: return [userDefaults.showRelinkConnectorsAfterProfileRestore].map(String.init(describing:)) + case .homeCards: + return [userDefaults.getHomeCards() == nil ? "No Data available" : "Data available"] } } } diff --git a/RadixWallet/Features/SettingsFeature/Settings+Reducer.swift b/RadixWallet/Features/SettingsFeature/Settings+Reducer.swift index 61edbea2c4..f1363a65af 100644 --- a/RadixWallet/Features/SettingsFeature/Settings+Reducer.swift +++ b/RadixWallet/Features/SettingsFeature/Settings+Reducer.swift @@ -13,7 +13,6 @@ public struct Settings: Sendable, FeatureReducer { @PresentationState public var destination: Destination.State? - public var userHasNoP2PLinks: Bool? = nil public var securityProblems: [SecurityProblem] = [] fileprivate var personas: [IdentityAddress] = [] @@ -24,7 +23,6 @@ public struct Settings: Sendable, FeatureReducer { public enum ViewAction: Sendable, Equatable { case task - case addConnectorButtonTapped case securityCenterButtonTapped case personasButtonTapped case dappsButtonTapped @@ -35,7 +33,6 @@ public struct Settings: Sendable, FeatureReducer { } public enum InternalAction: Sendable, Equatable { - case setP2PLinks(P2PLinks) case setSecurityProblems([SecurityProblem]) case setPersonas([IdentityAddress]) } @@ -93,7 +90,6 @@ public struct Settings: Sendable, FeatureReducer { // MARK: Reducer @Dependency(\.errorQueue) var errorQueue - @Dependency(\.p2pLinksClient) var p2pLinksClient @Dependency(\.securityCenterClient) var securityCenterClient @Dependency(\.personasClient) var personasClient @Dependency(\.dismiss) var dismiss @@ -111,14 +107,9 @@ public struct Settings: Sendable, FeatureReducer { public func reduce(into state: inout State, viewAction: ViewAction) -> Effect { switch viewAction { case .task: - return p2pLinksEffect() - .merge(with: securityProblemsEffect()) + return securityProblemsEffect() .merge(with: personasEffect()) - case .addConnectorButtonTapped: - state.destination = .manageP2PLinks(.init(destination: .newConnection(.init()))) - return .none - case .securityCenterButtonTapped: state.destination = .securityCenter(.init()) return .none @@ -151,9 +142,6 @@ public struct Settings: Sendable, FeatureReducer { public func reduce(into state: inout State, internalAction: InternalAction) -> Effect { switch internalAction { - case let .setP2PLinks(clients): - state.userHasNoP2PLinks = clients.isEmpty - return .none case let .setSecurityProblems(problems): state.securityProblems = problems return .none @@ -171,27 +159,10 @@ public struct Settings: Sendable, FeatureReducer { .none } } - - public func reduceDismissedDestination(into state: inout State) -> Effect { - switch state.destination { - case .manageP2PLinks: - p2pLinksEffect() - default: - .none - } - } } // MARK: Private extension Settings { - private func p2pLinksEffect() -> Effect { - .run { send in - await send(.internal(.setP2PLinks( - p2pLinksClient.getP2PLinks() - ))) - } - } - private func securityProblemsEffect() -> Effect { .run { send in for try await problems in await securityCenterClient.problems() { diff --git a/RadixWallet/Features/SettingsFeature/Settings+View.swift b/RadixWallet/Features/SettingsFeature/Settings+View.swift index 108ed44052..49c6ea4aa1 100644 --- a/RadixWallet/Features/SettingsFeature/Settings+View.swift +++ b/RadixWallet/Features/SettingsFeature/Settings+View.swift @@ -16,7 +16,6 @@ extension Settings { #if DEBUG let debugAppInfo: String #endif - let shouldShowAddP2PLinkButton: Bool let securityProblems: [SecurityProblem] let personasSecurityProblems: [SecurityProblem] let appVersion: String @@ -39,7 +38,6 @@ extension Settings { self.appVersion = L10n.WalletSettings.appVersion(bundleInfo.shortVersion) #endif - self.shouldShowAddP2PLinkButton = state.userHasNoP2PLinks ?? false self.securityProblems = state.securityProblems self.personasSecurityProblems = state.personasSecurityProblems } @@ -71,12 +69,6 @@ extension Settings.View { WithViewStore(store, observe: \.viewState, send: { .view($0) }) { viewStore in ScrollView { VStack(spacing: .zero) { - if viewStore.shouldShowAddP2PLinkButton { - ConnectExtensionView { - viewStore.send(.addConnectorButtonTapped) - } - } - ForEachStatic(rows(securityProblems: viewStore.securityProblems, personasProblems: viewStore.personasSecurityProblems)) { kind in SettingsRow(kind: kind, store: store) } @@ -251,39 +243,3 @@ private extension View { } #endif } - -// MARK: - Settings.View.ConnectExtensionView -extension Settings.View { - // MARK: - ConnectExtensionView - struct ConnectExtensionView: View { - let action: () -> Void - - var body: some View { - VStack(spacing: .medium2) { - Image(asset: AssetResource.connectorBrowsersIcon) - - VStack(spacing: .medium3) { - Text(L10n.WalletSettings.LinkToConnectorHeader.title) - .textStyle(.body1Header) - .foregroundColor(.app.gray1) - - Text(L10n.WalletSettings.LinkToConnectorHeader.subtitle) - .foregroundColor(.app.gray2) - .textStyle(.body2Regular) - .multilineTextAlignment(.center) - .padding(.horizontal, .large3) - } - - Button(L10n.WalletSettings.LinkToConnectorHeader.button, action: action) - .buttonStyle(.secondaryRectangular( - backgroundColor: .app.gray3, - shouldExpand: true, - image: .init(asset: AssetResource.qrCodeScanner) - )) - } - .padding(.vertical, .large3) - .padding(.horizontal, .large2) - .background(Color.clear) - } - } -}