RED-3988: move compare mode to pdf

This commit is contained in:
Dan Percic 2022-05-20 11:27:11 +03:00
parent ba8265c049
commit fe37a78488
8 changed files with 60 additions and 56 deletions

View File

@ -9,8 +9,8 @@
<input
#pageInput
(change)="pdfViewer.navigateToPage(pageInput.value)"
[max]="pdfViewer.totalPages"
[value]="pdfViewer.currentPage"
[max]="reusablePdf.totalPages$ | async"
[value]="reusablePdf.currentPage$ | async"
class="page-number-input"
min="1"
type="number"
@ -20,7 +20,7 @@
<div class="separator">/</div>
<div>
{{ pdfViewer.totalPages }}
{{ reusablePdf.totalPages$ | async }}
</div>
<div (click)="pdfViewer.navigateNextPage()">

View File

@ -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',

View File

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

View File

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

View File

@ -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() {

View File

@ -7,17 +7,14 @@ import { shareDistinctLast } from '@iqser/common-ui';
@Injectable()
export class ViewModeService {
readonly viewMode$: Observable<ViewMode>;
readonly compareMode$: Observable<boolean>;
readonly isRedacted$: Observable<boolean>;
readonly isStandard$: Observable<boolean>;
readonly isDelta$: Observable<boolean>;
private readonly _viewMode$ = new BehaviorSubject<ViewMode>('STANDARD');
private readonly _compareMode$ = new BehaviorSubject<boolean>(false);
readonly #viewMode$ = new BehaviorSubject<ViewMode>('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) {

View File

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

View File

@ -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<boolean>;
pageComplete$: Observable<unknown>;
compareMode$: Observable<boolean>;
totalPages$: Observable<number>;
#instance: WebViewerInstance;
#documentClosed$ = new Subject<boolean>();
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<boolean>(() => 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) {