From fe37a7848846f3de24328b33f6ba7c5c3bf4fb9e Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 20 May 2022 11:27:11 +0300 Subject: [PATCH] RED-3988: move compare mode to pdf --- .../pdf-viewer/pdf-viewer.component.html | 6 +-- .../pdf-viewer/pdf-viewer.component.ts | 10 ++-- .../file-preview-screen.component.ts | 3 +- .../services/annotation-draw.service.ts | 4 +- .../services/pdf-viewer.service.ts | 11 +---- .../services/view-mode.service.ts | 29 ++++------- .../services/viewer-header-config.service.ts | 4 +- .../reusable-pdf-viewer.service.ts | 49 +++++++++++++++---- 8 files changed, 60 insertions(+), 56 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.html b/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.html index aebbbada4..969536f81 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.html @@ -9,8 +9,8 @@ /
- {{ pdfViewer.totalPages }} + {{ reusablePdf.totalPages$ | async }}
diff --git a/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.ts index 469f46303..548f44168 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.ts @@ -30,7 +30,6 @@ import { AutoUnsubscribe, ConfirmationDialogInput, ErrorService, LoadingService, import { PdfViewer } from '../../services/pdf-viewer.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; 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 { map, switchMap, tap, withLatestFrom } from 'rxjs/operators'; @@ -84,7 +83,6 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha private readonly _annotationManager: REDAnnotationManager, readonly reusablePdf: ReusablePdfViewer, readonly stateService: FilePreviewStateService, - readonly viewModeService: ViewModeService, readonly multiSelectService: MultiSelectService, readonly pdfViewer: PdfViewer, ) { @@ -143,7 +141,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha this.instance, file, () => { - this.viewModeService.compareMode = true; + this.reusablePdf.openCompareMode(); }, () => { this.pdfViewer.navigateToPage(1); @@ -256,7 +254,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha const file = this.stateService.file; - if (this.viewModeService.isCompare && pageNumber % 2 === 0) { + if (this.reusablePdf.isCompare && pageNumber % 2 === 0) { this.instance.UI.disableElements(['textPopup']); } else { this.instance.UI.enableElements(['textPopup']); @@ -285,7 +283,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha private _setInitialDisplayMode() { this.instance.UI.setFitMode('FitPage'); const instanceDisplayMode = this.documentViewer.getDisplayModeManager().getDisplayMode(); - instanceDisplayMode.mode = this.viewModeService.isCompare ? 'Facing' : 'Single'; + instanceDisplayMode.mode = this.reusablePdf.isCompare ? 'Facing' : 'Single'; this.documentViewer.getDisplayModeManager().setDisplayMode(instanceDisplayMode); } @@ -362,7 +360,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha } private _configureRectangleAnnotationPopup(annotation: Annotation) { - if (!this.viewModeService.isCompare || annotation.getPageNumber() % 2 === 1) { + if (!this.reusablePdf.isCompare || annotation.getPageNumber() % 2 === 1) { this.instance.UI.annotationPopup.add([ { type: 'actionButton', diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index 085f8a864..9f136d435 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -129,7 +129,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni private get _canPerformAnnotationActions$() { const viewMode$ = this._viewModeService.viewMode$.pipe(tap(() => this.#deactivateMultiSelect())); - return combineLatest([this.state.file$, this.state.dossier$, viewMode$, this._viewModeService.compareMode$]).pipe( + return combineLatest([this.state.file$, this.state.dossier$, viewMode$, this.reusablePdf.compareMode$]).pipe( map( ([file, dossier, viewMode]) => this.permissionsService.canPerformAnnotationActions(file, dossier) && viewMode === 'STANDARD', @@ -204,7 +204,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni return this._navigateToDossier(); } - this._viewModeService.compareMode = false; this._viewModeService.switchToStandard(); this.state.reloadBlob(); diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-draw.service.ts index e0605da03..707fd286e 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-draw.service.ts @@ -12,7 +12,6 @@ import { firstValueFrom } from 'rxjs'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { PdfViewer } from './pdf-viewer.service'; import { FilePreviewStateService } from './file-preview-state.service'; -import { ViewModeService } from './view-mode.service'; import { FileDataService } from './file-data.service'; import { SuperTypes } from '@models/file/super-types'; import { ReusablePdfViewer } from '../../shared/components/reusable-pdf-viewer/reusable-pdf-viewer.service'; @@ -32,7 +31,6 @@ export class AnnotationDrawService { private readonly _pdf: PdfViewer, private readonly _reusablePdf: ReusablePdfViewer, private readonly _state: FilePreviewStateService, - private readonly _viewModeService: ViewModeService, private readonly _fileDataService: FileDataService, ) {} @@ -135,7 +133,7 @@ export class AnnotationDrawService { } private _computeAnnotation(annotationWrapper: AnnotationWrapper) { - const pageNumber = this._viewModeService.isCompare ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber; + const pageNumber = this._reusablePdf.isCompare ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber; if (pageNumber > this._reusablePdf.pageCount) { // skip imported annotations from files that have more pages than the current one return; diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-viewer.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-viewer.service.ts index 55f710ce1..375684de0 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-viewer.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-viewer.service.ts @@ -1,7 +1,6 @@ import { translateQuads } from '../../../utils'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { Core } from '@pdftron/webviewer'; -import { ViewModeService } from './view-mode.service'; import { File } from '@red/domain'; import { Injectable } from '@angular/core'; import { ListingService } from '@iqser/common-ui'; @@ -12,7 +11,6 @@ import { REDAnnotationManager } from '../../shared/components/reusable-pdf-viewe @Injectable() export class PdfViewer { constructor( - private readonly _viewModeService: ViewModeService, private readonly _multiSelectService: MultiSelectService, private readonly _reusablePdf: ReusablePdfViewer, private readonly _annotationManager: REDAnnotationManager, @@ -20,16 +18,11 @@ export class PdfViewer { ) {} get paginationOffset() { - return this._viewModeService.isCompare ? 2 : 1; + return this._reusablePdf.isCompare ? 2 : 1; } get currentPage() { - return this._viewModeService.isCompare ? Math.ceil(this._currentInternalPage / 2) : this._currentInternalPage; - } - - get totalPages() { - const pageCount = this._reusablePdf.pageCount; - return this._viewModeService.isCompare ? Math.ceil(pageCount / 2) : pageCount; + return this._reusablePdf.isCompare ? Math.ceil(this._currentInternalPage / 2) : this._currentInternalPage; } private get _currentInternalPage() { diff --git a/apps/red-ui/src/app/modules/file-preview/services/view-mode.service.ts b/apps/red-ui/src/app/modules/file-preview/services/view-mode.service.ts index 08c21b77d..9a9e50ba0 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/view-mode.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/view-mode.service.ts @@ -7,17 +7,14 @@ import { shareDistinctLast } from '@iqser/common-ui'; @Injectable() export class ViewModeService { readonly viewMode$: Observable; - readonly compareMode$: Observable; readonly isRedacted$: Observable; readonly isStandard$: Observable; readonly isDelta$: Observable; - private readonly _viewMode$ = new BehaviorSubject('STANDARD'); - private readonly _compareMode$ = new BehaviorSubject(false); + readonly #viewMode$ = new BehaviorSubject('STANDARD'); constructor() { - this.viewMode$ = this._viewMode$.asObservable(); - this.compareMode$ = this._compareMode$.asObservable(); + this.viewMode$ = this.#viewMode$.asObservable(); this.isRedacted$ = this._is('REDACTED'); this.isStandard$ = this._is('STANDARD'); this.isDelta$ = this._is('DELTA'); @@ -28,35 +25,27 @@ export class ViewModeService { } get viewMode() { - return this._viewMode$.value; + return this.#viewMode$.value; } set viewMode(mode: ViewMode) { - this._viewMode$.next(mode); + this.#viewMode$.next(mode); } get isStandard() { - return this._viewMode$.value === 'STANDARD'; + return this.#viewMode$.value === 'STANDARD'; } get isDelta() { - return this._viewMode$.value === 'DELTA'; + return this.#viewMode$.value === 'DELTA'; } get isRedacted() { - return this._viewMode$.value === 'REDACTED'; + return this.#viewMode$.value === 'REDACTED'; } get isTextHighlights() { - return this._viewMode$.value === 'TEXT_HIGHLIGHTS'; - } - - get isCompare() { - return this._compareMode$.value; - } - - set compareMode(compareMode: boolean) { - this._compareMode$.next(compareMode); + return this.#viewMode$.value === 'TEXT_HIGHLIGHTS'; } switchToStandard() { @@ -76,7 +65,7 @@ export class ViewModeService { } private _switchTo(mode: ViewMode) { - this._viewMode$.next(mode); + this.#viewMode$.next(mode); } private _is(mode: ViewMode) { diff --git a/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts b/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts index 1dd454726..cfb55dce0 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts @@ -6,7 +6,6 @@ import { BASE_HREF } from '../../../tokens'; import { PdfViewer } from './pdf-viewer.service'; import { TooltipsService } from './tooltips.service'; import { environment } from '@environments/environment'; -import { ViewModeService } from './view-mode.service'; import { FilePreviewStateService } from './file-preview-state.service'; import { PageRotationService } from './page-rotation.service'; import { ReusablePdfViewer } from '../../shared/components/reusable-pdf-viewer/reusable-pdf-viewer.service'; @@ -36,7 +35,6 @@ export class ViewerHeaderConfigService { private readonly _pdfViewer: PdfViewer, private readonly _reusablePdf: ReusablePdfViewer, private readonly _tooltipsService: TooltipsService, - private readonly _viewModeService: ViewModeService, private readonly _stateService: FilePreviewStateService, ) {} @@ -164,7 +162,7 @@ export class ViewerHeaderConfigService { } private async _closeCompareMode() { - this._viewModeService.compareMode = false; + this._reusablePdf.closeCompareMode(); const pdfNet = this._reusablePdf.PDFNet; await pdfNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null); const blob = await this._stateService.blob; diff --git a/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/reusable-pdf-viewer.service.ts b/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/reusable-pdf-viewer.service.ts index 66550448d..a7d15f4f6 100644 --- a/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/reusable-pdf-viewer.service.ts +++ b/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/reusable-pdf-viewer.service.ts @@ -3,19 +3,19 @@ import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/w import { environment } from '@environments/environment'; import { BASE_HREF_FN, BaseHrefFn } from '../../../../tokens'; import { File } from '@red/domain'; -import { ErrorService, shareDistinctLast, shareLast } from '@iqser/common-ui'; +import { ErrorService, log, shareDistinctLast, shareLast } from '@iqser/common-ui'; import { ActivatedRoute } from '@angular/router'; import { debounceTime, map, tap } from 'rxjs/operators'; -import { fromEvent, merge, Observable, Subject } from 'rxjs'; +import { BehaviorSubject, combineLatest, fromEvent, merge, Observable } from 'rxjs'; import { ConfigService } from '@services/config.service'; import { NGXLogger } from 'ngx-logger'; import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, USELESS_ELEMENTS } from './constants'; import { Rgb } from '@shared/components/reusable-pdf-viewer/types'; -import DocumentViewer = Core.DocumentViewer; import AnnotationManager = Core.AnnotationManager; import TextTool = Core.Tools.TextTool; import Annotation = Core.Annotations.Annotation; import TextHighlightAnnotation = Core.Annotations.TextHighlightAnnotation; +import DocumentViewer = Core.DocumentViewer; @Injectable({ providedIn: 'root', @@ -30,9 +30,11 @@ export class ReusablePdfViewer { documentLoaded$: Observable; pageComplete$: Observable; + compareMode$: Observable; + totalPages$: Observable; #instance: WebViewerInstance; - #documentClosed$ = new Subject(); + readonly #compareMode$ = new BehaviorSubject(false); constructor( @Inject(BASE_HREF_FN) private readonly _convertPath: BaseHrefFn, @@ -58,6 +60,10 @@ export class ReusablePdfViewer { return this.#instance.Core.PDFNet; } + get isCompare() { + return this.#compareMode$.value; + } + get pageCount() { try { return this.#instance.Core.documentViewer.getPageCount(); @@ -67,17 +73,30 @@ export class ReusablePdfViewer { } } + get #totalPages$() { + const layoutChanged$ = fromEvent(this.documentViewer, 'layoutChanged'); + const pageCount$ = layoutChanged$.pipe(map(() => this.pageCount)); + const docChanged$ = combineLatest([pageCount$, this.compareMode$]).pipe(log('total pages')); + return docChanged$.pipe(map(([pageCount, isCompare]) => (isCompare ? Math.ceil(pageCount / 2) : pageCount))); + } + get #pageComplete$() { return fromEvent(this.documentViewer, 'pageComplete').pipe(debounceTime(300)); } get #documentLoaded$() { - const event$ = fromEvent(this.documentViewer, this.#instance.UI.Events.DOCUMENT_LOADED); + const event$ = fromEvent(this.documentViewer, 'documentLoaded'); const toBool$ = event$.pipe(map(() => true)); const updateCurrentPage$ = toBool$.pipe(tap(() => this.#setCurrentPage())); - const log = tap(() => this._logger.info('[PDF] Document loaded')); - return updateCurrentPage$.pipe(log); + return updateCurrentPage$.pipe(tap(() => this._logger.info('[PDF] Document loaded'))); + } + + get #documentUnloaded$() { + const event$ = fromEvent(this.documentViewer, 'documentUnloaded'); + const toBool$ = event$.pipe(map(() => false)); + + return toBool$.pipe(tap(() => this._logger.info('[PDF] Document unloaded'))); } async init(htmlElement: HTMLElement) { @@ -87,8 +106,10 @@ export class ReusablePdfViewer { this.documentViewer = this.#instance.Core.documentViewer; this.annotationManager = this.#instance.Core.annotationManager; - this.documentLoaded$ = merge(this.#documentClosed$, this.#documentLoaded$).pipe(shareLast()); - this.pageComplete$ = this.#pageComplete$; + this.documentLoaded$ = merge(this.#documentUnloaded$, this.#documentLoaded$).pipe(shareLast()); + this.compareMode$ = this.#compareMode$.asObservable(); + this.pageComplete$ = this.#pageComplete$.pipe(shareLast()); + this.totalPages$ = this.#totalPages$.pipe(shareLast()); this.#setSelectionMode(); this.#configureElements(); this.#disableHotkeys(); @@ -107,10 +128,18 @@ export class ReusablePdfViewer { closeDocument() { this._logger.info('[PDF] Closing document'); - this.#documentClosed$.next(false); + this.closeCompareMode(); this.documentViewer.closeDocument(); } + openCompareMode() { + this.#compareMode$.next(true); + } + + closeCompareMode() { + this.#compareMode$.next(false); + } + async lockDocument() { const document = await this.PDFDoc; if (!document) {