Skip to content

Commit 953baf2

Browse files
authored
Merge pull request #3398 from numbersprotocol/copilot/improve-performance-error-handling
Performance and error-handling improvements across shared services
2 parents 0c024d4 + eae9acc commit 953baf2

11 files changed

Lines changed: 198 additions & 33 deletions

File tree

src/app/features/home/capture-tab/capture-tab.component.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2+
import { of } from 'rxjs';
3+
import { DiaBackendAuthService } from '../../../shared/dia-backend/auth/dia-backend-auth.service';
4+
import { DiaBackendTransactionRepository } from '../../../shared/dia-backend/transaction/dia-backend-transaction-repository.service';
25
import { SharedTestingModule } from '../../../shared/shared-testing.module';
36
import { CaptureTabComponent } from './capture-tab.component';
47
import { UploadingBarComponent } from './uploading-bar/uploading-bar.component';
@@ -7,10 +10,35 @@ describe('CaptureTabComponent', () => {
710
let component: CaptureTabComponent;
811
let fixture: ComponentFixture<CaptureTabComponent>;
912

13+
const diaBackendAuthServiceStub = {
14+
username$: of(''),
15+
email$: of(''),
16+
profileName$: of(''),
17+
profile$: of({
18+
description: '',
19+
profile_background_thumbnail: '',
20+
}),
21+
syncUser$: jasmine.createSpy().and.returnValue(of(void 0)),
22+
};
23+
24+
const diaBackendTransactionRepositoryStub = {
25+
inbox$: of({ count: 0 }),
26+
};
27+
1028
beforeEach(waitForAsync(() => {
1129
TestBed.configureTestingModule({
1230
declarations: [CaptureTabComponent, UploadingBarComponent],
1331
imports: [SharedTestingModule],
32+
providers: [
33+
{
34+
provide: DiaBackendAuthService,
35+
useValue: diaBackendAuthServiceStub,
36+
},
37+
{
38+
provide: DiaBackendTransactionRepository,
39+
useValue: diaBackendTransactionRepositoryStub,
40+
},
41+
],
1442
}).compileComponents();
1543

1644
fixture = TestBed.createComponent(CaptureTabComponent);

src/app/features/home/capture-tab/capture-tab.component.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { formatDate, KeyValue } from '@angular/common';
2-
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
2+
import {
3+
ChangeDetectionStrategy,
4+
ChangeDetectorRef,
5+
Component,
6+
OnInit,
7+
} from '@angular/core';
38
import { MatDialog } from '@angular/material/dialog';
49
import { Router } from '@angular/router';
510
import { Browser } from '@capacitor/browser';
@@ -48,6 +53,7 @@ import { PrefetchingDialogComponent } from '../onboarding/prefetching-dialog/pre
4853
selector: 'app-capture-tab',
4954
templateUrl: './capture-tab.component.html',
5055
styleUrls: ['./capture-tab.component.scss'],
56+
changeDetection: ChangeDetectionStrategy.OnPush,
5157
})
5258
export class CaptureTabComponent implements OnInit {
5359
/**
@@ -174,7 +180,10 @@ export class CaptureTabComponent implements OnInit {
174180
private initSegmentListener() {
175181
this.captureTabService.segment$
176182
.pipe(
177-
tap(segment => (this.segment = segment)),
183+
tap(segment => {
184+
this.segment = segment;
185+
this.changeDetectorRef.markForCheck();
186+
}),
178187
untilDestroyed(this)
179188
)
180189
.subscribe();

src/app/features/home/collection-tab/collection-tab/collection-tab.component.spec.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,37 @@
11
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2+
import { BehaviorSubject, of } from 'rxjs';
3+
import { DiaBackendAuthService } from '../../../../shared/dia-backend/auth/dia-backend-auth.service';
4+
import { IframeService } from '../../../../shared/iframe/iframe.service';
25
import { SharedTestingModule } from '../../../../shared/shared-testing.module';
3-
46
import { CollectionTabComponent } from './collection-tab.component';
57

68
describe('CollectionTabComponent', () => {
79
let component: CollectionTabComponent;
810
let fixture: ComponentFixture<CollectionTabComponent>;
911

12+
const diaBackendAuthServiceStub = {
13+
cachedQueryJWTToken$: of({ access: 'token', refresh: 'refresh' }),
14+
};
15+
16+
const iframeServiceStub = {
17+
collectionTabRefreshRequested$: new BehaviorSubject(undefined),
18+
collectionTabIframeNavigateBack$: of(void 0),
19+
};
20+
1021
beforeEach(waitForAsync(() => {
1122
TestBed.configureTestingModule({
1223
declarations: [CollectionTabComponent],
1324
imports: [SharedTestingModule],
25+
providers: [
26+
{
27+
provide: DiaBackendAuthService,
28+
useValue: diaBackendAuthServiceStub,
29+
},
30+
{
31+
provide: IframeService,
32+
useValue: iframeServiceStub,
33+
},
34+
],
1435
}).compileComponents();
1536

1637
fixture = TestBed.createComponent(CollectionTabComponent);

src/app/features/home/home.page.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
22
import { Router } from '@angular/router';
3+
import { of } from 'rxjs';
4+
import { DiaBackendAuthService } from '../../shared/dia-backend/auth/dia-backend-auth.service';
35
import { SharedTestingModule } from '../../shared/shared-testing.module';
46
import { CaptureTabComponent } from './capture-tab/capture-tab.component';
57
import { UploadingBarComponent } from './capture-tab/uploading-bar/uploading-bar.component';
@@ -10,6 +12,17 @@ describe('HomePage', () => {
1012
let component: HomePage;
1113
let fixture: ComponentFixture<HomePage>;
1214

15+
const diaBackendAuthServiceStub = {
16+
username$: of(''),
17+
email$: of(''),
18+
profileName$: of(''),
19+
profile$: of({
20+
description: '',
21+
profile_background_thumbnail: '',
22+
}),
23+
syncUser$: jasmine.createSpy().and.returnValue(of(void 0)),
24+
};
25+
1326
beforeEach(waitForAsync(() => {
1427
TestBed.configureTestingModule({
1528
declarations: [
@@ -19,6 +32,12 @@ describe('HomePage', () => {
1932
UploadingBarComponent,
2033
],
2134
imports: [SharedTestingModule],
35+
providers: [
36+
{
37+
provide: DiaBackendAuthService,
38+
useValue: diaBackendAuthServiceStub,
39+
},
40+
],
2241
}).compileComponents();
2342

2443
const router = TestBed.inject(Router);

src/app/features/invitation/invitation.page.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
11
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
22
import { IonicModule } from '@ionic/angular';
3+
import { of } from 'rxjs';
4+
import { DiaBackendAuthService } from '../../shared/dia-backend/auth/dia-backend-auth.service';
5+
import { ShareService } from '../../shared/share/share.service';
36
import { SharedTestingModule } from '../../shared/shared-testing.module';
47
import { InvitationPage } from './invitation.page';
58

69
describe('InvitationPage', () => {
710
let component: InvitationPage;
811
let fixture: ComponentFixture<InvitationPage>;
912

13+
const diaBackendAuthServiceStub = {
14+
referralCode$: of(''),
15+
getReferralCode: jasmine.createSpy().and.resolveTo(''),
16+
syncUser$: jasmine.createSpy().and.returnValue(of(void 0)),
17+
};
18+
19+
const shareServiceStub = {
20+
shareReferralCode: jasmine.createSpy(),
21+
};
22+
1023
beforeEach(waitForAsync(() => {
1124
TestBed.configureTestingModule({
1225
declarations: [InvitationPage],
1326
imports: [IonicModule.forRoot(), SharedTestingModule],
27+
providers: [
28+
{
29+
provide: DiaBackendAuthService,
30+
useValue: diaBackendAuthServiceStub,
31+
},
32+
{
33+
provide: ShareService,
34+
useValue: shareServiceStub,
35+
},
36+
],
1437
}).compileComponents();
1538

1639
fixture = TestBed.createComponent(InvitationPage);

src/app/features/settings/settings.page.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,38 @@
11
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2+
import { of } from 'rxjs';
3+
import { CaptureAppWebCryptoApiSignatureProvider } from '../../shared/collector/signature/capture-app-web-crypto-api-signature-provider/capture-app-web-crypto-api-signature-provider.service';
4+
import { DiaBackendAuthService } from '../../shared/dia-backend/auth/dia-backend-auth.service';
25
import { SharedTestingModule } from '../../shared/shared-testing.module';
36
import { SettingsPage } from './settings.page';
47

58
describe('SettingsPage', () => {
69
let component: SettingsPage;
710
let fixture: ComponentFixture<SettingsPage>;
811

12+
const diaBackendAuthServiceStub = {
13+
email$: of('tester@example.com'),
14+
emailVerified$: of(false),
15+
syncUser$: jasmine.createSpy().and.returnValue(of(void 0)),
16+
};
17+
18+
const signatureProviderStub = {
19+
privateKey$: of('private-key-for-test'),
20+
};
21+
922
beforeEach(waitForAsync(() => {
1023
TestBed.configureTestingModule({
1124
declarations: [SettingsPage],
1225
imports: [SharedTestingModule],
26+
providers: [
27+
{
28+
provide: DiaBackendAuthService,
29+
useValue: diaBackendAuthServiceStub,
30+
},
31+
{
32+
provide: CaptureAppWebCryptoApiSignatureProvider,
33+
useValue: signatureProviderStub,
34+
},
35+
],
1336
}).compileComponents();
1437

1538
fixture = TestBed.createComponent(SettingsPage);

src/app/features/wallets/wallets.page.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,49 @@
11
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
22
import { IonicModule } from '@ionic/angular';
3+
import { BehaviorSubject, of } from 'rxjs';
4+
import { CaptureAppWebCryptoApiSignatureProvider } from '../../shared/collector/signature/capture-app-web-crypto-api-signature-provider/capture-app-web-crypto-api-signature-provider.service';
5+
import { DiaBackendAuthService } from '../../shared/dia-backend/auth/dia-backend-auth.service';
6+
import { DiaBackendWalletService } from '../../shared/dia-backend/wallet/dia-backend-wallet.service';
37
import { SharedTestingModule } from '../../shared/shared-testing.module';
48
import { WalletsPage } from './wallets.page';
59

610
describe('WalletsPage', () => {
711
let component: WalletsPage;
812
let fixture: ComponentFixture<WalletsPage>;
913

14+
const diaBackendAuthServiceStub = {
15+
cachedQueryJWTToken$: of({ access: 'token', refresh: 'refresh' }),
16+
};
17+
18+
const diaBackendWalletServiceStub = {
19+
assetWalletAddr$: of('asset-wallet-address'),
20+
networkConnected$: of(true),
21+
reloadWallet$: new BehaviorSubject(false),
22+
};
23+
24+
const signatureProviderStub = {
25+
publicKey$: of('public-key'),
26+
privateKey$: of('private-key'),
27+
};
28+
1029
beforeEach(waitForAsync(() => {
1130
TestBed.configureTestingModule({
1231
declarations: [WalletsPage],
1332
imports: [IonicModule.forRoot(), SharedTestingModule],
33+
providers: [
34+
{
35+
provide: DiaBackendAuthService,
36+
useValue: diaBackendAuthServiceStub,
37+
},
38+
{
39+
provide: DiaBackendWalletService,
40+
useValue: diaBackendWalletServiceStub,
41+
},
42+
{
43+
provide: CaptureAppWebCryptoApiSignatureProvider,
44+
useValue: signatureProviderStub,
45+
},
46+
],
1447
}).compileComponents();
1548

1649
fixture = TestBed.createComponent(WalletsPage);

src/app/shared/dia-backend/auth/dia-backend-auth.service.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
22
import { Injectable } from '@angular/core';
33
import { Device } from '@capacitor/device';
44
import { Preferences } from '@capacitor/preferences';
5-
import { isEqual, reject } from 'lodash-es';
5+
import { isEqual } from 'lodash-es';
66
import {
77
Observable,
88
ReplaySubject,
@@ -435,15 +435,9 @@ export class DiaBackendAuthService {
435435
}
436436

437437
private async getToken() {
438-
return new Promise<string>(resolve => {
439-
this.preferences.getString(PrefKeys.TOKEN).then(token => {
440-
if (token.length !== 0) {
441-
resolve(token);
442-
} else {
443-
reject(new Error('Cannot get DIA backend token which is empty.'));
444-
}
445-
});
446-
});
438+
const token = await this.preferences.getString(PrefKeys.TOKEN);
439+
if (!token) throw new Error('Cannot get DIA backend token which is empty.');
440+
return token;
447441
}
448442

449443
private async setToken(value: string) {

src/app/shared/media/media-store/media-store.service.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,14 @@ export class MediaStore {
100100

101101
private async _write(index: string, base64: string, mimeType: MimeType) {
102102
await this.initialize();
103+
// Perform expensive blob conversion before acquiring the lock so concurrent
104+
// reads are not blocked during the conversion of large files.
105+
const blob = Capacitor.isNativePlatform()
106+
? await base64ToBlob(base64, mimeType)
107+
: undefined;
103108
return this.mutex.runExclusive(async () => {
104109
const mediaExtension = await this.setMediaExtension(index, mimeType);
105-
if (Capacitor.isNativePlatform()) {
106-
const blob = await base64ToBlob(base64, mimeType);
110+
if (blob !== undefined) {
107111
await write_blob({
108112
directory: this.directory,
109113
path: `${this.rootDir}/${index}.${mediaExtension.extension}`,

src/app/shared/preference-manager/preferences/capacitor-storage-preferences/capacitor-storage-preferences.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,20 @@ export class CapacitorStoragePreferences {
6464
}
6565

6666
private async initializeValue(key: string, defaultValue: SupportedTypes) {
67-
if (this.subjects.has(key)) {
68-
const subject$ = this.subjects.get(key);
69-
if (subject$?.value === undefined) {
70-
subject$?.next(defaultValue);
67+
return this.mutex.runExclusive(async () => {
68+
if (this.subjects.has(key)) {
69+
const subject$ = this.subjects.get(key);
70+
if (subject$?.value === undefined) {
71+
subject$?.next(defaultValue);
72+
}
73+
return;
7174
}
72-
return;
73-
}
74-
const value = await this.loadValue(key, defaultValue);
75-
this.subjects.set(
76-
key,
77-
new BehaviorSubject<SupportedTypes | undefined>(value)
78-
);
75+
const value = await this.loadValue(key, defaultValue);
76+
this.subjects.set(
77+
key,
78+
new BehaviorSubject<SupportedTypes | undefined>(value)
79+
);
80+
});
7981
}
8082

8183
private async loadValue(key: string, defaultValue: SupportedTypes) {

0 commit comments

Comments
 (0)