remove blob from file data

This commit is contained in:
Dan Percic 2022-02-03 14:11:04 +02:00
parent dc4d18433f
commit f5c613974b
5 changed files with 49 additions and 41 deletions

View File

@ -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<boolean>(false);
readonly blob$ = new BehaviorSubject<Blob>(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));

View File

@ -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 });

View File

@ -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));
}

View File

@ -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<FileDataModel>;
readonly file$: Observable<File>;
readonly blob$: Observable<Blob>;
readonly dossier$: Observable<Dossier>;
readonly isReadonly$: Observable<boolean>;
readonly isWritable$: Observable<boolean>;
readonly fileData$: Observable<FileDataModel>;
readonly dossierId: string;
readonly dossierTemplateId: string;
readonly fileId: string;
readonly #fileData$ = new BehaviorSubject<FileDataModel>(undefined);
readonly #blob$ = new BehaviorSubject<Blob | undefined>(undefined);
readonly #fileData$ = new BehaviorSubject<FileDataModel | undefined>(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<Dossier> {
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<Blob> {
return this._fileManagementService.downloadOriginalFile(file.dossierId, file.fileId, 'body', true, file.cacheIdentifier);
}
}

View File

@ -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<FileDataModel> {
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<Blob> {
return this._fileManagementService.downloadOriginalFile(file.dossierId, file.fileId, 'body', true, file.cacheIdentifier);
}
}