diff --git a/src/app/features/home/post-capture-tab/post-capture-details/post-capture-details.page.html b/src/app/features/home/post-capture-tab/post-capture-details/post-capture-details.page.html index d481a49e5..aad440972 100644 --- a/src/app/features/home/post-capture-tab/post-capture-details/post-capture-details.page.html +++ b/src/app/features/home/post-capture-tab/post-capture-details/post-capture-details.page.html @@ -10,8 +10,9 @@ person diff --git a/src/app/features/home/post-capture-tab/post-capture-details/post-capture-details.page.ts b/src/app/features/home/post-capture-tab/post-capture-details/post-capture-details.page.ts index 54ad840ac..81389a7d1 100644 --- a/src/app/features/home/post-capture-tab/post-capture-details/post-capture-details.page.ts +++ b/src/app/features/home/post-capture-tab/post-capture-details/post-capture-details.page.ts @@ -5,7 +5,7 @@ import { ActionSheetController } from '@ionic/angular'; import { TranslocoService } from '@ngneat/transloco'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { zip } from 'rxjs'; -import { map, shareReplay, switchMap } from 'rxjs/operators'; +import { first, map, shareReplay, switchMap } from 'rxjs/operators'; import { DiaBackendAsset, DiaBackendAssetRepository, @@ -27,7 +27,16 @@ export class PostCaptureDetailsPage { readonly diaBackendAsset$ = this.route.paramMap.pipe( map(params => params.get('id')), isNonNullable(), - switchMap(id => this.diaBackendAssetRepository.fetchById$(id)), + switchMap(id => this.diaBackendAssetRepository.getPostCaptureById$(id)), + shareReplay({ bufferSize: 1, refCount: true }) + ); + + readonly imageSrc$ = this.diaBackendAsset$.pipe( + switchMap(asset => + this.diaBackendAssetRepository.getAndCachePostCaptureImage$(asset) + ), + first(), + map(blob => URL.createObjectURL(blob)), shareReplay({ bufferSize: 1, refCount: true }) ); diff --git a/src/app/features/home/post-capture-tab/post-capture-tab.component.ts b/src/app/features/home/post-capture-tab/post-capture-tab.component.ts index a2e6206ab..ac54585db 100644 --- a/src/app/features/home/post-capture-tab/post-capture-tab.component.ts +++ b/src/app/features/home/post-capture-tab/post-capture-tab.component.ts @@ -21,7 +21,7 @@ export class PostCaptureTabComponent { switchMap(isConnected => iif( () => isConnected, - this.diaBackendAssetRepository.getPostCaptures$().pipe( + this.diaBackendAssetRepository.postCaptures$.pipe( pluck('results'), map(assets => assets.filter(a => a.source_transaction)) ) diff --git a/src/app/shared/services/dia-backend/asset/dia-backend-asset-repository.service.ts b/src/app/shared/services/dia-backend/asset/dia-backend-asset-repository.service.ts index 7c63a1e7f..7abc1529e 100644 --- a/src/app/shared/services/dia-backend/asset/dia-backend-asset-repository.service.ts +++ b/src/app/shared/services/dia-backend/asset/dia-backend-asset-repository.service.ts @@ -5,16 +5,31 @@ import { HttpParams, } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { defer, forkJoin, iif, of, Subject, throwError } from 'rxjs'; +import { + BehaviorSubject, + defer, + forkJoin, + iif, + merge, + of, + ReplaySubject, + Subject, + throwError, +} from 'rxjs'; import { catchError, concatMap, + distinctUntilChanged, first, + map, pluck, repeatWhen, + switchMap, + tap, } from 'rxjs/operators'; import { base64ToBlob } from '../../../../utils/encoding/encoding'; import { toExtension } from '../../../../utils/mime-type'; +import { isNonNullable } from '../../../../utils/rx-operators/rx-operators'; import { Tuple } from '../../database/table/table'; import { getOldProof, @@ -33,6 +48,14 @@ import { BASE_URL } from '../secret'; providedIn: 'root', }) export class DiaBackendAssetRepository { + private readonly postCapturesCache$ = new ReplaySubject< + PaginatedResponse + >(1); + + private readonly postCapturesImageCache$ = new BehaviorSubject( + new Map() + ); + readonly fetchCapturesCount$ = this.list$({ limit: 1, isOriginalOwner: true, @@ -48,6 +71,24 @@ export class DiaBackendAssetRepository { private readonly postCapturesUpdated$ = new Subject<{ reason?: string }>(); + readonly postCaptures$ = merge( + this.postCapturesCache$, + this.postCapturesCount$.pipe( + first(), + concatMap(count => + this.list$({ + isOriginalOwner: false, + orderBy: 'source_transaction', + limit: count, + }) + ), + tap(response => this.postCapturesCache$.next(response)) + ) + ).pipe( + distinctUntilChanged(), + repeatWhen(() => this.postCapturesUpdated$) + ); + constructor( private readonly httpClient: HttpClient, private readonly authService: DiaBackendAuthService @@ -73,26 +114,34 @@ export class DiaBackendAssetRepository { return this.list$({ offset, limit, isOriginalOwner: true }); } - getPostCaptures$(options?: { limit?: number; offset?: number }) { - return iif( - () => options?.limit !== undefined, - this.list$({ - isOriginalOwner: false, - orderBy: 'source_transaction', - limit: options?.limit, - offset: options?.offset, - }), - this.postCapturesCount$.pipe( - first(), - concatMap(count => - this.list$({ - isOriginalOwner: false, - orderBy: 'source_transaction', - limit: count, - }) + getPostCaptureById$(id: string) { + return merge( + this.postCapturesCache$.pipe( + map(postCaptures => postCaptures.results.find(p => p.id === id)), + isNonNullable() + ), + this.fetchById$(id) + ); + } + + getAndCachePostCaptureImage$(postCapture: DiaBackendAsset) { + return this.postCapturesImageCache$.pipe( + map(cache => cache.get(postCapture.id)), + switchMap(image => + iif( + () => !!image, + of(image).pipe(isNonNullable()), + this.downloadFile$({ id: postCapture.id, field: 'asset_file' }).pipe( + first(), + tap(blob => { + const currentCache = this.postCapturesImageCache$.value; + currentCache.set(postCapture.id, blob); + this.postCapturesImageCache$.next(currentCache); + }) + ) ) ) - ).pipe(repeatWhen(() => this.postCapturesUpdated$)); + ); } private list$({ diff --git a/src/app/shared/services/migration/migration.service.ts b/src/app/shared/services/migration/migration.service.ts index c538712fc..8be7d4132 100644 --- a/src/app/shared/services/migration/migration.service.ts +++ b/src/app/shared/services/migration/migration.service.ts @@ -143,8 +143,7 @@ export class MigrationService { } private async fetchAllPostCaptures() { - return this.diaBackendAssetRepository - .getPostCaptures$() + return this.diaBackendAssetRepository.postCaptures$ .pipe(first(), pluck('results')) .toPromise(); }