Skip to content

Commit 8306805

Browse files
authored
Merge pull request #1174 from numbersprotocol/build/bump-version-to-0.46.0
Build/bump version to 0.46.0
2 parents 5248d4a + 2658e91 commit 8306805

22 files changed

+427
-63
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## 0.46.0
9+
10+
### Added
11+
12+
- Support NUM payment for network applications.
13+
14+
### Changed
15+
16+
- Do not show the private key directly. Users need to agree with the warnings to see and copy their private key.
17+
818
## 0.45.1 - 2022-01-05
919

1020
### Fixed

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ android {
66
applicationId "io.numbersprotocol.capturelite"
77
minSdkVersion rootProject.ext.minSdkVersion
88
targetSdkVersion rootProject.ext.targetSdkVersion
9-
versionCode 281
10-
versionName "0.45.1"
9+
versionCode 290
10+
versionName "0.46.0"
1111
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1212
}
1313
buildTypes {

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "capture-lite",
3-
"version": "0.45.1",
3+
"version": "0.46.0",
44
"author": "numbersprotocol",
55
"homepage": "https://numbersprotocol.io/",
66
"scripts": {

src/app/features/home/details/actions/actions.page.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<div class="page-content">
99
<ng-container *ngFor="let action of actions$ | ngrxPush">
10-
<ion-card (click)="openAction(action)">
10+
<ion-card (click)="doAction(action)">
1111
<ion-card-header>
1212
<div class="wrapper">
1313
<div>
Lines changed: 96 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import { HttpErrorResponse } from '@angular/common/http';
12
import { Component } from '@angular/core';
23
import { MatDialog } from '@angular/material/dialog';
34
import { MatSnackBar } from '@angular/material/snack-bar';
45
import { ActivatedRoute } from '@angular/router';
56
import { TranslocoService } from '@ngneat/transloco';
67
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
7-
import { combineLatest } from 'rxjs';
8+
import { combineLatest, of } from 'rxjs';
89
import { catchError, concatMap, first, map, tap } from 'rxjs/operators';
910
import { ActionsDialogComponent } from '../../../../shared/actions/actions-dialog/actions-dialog.component';
1011
import {
@@ -13,7 +14,12 @@ import {
1314
} from '../../../../shared/actions/service/actions.service';
1415
import { BlockingActionService } from '../../../../shared/blocking-action/blocking-action.service';
1516
import { DiaBackendAuthService } from '../../../../shared/dia-backend/auth/dia-backend-auth.service';
17+
import {
18+
DiaBackendStoreService,
19+
NetworkAppOrderStatus,
20+
} from '../../../../shared/dia-backend/store/dia-backend-store.service';
1621
import { ErrorService } from '../../../../shared/error/error.service';
22+
import { OrderDetailDialogComponent } from '../../../../shared/order-detail-dialog/order-detail-dialog.component';
1723
import { isNonNullable } from '../../../../utils/rx-operators/rx-operators';
1824

1925
@UntilDestroy()
@@ -39,54 +45,108 @@ export class ActionsPage {
3945
private readonly route: ActivatedRoute,
4046
private readonly authService: DiaBackendAuthService,
4147
private readonly snackBar: MatSnackBar,
42-
private readonly dialog: MatDialog
48+
private readonly dialog: MatDialog,
49+
private readonly storeService: DiaBackendStoreService
4350
) {}
4451

45-
openAction(action: Action) {
52+
openActionDialog$(action: Action) {
4653
return combineLatest([
4754
this.actionsService.getParams$(action.params_list_custom_param1),
4855
this.authService.token$,
4956
this.id$,
50-
])
57+
]).pipe(
58+
first(),
59+
concatMap(([params, token, id]) => {
60+
const dialogRef = this.dialog.open<ActionsDialogComponent>(
61+
ActionsDialogComponent,
62+
{
63+
disableClose: true,
64+
data: {
65+
action: action,
66+
params: params,
67+
},
68+
}
69+
);
70+
return dialogRef.afterClosed().pipe(
71+
isNonNullable(),
72+
concatMap(data =>
73+
of({
74+
networkApp: action.network_app_id_text,
75+
actionArgs: { ...data, token: token, cid: id },
76+
} as CreateOrderInput)
77+
)
78+
);
79+
})
80+
);
81+
}
82+
83+
openOrderDialog$(orderStatus: NetworkAppOrderStatus) {
84+
const dialogRef = this.dialog.open<OrderDetailDialogComponent>(
85+
OrderDetailDialogComponent,
86+
{
87+
disableClose: true,
88+
data: orderStatus,
89+
width: '80%',
90+
}
91+
);
92+
return dialogRef.afterClosed().pipe(
93+
isNonNullable(),
94+
concatMap((orderId: string) => of(orderId))
95+
);
96+
}
97+
98+
createOrder$(appName: string, actionArgs: any) {
99+
return this.storeService.createNetworkAppOrder(appName, actionArgs).pipe(
100+
catchError((err: unknown) => {
101+
return this.errorService.toastError$(err);
102+
}),
103+
isNonNullable()
104+
);
105+
}
106+
107+
confirmOrder$(id: string) {
108+
return this.storeService.confirmNetworkAppOrder(id).pipe(
109+
catchError((err: unknown) => {
110+
if (err instanceof HttpErrorResponse) {
111+
const errorType = err.error.error?.type;
112+
if (errorType === 'insufficient_fund')
113+
return this.errorService.toastError$(
114+
this.translocoService.translate(`error.diaBackend.${errorType}`)
115+
);
116+
}
117+
return this.errorService.toastError$(err);
118+
}),
119+
isNonNullable()
120+
);
121+
}
122+
123+
doAction(action: Action) {
124+
this.openActionDialog$(action)
51125
.pipe(
52-
first(),
53-
concatMap(([params, token, id]) => {
54-
const dialogRef = this.dialog.open<ActionsDialogComponent>(
55-
ActionsDialogComponent,
56-
{
57-
disableClose: true,
58-
data: {
59-
action: action,
60-
params: params,
61-
},
62-
}
63-
);
64-
return dialogRef.afterClosed().pipe(
65-
isNonNullable(),
66-
tap(data =>
67-
this.sendAction(action, { ...data, token: token, cid: id })
126+
concatMap(createOrderInput =>
127+
this.blockingActionService.run$(
128+
this.createOrder$(
129+
createOrderInput.networkApp,
130+
createOrderInput.actionArgs
68131
)
132+
)
133+
),
134+
concatMap(orderStatus => this.openOrderDialog$(orderStatus)),
135+
concatMap(orderId =>
136+
this.blockingActionService.run$(this.confirmOrder$(orderId))
137+
),
138+
tap(() => {
139+
this.snackBar.open(
140+
this.translocoService.translate('message.sentSuccessfully')
69141
);
70142
}),
71143
untilDestroyed(this)
72144
)
73145
.subscribe();
74146
}
147+
}
75148

76-
sendAction(action: Action, body: any) {
77-
const action$ = this.actionsService.send$(action.base_url_text, body).pipe(
78-
catchError((err: unknown) => {
79-
return this.errorService.toastError$(err);
80-
}),
81-
tap(() =>
82-
this.snackBar.open(
83-
this.translocoService.translate('message.sentSuccessfully')
84-
)
85-
)
86-
);
87-
this.blockingActionService
88-
.run$(action$)
89-
.pipe(untilDestroyed(this))
90-
.subscribe();
91-
}
149+
interface CreateOrderInput {
150+
networkApp: string;
151+
actionArgs: any;
92152
}

src/app/features/profile/profile.page.html

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,15 @@
118118
<mat-icon>content_copy</mat-icon>
119119
</button>
120120
</mat-list-item>
121-
<mat-list-item>
122-
<mat-icon mat-list-icon>vpn_key</mat-icon>
123-
<div mat-line>{{ t('privateKey') }}</div>
124-
<div mat-line>{{ privateKey$ | ngrxPush }}</div>
125-
<button
126-
*ngIf="privateKey$ | ngrxPush as privateKey"
127-
(click)="copyPrivateKey(privateKey)"
128-
mat-icon-button
129-
>
130-
<mat-icon>content_copy</mat-icon>
131-
</button>
132-
</mat-list-item>
133121
</mat-list>
122+
<button
123+
(click)="exportPrivateKey()"
124+
class="expand"
125+
color="primary"
126+
mat-stroked-button
127+
>
128+
{{ t('exportPrivateKey') }}
129+
</button>
134130
<button (click)="logout()" class="expand" color="primary" mat-stroked-button>
135131
{{ t('logout') }}
136132
</button>

src/app/features/profile/profile.page.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import { Component } from '@angular/core';
2+
import { MatDialog } from '@angular/material/dialog';
23
import { MatSnackBar } from '@angular/material/snack-bar';
34
import { ActivatedRoute, Router } from '@angular/router';
45
import { Plugins } from '@capacitor/core';
56
import { AlertController } from '@ionic/angular';
67
import { TranslocoService } from '@ngneat/transloco';
78
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
89
import { defer, forkJoin, iif } from 'rxjs';
9-
import { catchError, concatMap, concatMapTo } from 'rxjs/operators';
10+
import { catchError, concatMap, concatMapTo, first } from 'rxjs/operators';
1011
import { BlockingActionService } from '../../shared/blocking-action/blocking-action.service';
1112
import { WebCryptoApiSignatureProvider } from '../../shared/collector/signature/web-crypto-api-signature-provider/web-crypto-api-signature-provider.service';
1213
import { ConfirmAlert } from '../../shared/confirm-alert/confirm-alert.service';
1314
import { Database } from '../../shared/database/database.service';
1415
import { DiaBackendAuthService } from '../../shared/dia-backend/auth/dia-backend-auth.service';
1516
import { DiaBackendWalletService } from '../../shared/dia-backend/wallet/dia-backend-wallet.service';
1617
import { ErrorService } from '../../shared/error/error.service';
18+
import { ExportPrivateKeyModalComponent } from '../../shared/export-private-key-modal/export-private-key-modal.component';
1719
import { MediaStore } from '../../shared/media/media-store/media-store.service';
1820
import { PreferenceManager } from '../../shared/preference-manager/preference-manager.service';
1921

@@ -50,7 +52,8 @@ export class ProfilePage {
5052
private readonly alertController: AlertController,
5153
private readonly router: Router,
5254
private readonly route: ActivatedRoute,
53-
private readonly diaBackendWalletService: DiaBackendWalletService
55+
private readonly diaBackendWalletService: DiaBackendWalletService,
56+
private readonly dialog: MatDialog
5457
) {}
5558

5659
ionViewWillEnter() {
@@ -115,11 +118,27 @@ export class ProfilePage {
115118
);
116119
}
117120

118-
async copyPrivateKey(privateKey: string) {
119-
const result = await this.confirmAlert.present({
120-
message: this.translocoService.translate('message.confirmCopyPrivateKey'),
121-
});
122-
if (result) await this.copyToClipboard(privateKey);
121+
exportPrivateKey() {
122+
this.privateKey$
123+
.pipe(
124+
first(),
125+
concatMap(async privateKey => {
126+
const result = await this.confirmAlert.present({
127+
message: this.translocoService.translate(
128+
'message.confirmCopyPrivateKey'
129+
),
130+
});
131+
if (result)
132+
this.dialog.open<ExportPrivateKeyModalComponent>(
133+
ExportPrivateKeyModalComponent,
134+
{
135+
data: { privateKey },
136+
}
137+
);
138+
}),
139+
untilDestroyed(this)
140+
)
141+
.subscribe();
123142
}
124143

125144
logout() {

src/app/shared/actions/service/actions.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export interface Action {
4242
readonly description_text: string;
4343
readonly params_list_custom_param1: string[];
4444
readonly title_text: string;
45+
readonly network_app_id_text: string;
4546
}
4647

4748
export interface Param {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { TestBed } from '@angular/core/testing';
2+
import { SharedTestingModule } from '../../shared-testing.module';
3+
import { DiaBackendStoreService } from './dia-backend-store.service';
4+
5+
describe('DiaBackendStoreService', () => {
6+
let service: DiaBackendStoreService;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({
10+
imports: [SharedTestingModule],
11+
});
12+
service = TestBed.inject(DiaBackendStoreService);
13+
});
14+
15+
it('should be created', () => {
16+
expect(service).toBeTruthy();
17+
});
18+
});

0 commit comments

Comments
 (0)