RED-3988: fix other compare mode & reload issues

This commit is contained in:
Dan Percic 2022-05-25 15:30:54 +03:00
parent 95efa62f27
commit f7e0fbc9ff
10 changed files with 68 additions and 67 deletions

View File

@ -3,11 +3,9 @@ import {
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
HostListener,
Input,
OnDestroy,
Output,
TemplateRef,
ViewChild,
} from '@angular/core';
@ -60,7 +58,6 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
@Input() dialogRef: MatDialogRef<unknown>;
@Input() file!: File;
@Input() annotationActionsTemplate: TemplateRef<unknown>;
@Output() readonly selectPage = new EventEmitter<number>();
displayedPages: number[] = [];
pagesPanelActive = true;
readonly displayedAnnotations$: Observable<Map<number, AnnotationWrapper[]>>;
@ -275,16 +272,16 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
}
scrollQuickNavFirst(): void {
this.selectPage.emit(1);
this.pdf.navigateTo(1);
}
scrollQuickNavLast(): Promise<void> {
return firstValueFrom(this.state.file$).then(file => this.selectPage.emit(file.numberOfPages));
return firstValueFrom(this.state.file$).then(file => this.pdf.navigateTo(file.numberOfPages));
}
pageSelectedByClick($event: number): void {
this.pagesPanelActive = true;
this.selectPage.emit($event);
this.pdf.navigateTo($event);
}
preventKeyDefault($event: KeyboardEvent): void {
@ -294,11 +291,11 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
}
jumpToPreviousWithAnnotations(): void {
this.selectPage.emit(this._prevPageWithAnnotations());
this.pdf.navigateTo(this._prevPageWithAnnotations());
}
jumpToNextWithAnnotations(): void {
this.selectPage.emit(this._nextPageWithAnnotations());
this.pdf.navigateTo(this._nextPageWithAnnotations());
}
navigateAnnotations($event: KeyboardEvent) {
@ -419,26 +416,26 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
if (pageIdx !== -1) {
// If active page has annotations
if (pageIdx !== this.displayedPages.length - 1) {
this.selectPage.emit(this.displayedPages[pageIdx + 1]);
this.pdf.navigateTo(this.displayedPages[pageIdx + 1]);
}
} else {
// If active page doesn't have annotations
const nextPage = this._nextPageWithAnnotations();
if (nextPage) {
this.selectPage.emit(nextPage);
this.pdf.navigateTo(nextPage);
}
}
} else {
if (pageIdx !== -1) {
// If active page has annotations
if (pageIdx !== 0) {
this.selectPage.emit(this.displayedPages[pageIdx - 1]);
this.pdf.navigateTo(this.displayedPages[pageIdx - 1]);
}
} else {
// If active page doesn't have annotations
const prevPage = this._prevPageWithAnnotations();
if (prevPage) {
this.selectPage.emit(prevPage);
this.pdf.navigateTo(prevPage);
}
}
}

View File

@ -75,7 +75,6 @@
<redaction-document-info *ngIf="documentInfoService.shown$ | async"></redaction-document-info>
<redaction-file-workload
(selectPage)="selectPage($event)"
*ngIf="!file.excluded"
[activeViewerPage]="pdf.currentPage$ | async"
[annotationActionsTemplate]="annotationActionsTemplate"

View File

@ -73,7 +73,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
readonly fileId = this.state.fileId;
readonly dossierId = this.state.dossierId;
readonly file$ = this.state.file$.pipe(tap(file => this._fileDataService.loadAnnotations(file)));
private _lastPage: string;
@ViewChild('annotationFilterTemplate', {
read: TemplateRef,
static: false,
@ -205,9 +204,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
this.#rebuildFilters();
}
async ngOnDetach() {
await this._documentViewer.lock();
this._documentViewer.close();
ngOnDetach() {
this._viewerHeaderService.resetCompareButtons();
super.ngOnDetach();
this._changeDetectorRef.markForCheck();
}
@ -222,7 +220,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
await this.ngOnInit();
await this._fileDataService.loadRedactionLog();
this._viewerHeaderService.updateElements();
this._lastPage = previousRoute.queryParams.page;
await this.#updateQueryParamsPage(Number(previousRoute.queryParams.page ?? '1'));
this._changeDetectorRef.markForCheck();
}
@ -242,12 +240,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
const reanalyzeFiles = reanalysisService.reanalyzeFilesForDossier([file], this.dossierId, { force: true });
await firstValueFrom(reanalyzeFiles);
}
this.pdfProxyService.loadViewer();
}
selectPage(pageNumber: number) {
this.pdf.navigateTo(pageNumber);
this._lastPage = pageNumber.toString();
this.pdfProxyService.loadViewer();
}
openManualAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) {
@ -320,7 +314,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
@Debounce(100)
async viewerReady() {
// Go to initial page from query params
const pageNumber: string = this._lastPage || this._activatedRoute.snapshot.queryParams.page;
const pageNumber: string = this._activatedRoute.snapshot.queryParams.page;
if (pageNumber) {
const file = this.state.file;
let page = parseInt(pageNumber, 10);
@ -332,7 +326,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
page = file.numberOfPages;
}
this.selectPage(page);
this.pdf.navigateTo(page);
}
this._loadingService.stop();
@ -358,20 +352,22 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
loadAnnotations() {
const documentLoaded$ = this._documentViewer.loaded$.pipe(
tap(() => {
tap(loaded => {
if (!loaded) {
return;
}
this._pageRotationService.clearRotations();
this._viewerHeaderService.disable(ROTATION_ACTION_BUTTONS);
return this.viewerReady();
}),
filter(s => s),
tap(() => this.viewerReady()),
);
const currentPageAnnotations$ = combineLatest([this.pdf.currentPage$, this._fileDataService.annotations$]).pipe(
map(([page, annotations]) => annotations.filter(annotation => annotation.pageNumber === page)),
);
let start;
return combineLatest([currentPageAnnotations$, documentLoaded$]).pipe(
filter(([, loaded]) => loaded),
tap(() => (start = new Date().getTime())),
map(([annotations]) => annotations),
startWith([] as AnnotationWrapper[]),
@ -548,7 +544,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
this.openManualAnnotationDialog($event);
});
this.addActiveScreenSubscription = this.pdfProxyService.pageChanged$.subscribe(page => this.viewerPageChanged(page));
this.addActiveScreenSubscription = this.pdfProxyService.pageChanged$.subscribe(page =>
this._ngZone.run(() => this.viewerPageChanged(page)),
);
this.addActiveScreenSubscription = this.pdfProxyService.annotationSelected$.subscribe();
}

View File

@ -38,6 +38,7 @@ import { ManualRedactionService } from './services/manual-redaction.service';
import { AnnotationWrapperComponent } from './components/annotation-wrapper/annotation-wrapper.component';
import { AnnotationReferenceComponent } from './components/annotation-reference/annotation-reference.component';
import { ImportRedactionsDialogComponent } from './dialogs/import-redactions-dialog/import-redactions-dialog';
import { DocumentUnloadedGuard } from './services/document-unloaded.guard';
const routes: Routes = [
{
@ -45,7 +46,7 @@ const routes: Routes = [
component: FilePreviewScreenComponent,
pathMatch: 'full',
data: { reuse: true },
canDeactivate: [PendingChangesGuard],
canDeactivate: [PendingChangesGuard, DocumentUnloadedGuard],
},
];
@ -95,6 +96,6 @@ const components = [
OverlayModule,
ColorPickerModule,
],
providers: [FilePreviewDialogService, ManualRedactionService],
providers: [FilePreviewDialogService, ManualRedactionService, DocumentUnloadedGuard],
})
export class FilePreviewModule {}

View File

@ -0,0 +1,18 @@
import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { filter, map, Observable } from 'rxjs';
import { REDDocumentViewer } from '../../pdf-viewer/services/document-viewer.service';
@Injectable()
export class DocumentUnloadedGuard implements CanDeactivate<unknown> {
constructor(private readonly _documentViewer: REDDocumentViewer) {}
canDeactivate(): Observable<boolean> {
this._documentViewer.close();
return this._documentViewer.loaded$.pipe(
filter(loaded => !loaded),
map(() => true),
);
}
}

View File

@ -3,7 +3,6 @@ import { HeaderElements } from '../../../file-preview/utils/constants';
import { ConfirmationDialogInput, ConfirmOptions, LoadingService } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FilesMapService } from '@services/files/files-map.service';
import { ActivatedRoute } from '@angular/router';
import { SharedDialogService } from '@shared/services/dialog.service';
import { PdfViewer } from '../../services/pdf-viewer.service';
import { ViewerHeaderService } from '../../services/viewer-header.service';
@ -28,7 +27,6 @@ export class CompareFileInputComponent {
private readonly _logger: NGXLogger,
private readonly _loadingService: LoadingService,
private readonly _documentViewer: REDDocumentViewer,
private readonly _activatedRoute: ActivatedRoute,
private readonly _filesMapService: FilesMapService,
private readonly _dialogService: SharedDialogService,
private readonly _viewerHeaderService: ViewerHeaderService,
@ -44,9 +42,7 @@ export class CompareFileInputComponent {
return this._filesMapService.get(dossierId, fileId)?.filename ?? 'document.pdf';
}
async upload(files: FileList) {
await this._documentViewer.lock();
upload(files: FileList) {
const fileToCompare = files[0];
this.input.nativeElement.value = null;
@ -61,11 +57,14 @@ export class CompareFileInputComponent {
fileReader.readAsArrayBuffer(fileToCompare);
}
async #createDocumentsAndCompare(blob: ArrayBuffer, fileName: string) {
async #createDocumentsAndCompare(buffer: ArrayBuffer, fileName: string) {
const currentBlob = await this._documentViewer.blob();
this._documentViewer.close();
const pdfNet = this._pdf.PDFNet;
const compareDocument = await pdfNet.PDFDoc.createFromBuffer(blob);
const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this._pdf.blob.arrayBuffer());
const compareDocument = await pdfNet.PDFDoc.createFromBuffer(buffer);
const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await currentBlob.arrayBuffer());
const currentDocumentPageCount = await currentDocument.getPageCount();
const compareDocumentPageCount = await compareDocument.getPageCount();

View File

@ -33,13 +33,11 @@ export class AnnotationDrawService {
) {}
async draw(annotations: List<AnnotationWrapper>, dossierTemplateId: string, hideSkipped: boolean) {
await this._documentViewer.lock();
try {
await this._draw(annotations, dossierTemplateId, hideSkipped);
} catch (e) {
console.log(e);
}
await this._documentViewer.unlock();
}
getAndConvertColor(superType: string, dossierTemplateId: string, dictionary?: string) {

View File

@ -19,9 +19,7 @@ export class REDDocumentViewer {
pageComplete$: Observable<boolean>;
keyUp$: Observable<KeyboardEvent>;
textSelected$: Observable<string>;
selectedText = '';
#document: DocumentViewer;
constructor(
@ -120,15 +118,9 @@ export class REDDocumentViewer {
return true;
}
async unlock() {
const document = await this.PDFDoc;
if (!document) {
return false;
}
await document.unlock();
this._logger.info('[PDF] Unlocked');
return true;
async blob() {
const data = await this.document.getFileData();
return new Blob([new Uint8Array(data)], { type: 'application/pdf' });
}
setRectangleToolStyles(color: Color) {

View File

@ -37,7 +37,6 @@ export class PdfViewer {
totalPages$: Observable<number>;
#instance: WebViewerInstance;
#currentBlob: Blob;
readonly #compareMode$ = new BehaviorSubject(false);
readonly #searchButton: IHeaderElement = {
type: 'actionButton',
@ -62,10 +61,6 @@ export class PdfViewer {
return this.#instance;
}
get blob() {
return this.#currentBlob;
}
get PDFNet(): typeof Core.PDFNet {
return this.#instance.Core.PDFNet;
}
@ -157,10 +152,12 @@ export class PdfViewer {
}
openCompareMode() {
this._logger.info('[PDF] Open compare mode');
this.#compareMode$.next(true);
}
closeCompareMode() {
this._logger.info('[PDF] Close compare mode');
this.#compareMode$.next(false);
}
@ -173,7 +170,6 @@ export class PdfViewer {
const document = await this.PDFNet.PDFDoc.createFromBuffer(await blob.arrayBuffer());
await document.flattenAnnotations(false);
this.#currentBlob = blob;
this.fileId = file.fileId;
this.dossierId = file.dossierId;

View File

@ -7,8 +7,8 @@ import { TooltipsService } from './tooltips.service';
import { PageRotationService } from './page-rotation.service';
import { PdfViewer } from './pdf-viewer.service';
import { ROTATION_ACTION_BUTTONS } from '../utils/constants';
import { ActivatedRoute } from '@angular/router';
import { FilesMapService } from '@services/files/files-map.service';
import { REDDocumentViewer } from './document-viewer.service';
const divider: IHeaderElement = {
type: 'divider',
@ -34,6 +34,7 @@ export class ViewerHeaderService {
private readonly _injector: Injector,
private readonly _translateService: TranslateService,
private readonly _pdf: PdfViewer,
private readonly _documentViewer: REDDocumentViewer,
private readonly _rotationService: PageRotationService,
private readonly _tooltipsService: TooltipsService,
) {}
@ -186,6 +187,11 @@ export class ViewerHeaderService {
});
}
resetCompareButtons() {
this.disable([HeaderElements.CLOSE_COMPARE_BUTTON]);
this.enable([HeaderElements.COMPARE_BUTTON]);
}
#toggleRotationActionButtons() {
if (this._rotationService.hasRotations) {
this.enable(ROTATION_ACTION_BUTTONS);
@ -196,16 +202,13 @@ export class ViewerHeaderService {
private _closeCompareMode() {
this._pdf.closeCompareMode();
const activatedRoute = this._injector.get(ActivatedRoute);
const dossierId = activatedRoute.snapshot.paramMap.get('dossierId');
const fileId = activatedRoute.snapshot.paramMap.get('fileId');
const { dossierId, fileId } = this._pdf;
const file = this._injector.get(FilesMapService).get(dossierId, fileId);
const filename = file.filename ?? 'document.pdf';
this._pdf.instance.UI.loadDocument(this.#docBeforeCompare, { filename });
this.disable([HeaderElements.CLOSE_COMPARE_BUTTON]);
this.enable([HeaderElements.COMPARE_BUTTON]);
this.resetCompareButtons();
this._pdf.navigateTo(1);
}
@ -217,10 +220,10 @@ export class ViewerHeaderService {
dataElement: HeaderElements.COMPARE_BUTTON,
img: this._convertPath('/assets/icons/general/pdftron-action-compare.svg'),
title: 'Compare',
onClick: () => {
onClick: async () => {
const element = compareFileInput.nativeElement as HTMLElement;
element.click();
this.#docBeforeCompare = this._pdf.blob;
this.#docBeforeCompare = await this._documentViewer.blob();
},
};
}