From b7e1f481487887f84c6558e3bba6c0675abb8bc4 Mon Sep 17 00:00:00 2001 From: Mike Godenzi Date: Fri, 23 Apr 2021 14:42:15 +0200 Subject: [PATCH] fix(): don't display BIP-39 alert isAdvancedMode === false and pass phrase has previously been entered --- .gitlab-ci.yml | 28 +++++---- android/app/build.gradle | 2 +- ios/App/App.xcodeproj/project.pbxproj | 30 ++++++---- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../xcshareddata/xcschemes/App.xcscheme | 20 ++++++- .../xcshareddata/swiftpm/Package.resolved | 4 +- package-lock.json | 57 ++++++++++++------- package.json | 8 +-- src/app/app.component.ts | 5 ++ .../bip85-generate/bip85-generate.page.ts | 15 +++-- .../deserialized-detail.page.ts | 16 ++++-- src/app/pages/tabs/tabs.page.html | 2 +- src/app/pages/tabs/tabs.page.ts | 17 ++++++ src/assets/i18n/en.json | 7 ++- 14 files changed, 151 insertions(+), 64 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8d488930..9fa4e2cb 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,13 +13,14 @@ stages: - qa - native_build - native_test + - publish build_ionic: stage: build script: - docker build -t $GOOGLE_TAG . tags: - - android-ui + - docker unit: stage: test @@ -32,7 +33,7 @@ unit: - docker rm unit-$CI_COMMIT_SHA - docker rm lint-$CI_COMMIT_SHA tags: - - android-ui + - docker artifacts: paths: - lcov.info @@ -42,7 +43,7 @@ build_android: stage: native_build when: manual tags: - - android-ui + - docker variables: LOCAL_ANDROID: 'android-$CI_PIPELINE_ID' script: @@ -97,14 +98,13 @@ qa: after_script: - docker rm -f qa-$CI_PIPELINE_ID || true tags: - - android-ui + - docker build_ios: stage: native_build when: manual before_script: - echo "$IOS_BUILD_JSON" > build.json - - echo "$IOS_EXPORT_OPTIONS" > exportOptions.plist script: - export DEVELOPER_DIR=$XCODE_PATH - nvm use 14 @@ -115,13 +115,21 @@ build_ios: - npx ionic info - npx ionic build --prod - npx cap sync ios - - xcodebuild -workspace ios/App/App.xcworkspace -scheme "App" -destination generic/platform=iOS -configuration Release archive -archivePath ios/App.xcarchive MARKETING_VERSION=$VERSION CURRENT_PROJECT_VERSION=$CI_PIPELINE_ID -allowProvisioningUpdates - - xcodebuild -exportArchive -archivePath ios/App.xcarchive -exportOptionsPlist exportOptions.plist -exportPath ios/ -allowProvisioningUpdates - - xcrun altool --upload-app -f ios/App.ipa -u $IOS_USERNAME -p $IOS_PASSWORD + - xcodebuild -workspace ios/App/App.xcworkspace -scheme "App" -destination generic/platform=iOS -configuration Release archive -archivePath ios/airgap-vault-$VERSION-$CI_PIPELINE_ID.xcarchive MARKETING_VERSION=$VERSION CURRENT_PROJECT_VERSION=$CI_PIPELINE_ID -allowProvisioningUpdates artifacts: paths: - - ios/App.ipa - - ios/App.xcarchive + - ios/airgap-vault-$VERSION-$CI_PIPELINE_ID.xcarchive tags: - ios +publish_ios: + stage: publish + when: manual + before_script: + - echo "$IOS_EXPORT_OPTIONS" > exportOptions.plist + script: + - export DEVELOPER_DIR=$XCODE_PATH + - xcodebuild -exportArchive -archivePath ios/airgap-vault-$VERSION-$CI_PIPELINE_ID.xcarchive -exportOptionsPlist exportOptions.plist -exportPath ios/ -allowProvisioningUpdates + - xcrun altool --upload-app -f ios/App.ipa -u $IOS_USERNAME -p $IOS_PASSWORD + tags: + - ios diff --git a/android/app/build.gradle b/android/app/build.gradle index 480578d6..1b04b4a2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -66,7 +66,7 @@ dependencies { implementation 'com.google.android.material:material:1.2.0' implementation 'com.scottyab:rootbeer-lib:0.0.7' - def saplingVersion = "0.0.5-beta10" + def saplingVersion = "0.0.6" implementation "com.github.airgap-it:airgap-sapling:$saplingVersion" } diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 45559a55..b2b1a628 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ 2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; 49690A7E25C2BF80004A3586 /* VaultError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49690A7D25C2BF80004A3586 /* VaultError.swift */; }; + 49D642732629D22A0066C013 /* SaplingFFI in Frameworks */ = {isa = PBXBuildFile; productRef = 49D642722629D22A0066C013 /* SaplingFFI */; }; + 49D642752629D22A0066C013 /* Sapling in Frameworks */ = {isa = PBXBuildFile; productRef = 49D642742629D22A0066C013 /* Sapling */; }; 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; @@ -17,7 +19,6 @@ 50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; }; 885F55E825EE224200D85A88 /* SaplingNative.m in Sources */ = {isa = PBXBuildFile; fileRef = 885F55E725EE224200D85A88 /* SaplingNative.m */; }; 885F55EB25EE226300D85A88 /* SaplingNative.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885F55EA25EE226300D85A88 /* SaplingNative.swift */; }; - 888EC6D125EFE88400F0947F /* Sapling in Frameworks */ = {isa = PBXBuildFile; productRef = 888EC6D025EFE88400F0947F /* Sapling */; }; 88AE2EE823D5C7A500428560 /* SecurityUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88AE2EE723D5C7A500428560 /* SecurityUtils.swift */; }; 88AE2EED23D5CB3200428560 /* PluginCall+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88AE2EEC23D5CB3200428560 /* PluginCall+Additions.swift */; }; 88AE2EEF23D5D7B300428560 /* SecurityUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 88AE2EEE23D5D7B300428560 /* SecurityUtils.m */; }; @@ -71,8 +72,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 49D642752629D22A0066C013 /* Sapling in Frameworks */, A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */, - 888EC6D125EFE88400F0947F /* Sapling in Frameworks */, + 49D642732629D22A0066C013 /* SaplingFFI in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -213,7 +215,8 @@ ); name = App; packageProductDependencies = ( - 888EC6D025EFE88400F0947F /* Sapling */, + 49D642722629D22A0066C013 /* SaplingFFI */, + 49D642742629D22A0066C013 /* Sapling */, ); productName = App; productReference = 504EC3041FED79650016851F /* App.app */; @@ -245,7 +248,7 @@ ); mainGroup = 504EC2FB1FED79650016851F; packageReferences = ( - 888EC6CF25EFE88400F0947F /* XCRemoteSwiftPackageReference "airgap-sapling" */, + 49D642712629D22A0066C013 /* XCRemoteSwiftPackageReference "airgap-sapling" */, ); productRefGroup = 504EC3051FED79650016851F /* Products */; projectDirPath = ""; @@ -296,10 +299,10 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( + inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -543,20 +546,25 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 888EC6CF25EFE88400F0947F /* XCRemoteSwiftPackageReference "airgap-sapling" */ = { + 49D642712629D22A0066C013 /* XCRemoteSwiftPackageReference "airgap-sapling" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/airgap-it/airgap-sapling"; requirement = { - kind = exactVersion; - version = "0.0.5-beta10"; + kind = upToNextMajorVersion; + minimumVersion = 0.0.6; }; }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 888EC6D025EFE88400F0947F /* Sapling */ = { + 49D642722629D22A0066C013 /* SaplingFFI */ = { + isa = XCSwiftPackageProductDependency; + package = 49D642712629D22A0066C013 /* XCRemoteSwiftPackageReference "airgap-sapling" */; + productName = SaplingFFI; + }; + 49D642742629D22A0066C013 /* Sapling */ = { isa = XCSwiftPackageProductDependency; - package = 888EC6CF25EFE88400F0947F /* XCRemoteSwiftPackageReference "airgap-sapling" */; + package = 49D642712629D22A0066C013 /* XCRemoteSwiftPackageReference "airgap-sapling" */; productName = Sapling; }; /* End XCSwiftPackageProductDependency section */ diff --git a/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index f3bae547..cc5a0400 100644 --- a/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/airgap-it/airgap-sapling", "state": { "branch": null, - "revision": "aa23b91ba46c93723eca27fa1b41ea4064b9ef1c", - "version": "0.0.5-beta10" + "revision": "c6606fce5d84cea678414681b13ef5efb3629a7e", + "version": "0.0.6" } } ] diff --git a/ios/App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme b/ios/App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme index 95183528..0727d124 100644 --- a/ios/App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme +++ b/ios/App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme @@ -1,7 +1,7 @@ + version = "1.7"> @@ -74,5 +74,23 @@ + + + + + + + + + + diff --git a/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved index f3bae547..cc5a0400 100644 --- a/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ios/App/App.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/airgap-it/airgap-sapling", "state": { "branch": null, - "revision": "aa23b91ba46c93723eca27fa1b41ea4064b9ef1c", - "version": "0.0.5-beta10" + "revision": "c6606fce5d84cea678414681b13ef5efb3629a7e", + "version": "0.0.6" } } ] diff --git a/package-lock.json b/package-lock.json index 7e308f47..3c482c0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,50 +11,58 @@ "dev": true }, "@airgap/angular-core": { - "version": "0.0.9-beta.13", - "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.9-beta.13.tgz", - "integrity": "sha512-X/+YdSAZrY2PBl2JW5B1rFgmxw6QLLuAQTIQtO9RFSTntKMOXUkquJu6ApOPgq1UH6g6O+IS4KIMheVIALvKBA==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.9.tgz", + "integrity": "sha512-aDIPXUX1GKFcmn9/x4ZJJh7+EoAAG75XG+S3U2Y7NyZJnYukypjY3Nt3Lx7G1pCnnV2B1orP+ox/0BnFWVn8tw==", "requires": { "tslib": "^2.0.0" }, "dependencies": { "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" } } }, "@airgap/angular-ngrx": { - "version": "0.0.9-beta.13", - "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.9-beta.13.tgz", - "integrity": "sha512-pxY3sDTPn3VkiL5i4PLwQsE5h6dG0JoudutfFjyAPSQtcqinwf8Jy/mr5U46mloPoI9tOWAHcY0tVhkv8Ka72g==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.9.tgz", + "integrity": "sha512-RQ7RmPtlhtCRQdscNU1vmkpYw44/FFv6mFxAnA6wW30c8G/oq+mdGdGlA6GqJCZQ2lyHJsyac7gPVmGD6HmifQ==", "requires": { "tslib": "^2.0.0" }, "dependencies": { "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" } } }, "@airgap/coinlib-core": { - "version": "0.10.7-beta.3", - "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.10.7-beta.3.tgz", - "integrity": "sha512-2Fl/fApSwvXsz3NKF1VFQA3nH7bWVa+oo/3wPlw6WY12C4C/APeK+0ta04BIj+hG3+lIZ8/RS42mtgIH5S7i1w==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.11.0.tgz", + "integrity": "sha512-bo925ntB0jGanuj9JpwefXtIbZo2+wyLdiShYxNdtLo3hLyuIMd7mOLI13TLTDs2vSTaWGnOcjVGOeE8GPJmFg==", "requires": { - "@airgap/sapling-wasm": "0.0.5-beta.10", + "@airgap/sapling-wasm": "0.0.5", "@polkadot/util": "2.0.1", "@polkadot/wasm-crypto": "0.20.1", + "idna-uts46-hx": "^3.3.1", "libsodium-wrappers": "0.7.6" + }, + "dependencies": { + "@airgap/sapling-wasm": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@airgap/sapling-wasm/-/sapling-wasm-0.0.5.tgz", + "integrity": "sha512-u3dCsqC4WqTlscAU6p5BED+O/tXEDRcIzeOf7OTtz4zoK8wyMX6ZcJImZONhYG6IKu8cSc8eQNwm6fghHL3SxA==" + } } }, "@airgap/sapling-wasm": { - "version": "0.0.5-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/sapling-wasm/-/sapling-wasm-0.0.5-beta.10.tgz", - "integrity": "sha512-0s+j1kleYZRbxM1ej0/7roHwRy0nIG5Dv3pSp0HBtTu0Z/aYPnuAys7gvBY+sRPxaCoJNc9nkwvpD4ogX1kdSg==" + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@airgap/sapling-wasm/-/sapling-wasm-0.0.6.tgz", + "integrity": "sha512-hGD1ZMe3aLIJdjRxq6KVLjMkxza9BW2AZxJEWtVOLAwJDvUyb4yw+i2hnjIKve2kO82m6UJ3tJIDGhbZ4gU6eg==" }, "@angular-devkit/architect": { "version": "0.1000.6", @@ -9242,6 +9250,14 @@ "postcss": "^7.0.14" } }, + "idna-uts46-hx": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-3.4.0.tgz", + "integrity": "sha512-b1I4qYTcJcX1TANn8OhOGrQUIWOfZUWrLKWDeKbV6posVLjp7OTqFKX3N20efrIMzQM1KhiphOEazBEEUFR9bg==", + "requires": { + "punycode": "^2.1.1" + } + }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -14241,8 +14257,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "puppeteer": { "version": "1.20.0", diff --git a/package.json b/package.json index 8b10532d..1d84ca31 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,10 @@ "apply-diagnostic-modules": "node apply-diagnostic-modules.js" }, "dependencies": { - "@airgap/angular-core": "0.0.9-beta.13", - "@airgap/angular-ngrx": "0.0.9-beta.13", - "@airgap/coinlib-core": "0.10.7-beta.3", - "@airgap/sapling-wasm": "0.0.5-beta.10", + "@airgap/angular-core": "0.0.9", + "@airgap/angular-ngrx": "0.0.9", + "@airgap/coinlib-core": "0.11.0", + "@airgap/sapling-wasm": "0.0.6", "@angular/common": "^11.0.4", "@angular/core": "^11.0.4", "@angular/forms": "^11.0.4", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index c7c69575..3377918e 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -144,6 +144,11 @@ export class AppComponent implements AfterViewInit { } private async getSaplingParams(type: 'spend' | 'output'): Promise { + if (this.platform.is('hybrid')) { + // Sapling params are read and used in a native plugin, there's no need to read them in the Ionic part + return Buffer.alloc(0) + } + const params: ArrayBuffer = await this.httpClient .get(`./assets/sapling/sapling-${type}.params`, { responseType: 'arraybuffer' }) .toPromise() diff --git a/src/app/pages/bip85-generate/bip85-generate.page.ts b/src/app/pages/bip85-generate/bip85-generate.page.ts index d4b9b623..28f3b050 100644 --- a/src/app/pages/bip85-generate/bip85-generate.page.ts +++ b/src/app/pages/bip85-generate/bip85-generate.page.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core' import { AlertController } from '@ionic/angular' +import { TranslateService } from '@ngx-translate/core' import { Secret } from 'src/app/models/secret' import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' import { NavigationService } from 'src/app/services/navigation/navigation.service' @@ -20,7 +21,11 @@ export class Bip85GeneratePage { public revealBip39Passphrase: boolean = false public bip39Passphrase: string = '' - constructor(private readonly navigationService: NavigationService, private readonly alertController: AlertController) { + constructor( + private readonly navigationService: NavigationService, + private readonly alertController: AlertController, + private readonly translateService: TranslateService + ) { if (this.navigationService.getState()) { this.secret = this.navigationService.getState().secret console.log(this.secret) @@ -28,16 +33,16 @@ export class Bip85GeneratePage { } public async generateChildSeed() { - if (this.bip39Passphrase.length > 0) { + if (this.bip39Passphrase.length > 0 && this.isAdvancedMode) { const alert = await this.alertController.create({ - header: 'BIP39 Passphrase', - message: 'You set a BIP39 Passphrase. You will need to enter this passphrase again when you try to derive the same child key!', + header: this.translateService.instant('bip85-generate.alert.header'), + message: this.translateService.instant('bip85-generate.alert.message'), backdropDismiss: false, inputs: [ { name: 'understood', type: 'checkbox', - label: 'I understand', + label: this.translateService.instant('bip85-generate.alert.understand'), value: 'understood', checked: false } diff --git a/src/app/pages/deserialized-detail/deserialized-detail.page.ts b/src/app/pages/deserialized-detail/deserialized-detail.page.ts index 7c36b1ad..e1831a41 100644 --- a/src/app/pages/deserialized-detail/deserialized-detail.page.ts +++ b/src/app/pages/deserialized-detail/deserialized-detail.page.ts @@ -4,8 +4,8 @@ import { Component } from '@angular/core' import { ModalController } from '@ionic/angular' import { AlertOptions, LoadingOptions, ModalOptions, OverlayEventDetail } from '@ionic/core' import { Store } from '@ngrx/store' -import { Observable } from 'rxjs' -import { debounceTime, distinctUntilChanged } from 'rxjs/operators' +import { Observable, Subject } from 'rxjs' +import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators' import { ErrorCategory, handleErrorLocal } from '../../services/error-handler/error-handler.service' import { SelectAccountPage } from '../select-account/select-account.page' @@ -40,6 +40,7 @@ export class DeserializedDetailPage { private loadingElement: HTMLIonLoadingElement | undefined private alertElement: HTMLIonAlertElement | undefined private modalElement: HTMLIonModalElement | undefined + private readonly ngDestroyed$: Subject = new Subject() constructor( private readonly store: Store, @@ -60,13 +61,18 @@ export class DeserializedDetailPage { this.rawData$ = this.store.select(fromDeserializedDetail.selectRaw) // FIXME [#210] set debounce time - this.loader$.pipe(debounceTime(0), distinctUntilChanged()).subscribe(this.showOrHideLoader.bind(this)) - this.alert$.subscribe(this.showOrDismissAlert.bind(this)) - this.modal$.subscribe(this.showOrDismissModal.bind(this)) + this.loader$.pipe(debounceTime(0), distinctUntilChanged(), takeUntil(this.ngDestroyed$)).subscribe(this.showOrHideLoader.bind(this)) + this.alert$.pipe(takeUntil(this.ngDestroyed$)).subscribe(this.showOrDismissAlert.bind(this)) + this.modal$.pipe(takeUntil(this.ngDestroyed$)).subscribe(this.showOrDismissModal.bind(this)) this.store.dispatch(actions.viewInitialization()) } + public ngOnDestroy(): void { + this.ngDestroyed$.next() + this.ngDestroyed$.complete() + } + public continue(): void { this.store.dispatch(actions.approved()) } diff --git a/src/app/pages/tabs/tabs.page.html b/src/app/pages/tabs/tabs.page.html index 04a7d2c8..24f72961 100644 --- a/src/app/pages/tabs/tabs.page.html +++ b/src/app/pages/tabs/tabs.page.html @@ -1,4 +1,4 @@ - + diff --git a/src/app/pages/tabs/tabs.page.ts b/src/app/pages/tabs/tabs.page.ts index 99fb1f78..31d49e8b 100644 --- a/src/app/pages/tabs/tabs.page.ts +++ b/src/app/pages/tabs/tabs.page.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core' +import { IonTabs } from '@ionic/angular' @Component({ selector: 'airgap-tabs', @@ -6,5 +7,21 @@ import { Component } from '@angular/core' styleUrls: ['tabs.page.scss'] }) export class TabsPage { + private activeTab?: HTMLElement + constructor() {} + + tabChange(tabsRef: IonTabs) { + this.activeTab = tabsRef.outlet.activatedView.element + } + + ionViewWillEnter() { + this.propagateToActiveTab('ionViewWillEnter') + } + + private propagateToActiveTab(eventName: string) { + if (this.activeTab) { + this.activeTab.dispatchEvent(new CustomEvent(eventName)) + } + } } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 1ee8df34..1ba5230c 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -432,7 +432,12 @@ "generate": "Generate", "advanced_label": "Advanced Mode", "bip39-passphrase": "BIP-39 Passphrase", - "bip39-passphrase-reveal": "Reveal Passphrase" + "bip39-passphrase-reveal": "Reveal Passphrase", + "alert": { + "header": "BIP-39 Passphrase", + "message": "You set a BIP39 Passphrase. You will need to enter this passphrase again when you try to derive the same child key!", + "understand": "I understand" + } }, "bip85-show": {