diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 8d800af70..5e9832f96 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -19,7 +19,7 @@ jobs: - name: Get release version id: version_check - run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//} + run: echo "version_new=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT - name: Build Ionic env: @@ -90,7 +90,7 @@ jobs: - name: Get release version id: version_check - run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//} + run: echo "version_new=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT - name: Build Ionic env: @@ -166,7 +166,7 @@ jobs: - name: Get release version id: version_check - run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//} + run: echo "version_new=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT - name: Build Ionic env: @@ -286,7 +286,7 @@ jobs: - name: Get release version id: version_check - run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//} + run: echo "version_new=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT - name: Create GitHub prerelease id: create_release diff --git a/CHANGELOG.md b/CHANGELOG.md index 69542499b..1fd5fd1a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 To check the difference between the last releaes and the latest dev status, click the link above. +## [0.74.0] - 2023-02-14 + +### Added + +1. Feature support iframe wallet page (#2577) + +### Fixed + +1. Fix camera tap to focus (#2527) +2. Fix to show bronze pack price (#2521) + ## [0.73.1] - 2023-01-30 ### Added @@ -2019,7 +2030,8 @@ This is the first release! _Capture Lite_ is a cross-platform app adapted from [ - Web - see the demo [here](https://github.com/numbersprotocol/capture-lite#demo-app) - Android - the APK file `app-debug.apk` is attached to this release -[unreleased]: https://github.com/numbersprotocol/capture-lite/compare/0.73.1...HEAD +[unreleased]: https://github.com/numbersprotocol/capture-lite/compare/0.74.0...HEAD +[0.74.0]: https://github.com/numbersprotocol/capture-lite/compare/0.73.0...0.74.0 [0.73.1]: https://github.com/numbersprotocol/capture-lite/compare/0.72.4...0.73.1 [0.72.4]: https://github.com/numbersprotocol/capture-lite/compare/0.72.3...0.72.4 [0.72.3]: https://github.com/numbersprotocol/capture-lite/compare/0.72.2...0.72.3 diff --git a/android/app/build.gradle b/android/app/build.gradle index d302e5a6e..f583aa32b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "io.numbersprotocol.capturelite" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 471 - versionName "0.73.1" + versionCode 472 + versionName "0.74.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildFeatures { diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 2abc0cce0..7db3d22e2 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -374,7 +374,7 @@ INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 0.73.1; + MARKETING_VERSION = 0.74.0; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = io.numbersprotocol.capturelite; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -401,7 +401,7 @@ INFOPLIST_FILE = App/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 0.73.1; + MARKETING_VERSION = 0.74.0; PRODUCT_BUNDLE_IDENTIFIER = io.numbersprotocol.capturelite; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = NumbersAppDistributionV4; diff --git a/package-lock.json b/package-lock.json index 30cbdd9b1..b69389392 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "capture-lite", - "version": "0.73.1", + "version": "0.74.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "capture-lite", - "version": "0.73.1", + "version": "0.74.0", "dependencies": { "packages": "^0.0.8", "@angular/animations": "^14.2.0", diff --git a/package.json b/package.json index 2bd9d82ea..a66d443fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "capture-lite", - "version": "0.73.1", + "version": "0.74.0", "author": "numbersprotocol", "homepage": "https://numbersprotocol.io/", "scripts": { diff --git a/src/app/features/home/custom-camera/custom-camera.page.html b/src/app/features/home/custom-camera/custom-camera.page.html index a59b1dfb4..bfbf594b3 100644 --- a/src/app/features/home/custom-camera/custom-camera.page.html +++ b/src/app/features/home/custom-camera/custom-camera.page.html @@ -50,6 +50,7 @@
-
+
{{ product.inAppProduct.title }}
-
+
{{ product.inAppProduct.price }}
diff --git a/src/app/features/wallets/wallets.page.html b/src/app/features/wallets/wallets.page.html index c31a2f78f..c4107a8a7 100644 --- a/src/app/features/wallets/wallets.page.html +++ b/src/app/features/wallets/wallets.page.html @@ -1,149 +1,27 @@ - - - {{ t('wallets.wallets') }} - + + + + {{ 'wallets.walets' | transloco }} + +
+ {{ 'message.networkNotConnected' | transloco }} +
+
- - - -

- ↓{{ t('wallets.pullToRefreshBalance') }}↓ -

- - - - - -

- {{ totalBalance$ | ngrxPush | currency }} NUM -

-
-
- - - - -

NUM

-
-
-
-
- - Mainnet: - - - ${{ mainNumBalance$ | ngrxPush | number: '1.2-2' }} - - - - - - - {{ t('wallets.buyCredits.credits') }}: - {{ points$ | ngrxPush | number: '1.2-2' }} - - - {{ t('wallets.buyCredits.buyCredits') }} - {{ t('wallets.deposit') }} - {{ t('wallets.withdraw') }} - -
-
- - - - -
- {{ t('wallets.myAssetWallet') }} - -
-
{{ assetWalletAddr$ | ngrxPush }}
- -
- - vpn_key -
- {{ t('wallets.integrityWallet') }} - -
-
{{ publicKey$ | ngrxPush }}
- -
- - history -
{{ t('wallets.assetWalletHistory') }}
- -
-
- - {{ t('wallets.exportIntegrityKey') }} - -
+ + + + diff --git a/src/app/features/wallets/wallets.page.scss b/src/app/features/wallets/wallets.page.scss index 0c67b9487..044c5df02 100644 --- a/src/app/features/wallets/wallets.page.scss +++ b/src/app/features/wallets/wallets.page.scss @@ -1,148 +1,39 @@ mat-toolbar { span { padding-right: 40px; + font-style: normal; + font-weight: 500; + font-size: 16px; + line-height: 21px; + text-align: center; + color: white; } -} - -.text-black { - color: black; -} - -#pull-to-refresh-help-text { - margin: 0; - font-style: normal; - font-weight: 500; - font-size: 11px; - line-height: 10px; - text-align: center; - letter-spacing: 0.02em; - color: #9c9c9c; -} - -ion-card { - background: white; - border-radius: 15px; - flex: none; - order: 0; - flex-grow: 0; - margin-top: 5px; - margin-left: 8px; - margin-right: 8px; - - ion-grid { - margin-left: 12px; - margin-right: 8px; - - h1.balance-text { - @media (max-width: 360px) { - font-size: 20px; - } - } - - #num-icon-row { - ion-img { - margin-top: 10px; - width: 29px; - - @media (max-width: 360px) { - width: 20px; - } - } - - h3.num-text { - flex: none; - order: 1; - flex-grow: 0; - margin-top: 21px; - margin-left: 7px; - - @media (max-width: 360px) { - font-size: 20px; - } - } - } - - #mainnet-points-row { - margin-top: 5%; - padding-left: 2%; - align-items: center; - - .mainnet-points { - letter-spacing: 0.05em; - font-weight: bold; - margin-left: 1%; - transform: translateY(-2); - } - - ion-icon { - transform: translateY(0.5px); - font-size: 1.1em; - margin-left: 8px; - margin-right: 5%; - } - - mat-spinner { - margin-left: 5%; - margin-right: 5%; - } - } - #buy-deposit-withdraw-row { - margin-top: 10px; - } + .capture-rebranded-button { + margin: 0 4px; + background: #ffffff40 !important; /* stylelint-disable-line declaration-no-important */ + color: white !important; /* stylelint-disable-line declaration-no-important */ + backdrop-filter: blur(4px); + box-shadow: none; } } -ion-button { - --box-shadow: 0; -} - -.num-operation-btn { - --border-radius: 10.4988px; - - margin-bottom: 16px; - padding-right: 10px; - min-width: 90px; -} - -mat-list { - padding-top: 0; - margin: 0 8px; -} - -#buy-num-btn { - color: white; -} - -.deposit-withdraw-num-btn { - color: #626262; -} - -#export-integrity-wallet-btn { - margin: 8px 16px; -} - -.info-icon { - transform: translateY(3px); - margin-left: 3px; - font-size: 1.1em; -} - -.asset-wallet-qr-code-container { - // background-color: green; - max-width: 300px; - margin: 0 auto; - display: flex; - flex-direction: column; - align-items: center; +.no-network-text { + font-size: 18px; + margin: auto; } -.qr-code-info { - text-align: center; - opacity: 0.6; - font-size: 12px; +.bubble-iframe { + background-color: black; + width: 100vw; + height: 100vh; + border: 0; } -.vertical-pacing-12 { - height: 12px; +ion-spinner { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + scale: 1.5; } diff --git a/src/app/features/wallets/wallets.page.ts b/src/app/features/wallets/wallets.page.ts index 2c46f63c2..53e82c122 100644 --- a/src/app/features/wallets/wallets.page.ts +++ b/src/app/features/wallets/wallets.page.ts @@ -1,31 +1,17 @@ import { Component } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { MatIconRegistry } from '@angular/material/icon'; import { MatSnackBar } from '@angular/material/snack-bar'; -import { DomSanitizer } from '@angular/platform-browser'; import { Router } from '@angular/router'; -import { Browser } from '@capacitor/browser'; import { Clipboard } from '@capacitor/clipboard'; -import { Platform } from '@ionic/angular'; +import { NavController } from '@ionic/angular'; import { TranslocoService } from '@ngneat/transloco'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { NgxQrcodeElementTypes } from '@techiediaries/ngx-qrcode'; -import { BehaviorSubject, combineLatest, forkJoin } from 'rxjs'; -import { - catchError, - concatMap, - finalize, - first, - map, - switchMap, - tap, -} from 'rxjs/operators'; +import { BehaviorSubject, fromEvent } from 'rxjs'; +import { concatMap, first, map, tap } from 'rxjs/operators'; import { WebCryptoApiSignatureProvider } from '../../shared/collector/signature/web-crypto-api-signature-provider/web-crypto-api-signature-provider.service'; -import { ConfirmAlert } from '../../shared/confirm-alert/confirm-alert.service'; import { DiaBackendAuthService } from '../../shared/dia-backend/auth/dia-backend-auth.service'; +import { BUBBLE_IFRAME_URL } from '../../shared/dia-backend/secret'; import { DiaBackendWalletService } from '../../shared/dia-backend/wallet/dia-backend-wallet.service'; -import { ErrorService } from '../../shared/error/error.service'; -import { ExportPrivateKeyModalComponent } from '../../shared/export-private-key-modal/export-private-key-modal.component'; @UntilDestroy({ checkProperties: true }) @Component({ selector: 'app-wallets', @@ -33,168 +19,109 @@ import { ExportPrivateKeyModalComponent } from '../../shared/export-private-key- styleUrls: ['./wallets.page.scss'], }) export class WalletsPage { - readonly domainMainnetNum = 'mainnet.num.network'; - - readonly mainNumBalance$ = - this.diaBackendWalletService.assetWalletMainnetNumBalance$; - readonly points$ = this.diaBackendAuthService.points$; - - readonly totalBalance$ = new BehaviorSubject(0); - readonly publicKey$ = this.webCryptoApiSignatureProvider.publicKey$; readonly privateKey$ = this.webCryptoApiSignatureProvider.privateKey$; readonly assetWalletAddr$ = this.diaBackendWalletService.assetWalletAddr$; - readonly isLoadingBalance$ = new BehaviorSubject(false); readonly networkConnected$ = this.diaBackendWalletService.networkConnected$; + readonly iframeUrl$ = this.diaBackendAuthService.cachedQueryJWTToken$.pipe( + map(token => { + const queryParams = `token=${token.access}&refresh_token=${token.refresh}`; + const url = `${BUBBLE_IFRAME_URL}/wallet?${queryParams}`; + return url; + }) + ); + readonly iframeLoaded$ = new BehaviorSubject(false); + elementType = NgxQrcodeElementTypes.URL; shouldHideDepositButton = false; constructor( private readonly diaBackendWalletService: DiaBackendWalletService, private readonly diaBackendAuthService: DiaBackendAuthService, - private readonly matIconRegistry: MatIconRegistry, - private readonly domSanitizer: DomSanitizer, private readonly snackBar: MatSnackBar, private readonly translocoService: TranslocoService, private readonly webCryptoApiSignatureProvider: WebCryptoApiSignatureProvider, - private readonly confirmAlert: ConfirmAlert, - private readonly dialog: MatDialog, - private readonly errorService: ErrorService, private readonly router: Router, - private readonly platform: Platform - ) { - this.matIconRegistry.addSvgIcon( - 'wallet', - this.domSanitizer.bypassSecurityTrustResourceUrl( - '../../../assets/images/wallet.svg' - ) - ); + private readonly navController: NavController + ) {} + + ionViewDidEnter() { + this.processIframeEvents(); + } - combineLatest([this.mainNumBalance$, this.points$]) + private processIframeEvents() { + fromEvent(window, 'message') .pipe( - first(), - map( - ([mainNumBalance, points]) => Number(mainNumBalance) + Number(points) - ), + tap(event => { + const postMessageEvent = event as MessageEvent; + switch (postMessageEvent.data) { + case 'iframe-on-load': + this.iframeLoaded$.next(true); + break; + case 'iframeBackButtonClicked': + this.navController.pop(); + break; + case 'iframe-buy-num-button-clicked': + this.navigateToBuyNumPage(); + break; + case 'iframe-copy-to-clipboard-asset-wallet': + this.copyToClipboardAssetWallet(); + break; + case 'iframe-copy-to-clipboard-integrity-wallet': + this.copyToClipboardIntegrityWallet(); + break; + case 'iframe-copy-to-clipboard-private-key': + this.copyToClipboardPrivateKey(); + break; + default: + break; + } + }), untilDestroyed(this) ) - .subscribe(totalBalance => this.totalBalance$.next(totalBalance)); - - this.shouldHideDepositButton = this.platform.is('ios'); - } - - // eslint-disable-next-line class-methods-use-this - onBuyNumBtnClicked() { - Browser.open({ - url: `https://link.numbersprotocol.io/buy-num`, - toolbarColor: '#564dfc', - }); - } - - navigateToBuyNumPage() { - this.router.navigate(['wallets', 'buy-num']); + .subscribe(); } - openAssetWalletHistory() { - this.diaBackendWalletService.assetWalletAddr$ + private copyToClipboardAssetWallet() { + this.assetWalletAddr$ .pipe( first(), - switchMap(address => - Browser.open({ - url: `https://${this.domainMainnetNum}/address/${address}`, - toolbarColor: '#000000', - }) - ), + concatMap(assetWalletAddr => this.copyToClipboard(assetWalletAddr)), untilDestroyed(this) ) .subscribe(); } - refreshBalance(event: Event) { - (event).detail.complete(); - this.networkConnected$ + private copyToClipboardIntegrityWallet() { + this.publicKey$ .pipe( first(), - concatMap(networkConnected => { - if (!networkConnected) { - return this.errorService.toastError$( - this.translocoService.translate( - `error.wallets.noNetworkConnectionCannotRefreshBalance` - ) - ); - } - this.isLoadingBalance$.next(true); - return forkJoin([ - this.diaBackendWalletService.syncAssetWalletBalance$(), - this.diaBackendAuthService.syncProfile$(), - ]).pipe( - tap(async ([assetWallet, _]) => { - this.totalBalance$.next( - Number(assetWallet[1]) + - (await this.diaBackendAuthService.getPoints()) - ); - }), - catchError(() => - this.errorService.toastError$( - this.translocoService.translate( - `error.wallets.cannotRefreshBalance` - ) - ) - ), - finalize(() => this.isLoadingBalance$.next(false)) - ); - }), + concatMap(publicKey => this.copyToClipboard(publicKey)), untilDestroyed(this) ) .subscribe(); } - async onDepositWithdrawBtnClick(mode: 'deposit' | 'withdraw') { - this.networkConnected$ + private copyToClipboardPrivateKey() { + this.privateKey$ .pipe( first(), - concatMap(networkConnected => { - if (!networkConnected) { - return this.errorService.toastError$( - this.translocoService.translate(`error.internetError`) - ); - } - return this.router.navigate(['wallets', 'transfer', mode]); - }), + concatMap(privateKey => this.copyToClipboard(privateKey)), untilDestroyed(this) ) .subscribe(); } + navigateToBuyNumPage() { + this.router.navigate(['wallets', 'buy-num']); + } + async copyToClipboard(value: string) { await Clipboard.write({ string: value }); this.snackBar.open( this.translocoService.translate('message.copiedToClipboard') ); } - - exportIntegrityWalletPrivateKey() { - this.privateKey$ - .pipe( - first(), - concatMap(async privateKey => { - const result = await this.confirmAlert.present({ - message: this.translocoService.translate( - 'message.confirmCopyPrivateKey' - ), - }); - if (result) - this.dialog.open( - ExportPrivateKeyModalComponent, - { - data: { privateKey }, - } - ); - }), - untilDestroyed(this) - ) - .subscribe(); - } }