From f5c613974be87956da30f7eb1a9e6acf0583eb0d Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 3 Feb 2022 14:11:04 +0200 Subject: [PATCH] remove blob from file data --- .../src/app/models/file/file-data.model.ts | 7 +--- .../pdf-viewer/pdf-viewer.component.ts | 14 +++---- .../file-preview-screen.component.ts | 1 + .../services/file-preview-state.service.ts | 42 ++++++++++++++++--- .../services/pdf-viewer-data.service.ts | 26 +++--------- 5 files changed, 49 insertions(+), 41 deletions(-) diff --git a/apps/red-ui/src/app/models/file/file-data.model.ts b/apps/red-ui/src/app/models/file/file-data.model.ts index 7b73d7228..36b1a7870 100644 --- a/apps/red-ui/src/app/models/file/file-data.model.ts +++ b/apps/red-ui/src/app/models/file/file-data.model.ts @@ -16,19 +16,16 @@ import { RedactionLogEntry } from './redaction-log.entry'; export class FileDataModel { static readonly DELTA_VIEW_TIME = 10 * 60 * 1000; // 10 minutes; - allAnnotations: AnnotationWrapper[]; + allAnnotations: AnnotationWrapper[] = []; readonly hasChangeLog$ = new BehaviorSubject(false); - readonly blob$ = new BehaviorSubject(undefined); constructor( private readonly _file: File, - private readonly _blob: Blob, private _redactionLog: IRedactionLog, public viewedPages?: IViewedPage[], private _dictionaryData?: { [p: string]: Dictionary }, private _areDevFeaturesEnabled?: boolean, ) { - this.blob$.next(_blob); this._buildAllAnnotations(); } @@ -56,7 +53,7 @@ export class FileDataModel { private _buildAllAnnotations() { const entries: RedactionLogEntry[] = this._convertData(); - const previousAnnotations = this.allAnnotations || []; + const previousAnnotations = [...this.allAnnotations]; this.allAnnotations = entries .map(entry => AnnotationWrapper.fromData(entry)) .filter(ann => ann.manual || !this._file.excludedPages.includes(ann.pageNumber)); diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/pdf-viewer/pdf-viewer.component.ts index b9f9e816b..c95791eb1 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/pdf-viewer/pdf-viewer.component.ts @@ -27,7 +27,7 @@ import { AnnotationActionsService } from '../../services/annotation-actions.serv import { UserPreferenceService } from '@services/user-preference.service'; import { BASE_HREF } from '../../../../../../tokens'; import { ConfigService } from '@services/config.service'; -import { AutoUnsubscribe, ConfirmationDialogInput, LoadingService, shareDistinctLast } from '@iqser/common-ui'; +import { AutoUnsubscribe, ConfirmationDialogInput, LoadingService } from '@iqser/common-ui'; import { DossiersDialogService } from '../../../../services/dossiers-dialog.service'; import { loadCompareDocumentWrapper } from '../../../../utils/compare-mode.utils'; import { PdfViewerUtils } from '../../../../utils/pdf-viewer.utils'; @@ -37,7 +37,7 @@ import { toPosition } from '../../../../utils/pdf-calculation.utils'; import { ViewModeService } from '../../services/view-mode.service'; import { MultiSelectService } from '../../services/multi-select.service'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; -import { filter, switchMap, tap, withLatestFrom } from 'rxjs/operators'; +import { tap, withLatestFrom } from 'rxjs/operators'; import Tools = Core.Tools; import TextTool = Tools.TextTool; import Annotation = Core.Annotations.Annotation; @@ -120,12 +120,8 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha this._setReadyAndInitialState = this._setReadyAndInitialState.bind(this); await this._loadViewer(); - this.addActiveScreenSubscription = this.stateService.fileData$ + this.addActiveScreenSubscription = this.stateService.blob$ .pipe( - filter(fileData => !!fileData), - switchMap(fileData => fileData.blob$), - // Skip document reload if file content hasn't changed - shareDistinctLast(), withLatestFrom(this.stateService.file$), tap(([blob, file]) => this._loadDocument(blob, file)), ) @@ -158,7 +154,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha await pdfNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null); const compareDocument = await pdfNet.PDFDoc.createFromBuffer(fileReader.result as ArrayBuffer); - const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this.stateService.fileData.blob$.value.arrayBuffer()); + const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this.stateService.blob.arrayBuffer()); const loadCompareDocument = async () => { this._loadingService.start(); @@ -212,7 +208,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha this.viewModeService.compareMode = false; const pdfNet = this.instance.Core.PDFNet; await pdfNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null); - const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this.stateService.fileData.blob$.value.arrayBuffer()); + const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this.stateService.blob.arrayBuffer()); const filename = (await this.stateService.file).filename ?? 'document.pdf'; this.instance.UI.loadDocument(currentDocument, { filename }); diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts index 145405297..47343684d 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts @@ -561,6 +561,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni return; } + await this.stateService.loadBlob(file); this.stateService.fileData = await firstValueFrom(this._pdfViewerDataService.loadDataFor(file)); } diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/file-preview-state.service.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/file-preview-state.service.ts index 5ba0e6889..14a3148e0 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/file-preview-state.service.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/file-preview-state.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs'; +import { BehaviorSubject, firstValueFrom, Observable, switchMap } from 'rxjs'; import { FileDataModel } from '@models/file/file-data.model'; import { Dossier, File } from '@red/domain'; import { DossiersService } from '../../../../../services/entity-services/dossiers.service'; @@ -7,33 +7,42 @@ import { ActivatedRoute } from '@angular/router'; import { FilesMapService } from '../../../../../services/entity-services/files-map.service'; import { PermissionsService } from '../../../../../services/permissions.service'; import { boolFactory } from '@iqser/common-ui'; +import { filter, map, tap } from 'rxjs/operators'; +import { FileManagementService } from '../../../../../services/entity-services/file-management.service'; @Injectable() export class FilePreviewStateService { - readonly fileData$: Observable; readonly file$: Observable; + readonly blob$: Observable; readonly dossier$: Observable; readonly isReadonly$: Observable; readonly isWritable$: Observable; + readonly fileData$: Observable; + readonly dossierId: string; readonly dossierTemplateId: string; readonly fileId: string; - readonly #fileData$ = new BehaviorSubject(undefined); + + readonly #blob$ = new BehaviorSubject(undefined); + readonly #fileData$ = new BehaviorSubject(undefined); constructor( dossiersService: DossiersService, filesMapService: FilesMapService, permissionsService: PermissionsService, activatedRoute: ActivatedRoute, + private readonly _fileManagementService: FileManagementService, ) { + this.fileId = activatedRoute.snapshot.paramMap.get('fileId'); this.dossierId = activatedRoute.snapshot.paramMap.get('dossierId'); this.dossierTemplateId = dossiersService.find(this.dossierId).dossierTemplateId; - this.dossier$ = dossiersService.getEntityChanged$(this.dossierId); - this.fileId = activatedRoute.snapshot.paramMap.get('fileId'); - this.fileData$ = this.#fileData$.asObservable(); + this.dossier$ = dossiersService.getEntityChanged$(this.dossierId); this.file$ = filesMapService.watch$(this.dossierId, this.fileId); [this.isReadonly$, this.isWritable$] = boolFactory(this.file$, file => !permissionsService.canPerformAnnotationActions(file)); + + this.fileData$ = this.#fileData$.asObservable().pipe(filter(value => !!value)); + this.blob$ = this.#blob$.asObservable().pipe(filter(value => !!value)); } get fileData(): FileDataModel { @@ -51,4 +60,25 @@ export class FilePreviewStateService { get dossier(): Promise { return firstValueFrom(this.dossier$); } + + get blob(): Blob | undefined { + return this.#blob$.value; + } + + loadBlob(newFile: File) { + const newBlob$ = this.#downloadOriginalFile(newFile).pipe( + tap(blob => this.#blob$.next(blob)), + tap(() => console.log('new')), + ); + const blob$ = this.file$.pipe( + map(file => file.cacheIdentifier === newFile.cacheIdentifier && this.blob), + switchMap(isSame => (isSame ? this.blob$ : newBlob$)), + ); + + return firstValueFrom(blob$); + } + + #downloadOriginalFile(file: File): Observable { + return this._fileManagementService.downloadOriginalFile(file.dossierId, file.fileId, 'body', true, file.cacheIdentifier); + } } diff --git a/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts b/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts index 0a0313f4b..b4430c3df 100644 --- a/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts @@ -1,23 +1,19 @@ import { Injectable } from '@angular/core'; -import { forkJoin, Observable, of, switchMap } from 'rxjs'; -import { catchError, map, take, tap } from 'rxjs/operators'; +import { forkJoin, Observable, of } from 'rxjs'; +import { catchError, map, tap } from 'rxjs/operators'; import { FileDataModel } from '@models/file/file-data.model'; import { PermissionsService } from '@services/permissions.service'; import { File, IRedactionLog, IViewedPage } from '@red/domain'; -import { FileManagementService } from '@services/entity-services/file-management.service'; import { RedactionLogService } from './redaction-log.service'; import { ViewedPagesService } from '@services/entity-services/viewed-pages.service'; import { AppStateService } from '../../../state/app-state.service'; -import { DossiersService } from '../../../services/entity-services/dossiers.service'; import { UserPreferenceService } from '../../../services/user-preference.service'; import { FilePreviewStateService } from '../screens/file-preview-screen/services/file-preview-state.service'; @Injectable() export class PdfViewerDataService { constructor( - private readonly _dossiersService: DossiersService, private readonly _permissionsService: PermissionsService, - private readonly _fileManagementService: FileManagementService, private readonly _redactionLogService: RedactionLogService, private readonly _viewedPagesService: ViewedPagesService, private readonly _appStateService: AppStateService, @@ -33,24 +29,16 @@ export class PdfViewerDataService { } loadDataFor(newFile: File): Observable { - const oldBlob$ = this._stateService.fileData?.blob$; - const blob$ = this._stateService.file$.pipe( - map(file => file.cacheIdentifier === newFile.cacheIdentifier && oldBlob$), - switchMap(isSame => (isSame ? oldBlob$ : this.downloadOriginalFile(newFile))), - take(1), - ); const redactionLog$ = this.loadRedactionLogFor(newFile.dossierId, newFile.fileId); const viewedPages$ = this.getViewedPagesFor(newFile); - const dossier = this._dossiersService.find(newFile.dossierId); - - return forkJoin([blob$, redactionLog$, viewedPages$]).pipe( + return forkJoin([redactionLog$, viewedPages$]).pipe( map( - (data: [blob: Blob, redactionLog: IRedactionLog, viewedPages: IViewedPage[]]) => + (data: [redactionLog: IRedactionLog, viewedPages: IViewedPage[]]) => new FileDataModel( newFile, ...data, - this._appStateService.dictionaryData[dossier.dossierTemplateId], + this._appStateService.dictionaryData[this._stateService.dossierTemplateId], this._userPreferenceService.areDevFeaturesEnabled, ), ), @@ -63,8 +51,4 @@ export class PdfViewerDataService { } return of([]); } - - downloadOriginalFile(file: File): Observable { - return this._fileManagementService.downloadOriginalFile(file.dossierId, file.fileId, 'body', true, file.cacheIdentifier); - } }