extract web viewer instance into a service
This commit is contained in:
parent
98a25abd27
commit
7baa9b9f56
@ -2,18 +2,18 @@
|
||||
<div #viewer [id]="(stateService.file$ | async).fileId" class="viewer"></div>
|
||||
</div>
|
||||
|
||||
<input #compareFileInput (change)="uploadFile($event.target['files'])" class="file-upload-input" type="file" accept="application/pdf" />
|
||||
<input #compareFileInput (change)="uploadFile($event.target['files'])" accept="application/pdf" class="file-upload-input" type="file" />
|
||||
|
||||
<div *ngIf="utils?.totalPages && utils?.currentPage" class="pagination noselect">
|
||||
<div (click)="utils.previousPage()">
|
||||
<div *ngIf="pdf?.totalPages && pdf?.currentPage" class="pagination noselect">
|
||||
<div (click)="pdf.previousPage()">
|
||||
<mat-icon class="chevron-icon" svgIcon="red:nav-prev"></mat-icon>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
#pageInput
|
||||
(change)="utils.navigateToPage(pageInput.value)"
|
||||
[max]="utils.totalPages"
|
||||
[value]="utils.currentPage"
|
||||
(change)="pdf.navigateToPage(pageInput.value)"
|
||||
[max]="pdf.totalPages"
|
||||
[value]="pdf.currentPage"
|
||||
class="page-number-input"
|
||||
min="1"
|
||||
type="number"
|
||||
@ -21,9 +21,9 @@
|
||||
</div>
|
||||
<div class="separator">/</div>
|
||||
<div>
|
||||
{{ utils.totalPages }}
|
||||
{{ pdf.totalPages }}
|
||||
</div>
|
||||
<div (click)="utils.nextPage()">
|
||||
<div (click)="pdf.nextPage()">
|
||||
<mat-icon class="chevron-icon" svgIcon="red:nav-next"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { Dossier, File, IHeaderElement, IManualRedactionEntry, RotationTypes } from '@red/domain';
|
||||
import WebViewer, { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
ManualRedactionEntryType,
|
||||
@ -30,7 +30,7 @@ import { ConfigService } from '@services/config.service';
|
||||
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';
|
||||
import { PdfViewer } from '../../services/pdf-viewer.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { toPosition } from '../../../../utils/pdf-calculation.utils';
|
||||
@ -40,30 +40,11 @@ import { FilePreviewStateService } from '../../services/file-preview-state.servi
|
||||
import { tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { FileManagementService } from '../../../../../../services/entity-services/file-management.service';
|
||||
import { PageRotationService } from '../../services/page-rotation.service';
|
||||
import { ALLOWED_KEYBOARD_SHORTCUTS, HeaderElements, TextPopups } from '../../shared/constants';
|
||||
import Tools = Core.Tools;
|
||||
import TextTool = Tools.TextTool;
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
const ALLOWED_KEYBOARD_SHORTCUTS: readonly string[] = ['+', '-', 'p', 'r', 'Escape'] as const;
|
||||
const headerElements = {
|
||||
SHAPE_TOOL_GROUP_BUTTON: 'shapeToolGroupButton',
|
||||
ROTATE_LEFT_BUTTON: 'rotateLeftButton',
|
||||
ROTATE_RIGHT_BUTTON: 'rotateRightButton',
|
||||
APPLY_ROTATION: 'applyRotation',
|
||||
DISCARD_ROTATION: 'discardRotation',
|
||||
TOGGLE_TOOLTIPS: 'toggle-tooltips',
|
||||
ANNOTATION_POPUP: 'annotationPopup',
|
||||
COMPARE_BUTTON: 'compareButton',
|
||||
CLOSE_COMPARE_BUTTON: 'closeCompareButton',
|
||||
} as const;
|
||||
|
||||
const textPopups = {
|
||||
ADD_REDACTION: 'add-redaction',
|
||||
ADD_DICTIONARY: 'add-dictionary',
|
||||
ADD_RECTANGLE: 'add-rectangle',
|
||||
ADD_FALSE_POSITIVE: 'add-false-positive',
|
||||
} as const;
|
||||
|
||||
function getDivider(hiddenOn?: readonly ('desktop' | 'mobile' | 'tablet')[]) {
|
||||
return {
|
||||
type: 'divider',
|
||||
@ -92,7 +73,6 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
instance: WebViewerInstance;
|
||||
documentViewer: Core.DocumentViewer;
|
||||
annotationManager: Core.AnnotationManager;
|
||||
utils: PdfViewerUtils;
|
||||
private _selectedText = '';
|
||||
|
||||
constructor(
|
||||
@ -112,6 +92,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
readonly stateService: FilePreviewStateService,
|
||||
readonly viewModeService: ViewModeService,
|
||||
readonly multiSelectService: MultiSelectService,
|
||||
readonly pdf: PdfViewer,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@ -173,7 +154,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
const loadCompareDocument = async () => {
|
||||
this._loadingService.start();
|
||||
this.utils.ready = false;
|
||||
this.pdf.ready = false;
|
||||
const mergedDocument = await pdfNet.PDFDoc.create();
|
||||
const file = await this.stateService.file;
|
||||
await loadCompareDocumentWrapper(
|
||||
@ -186,7 +167,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this.viewModeService.compareMode = true;
|
||||
},
|
||||
() => {
|
||||
this.utils.navigateToPage(1);
|
||||
this.pdf.navigateToPage(1);
|
||||
},
|
||||
this.instance.Core.PDFNet,
|
||||
);
|
||||
@ -229,30 +210,19 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
const filename = (await this.stateService.file).filename ?? 'document.pdf';
|
||||
this.instance.UI.loadDocument(currentDocument, { filename });
|
||||
|
||||
this.instance.UI.disableElements([headerElements.CLOSE_COMPARE_BUTTON]);
|
||||
this.instance.UI.enableElements([headerElements.COMPARE_BUTTON]);
|
||||
this.utils.navigateToPage(1);
|
||||
this.instance.UI.disableElements([HeaderElements.CLOSE_COMPARE_BUTTON]);
|
||||
this.instance.UI.enableElements([HeaderElements.COMPARE_BUTTON]);
|
||||
this.pdf.navigateToPage(1);
|
||||
}
|
||||
|
||||
private async _loadViewer() {
|
||||
this.instance = await WebViewer(
|
||||
{
|
||||
licenseKey: environment.licenseKey ? atob(environment.licenseKey) : null,
|
||||
fullAPI: true,
|
||||
path: this._convertPath('/assets/wv-resources'),
|
||||
css: this._convertPath('/assets/pdftron/stylesheet.css'),
|
||||
backendType: 'ems',
|
||||
},
|
||||
this.viewer.nativeElement as HTMLElement,
|
||||
);
|
||||
|
||||
this.documentViewer = this.instance.Core.documentViewer;
|
||||
this.annotationManager = this.instance.Core.annotationManager;
|
||||
this.utils = new PdfViewerUtils(this.instance, this.viewModeService);
|
||||
this.instance = await this.pdf.loadViewer(this.viewer.nativeElement as HTMLElement);
|
||||
this.documentViewer = this.pdf.documentViewer;
|
||||
this.annotationManager = this.pdf.annotationManager;
|
||||
|
||||
this._setSelectionMode();
|
||||
this._configureElements();
|
||||
this.utils.disableHotkeys();
|
||||
this.pdf.disableHotkeys();
|
||||
await this._configureTextPopup();
|
||||
|
||||
this.annotationManager.addEventListener('annotationSelected', (annotations: Annotation[], action) => {
|
||||
@ -262,7 +232,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this._toggleRectangleAnnotationAction(true);
|
||||
} else {
|
||||
if (!this.multiSelectService.isEnabled) {
|
||||
this.utils.deselectAnnotations(this.annotations.filter(wrapper => !nextAnnotations.find(ann => ann.Id === wrapper.id)));
|
||||
this.pdf.deselectAnnotations(this.annotations.filter(wrapper => !nextAnnotations.find(ann => ann.Id === wrapper.id)));
|
||||
}
|
||||
this._configureAnnotationSpecificActions(annotations);
|
||||
this._toggleRectangleAnnotationAction(annotations.length === 1 && annotations[0].ReadOnly);
|
||||
@ -280,7 +250,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
});
|
||||
|
||||
this.documentViewer.addEventListener('pageNumberUpdated', (pageNumber: number) => {
|
||||
this.utils.deselectAllAnnotations();
|
||||
this.pdf.deselectAllAnnotations();
|
||||
this._ngZone.run(() => this.pageChanged.emit(pageNumber));
|
||||
return this._handleCustomActions();
|
||||
});
|
||||
@ -305,7 +275,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
this.documentViewer.addEventListener('textSelected', async (quads, selectedText, pageNumber: number) => {
|
||||
this._selectedText = selectedText;
|
||||
const textActions = [textPopups.ADD_DICTIONARY, textPopups.ADD_FALSE_POSITIVE];
|
||||
const textActions = [TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE];
|
||||
|
||||
const file = await this.stateService.file;
|
||||
|
||||
@ -315,7 +285,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this.instance.UI.enableElements(['textPopup']);
|
||||
}
|
||||
|
||||
if (selectedText.length > 2 && this.canPerformActions && !this.utils.isCurrentPageExcluded(file)) {
|
||||
if (selectedText.length > 2 && this.canPerformActions && !this.pdf.isCurrentPageExcluded(file)) {
|
||||
this.instance.UI.enableElements(textActions);
|
||||
} else {
|
||||
this.instance.UI.disableElements(textActions);
|
||||
@ -353,9 +323,9 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
private _toggleRectangleAnnotationAction(readonly = false) {
|
||||
if (!readonly) {
|
||||
this.instance.UI.enableElements([textPopups.ADD_RECTANGLE]);
|
||||
this.instance.UI.enableElements([TextPopups.ADD_RECTANGLE]);
|
||||
} else {
|
||||
this.instance.UI.disableElements([textPopups.ADD_RECTANGLE]);
|
||||
this.instance.UI.disableElements([TextPopups.ADD_RECTANGLE]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -385,7 +355,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
const applyRotation: IHeaderElement = {
|
||||
type: 'customElement',
|
||||
dataElement: headerElements.APPLY_ROTATION,
|
||||
dataElement: HeaderElements.APPLY_ROTATION,
|
||||
render: () => {
|
||||
const paragraph = document.createElement('p');
|
||||
paragraph.innerText = 'APPLY';
|
||||
@ -398,14 +368,13 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
`;
|
||||
paragraph.addEventListener('click', async () => {
|
||||
await this._pageRotationService.applyRotation();
|
||||
this._showRotationConfirmationButtons();
|
||||
});
|
||||
return paragraph;
|
||||
},
|
||||
};
|
||||
const discardRotation: IHeaderElement = {
|
||||
type: 'customElement',
|
||||
dataElement: headerElements.DISCARD_ROTATION,
|
||||
dataElement: HeaderElements.DISCARD_ROTATION,
|
||||
render: () => {
|
||||
const paragraph = document.createElement('p');
|
||||
paragraph.innerText = 'DISCARD';
|
||||
@ -417,16 +386,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
opacity: 0.7;
|
||||
`;
|
||||
paragraph.addEventListener('click', () => {
|
||||
const rotations = this._pageRotationService.rotations$.value;
|
||||
const oneRotationDegree = 90;
|
||||
for (const page of Object.keys(rotations)) {
|
||||
const times = rotations[page] / oneRotationDegree;
|
||||
for (let i = 1; i <= times; i++) {
|
||||
this.documentViewer.rotateCounterClockwise(Number(page));
|
||||
}
|
||||
}
|
||||
this._pageRotationService.clearRotations();
|
||||
this._showRotationConfirmationButtons();
|
||||
this._pageRotationService.discardRotation();
|
||||
});
|
||||
return paragraph;
|
||||
},
|
||||
@ -438,7 +398,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
{
|
||||
type: 'actionButton',
|
||||
element: 'compare',
|
||||
dataElement: headerElements.COMPARE_BUTTON,
|
||||
dataElement: HeaderElements.COMPARE_BUTTON,
|
||||
img: this._convertPath('/assets/icons/general/pdftron-action-compare.svg'),
|
||||
title: 'Compare',
|
||||
onClick: () => {
|
||||
@ -448,7 +408,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
{
|
||||
type: 'actionButton',
|
||||
element: 'closeCompare',
|
||||
dataElement: headerElements.CLOSE_COMPARE_BUTTON,
|
||||
dataElement: HeaderElements.CLOSE_COMPARE_BUTTON,
|
||||
img: this._convertPath('/assets/icons/general/pdftron-action-close-compare.svg'),
|
||||
title: 'Leave Compare Mode',
|
||||
onClick: async () => {
|
||||
@ -459,13 +419,13 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
{
|
||||
type: 'actionButton',
|
||||
element: 'tooltips',
|
||||
dataElement: headerElements.TOGGLE_TOOLTIPS,
|
||||
dataElement: HeaderElements.TOGGLE_TOOLTIPS,
|
||||
img: this._toggleTooltipsIcon,
|
||||
title: this._toggleTooltipsBtnTitle,
|
||||
onClick: async () => {
|
||||
await this._userPreferenceService.toggleFilePreviewTooltipsPreference();
|
||||
this._updateTooltipsVisibility();
|
||||
this.instance.UI.updateElement(headerElements.TOGGLE_TOOLTIPS, {
|
||||
this.instance.UI.updateElement(HeaderElements.TOGGLE_TOOLTIPS, {
|
||||
title: this._toggleTooltipsBtnTitle,
|
||||
img: this._toggleTooltipsIcon,
|
||||
});
|
||||
@ -475,7 +435,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
{
|
||||
type: 'toolGroupButton',
|
||||
toolGroup: 'rectangleTools',
|
||||
dataElement: headerElements.SHAPE_TOOL_GROUP_BUTTON,
|
||||
dataElement: HeaderElements.SHAPE_TOOL_GROUP_BUTTON,
|
||||
img: this._convertPath('/assets/icons/general/rectangle.svg'),
|
||||
title: 'annotation.rectangle',
|
||||
},
|
||||
@ -483,24 +443,16 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
{
|
||||
type: 'actionButton',
|
||||
element: 'tooltips',
|
||||
dataElement: headerElements.ROTATE_LEFT_BUTTON,
|
||||
dataElement: HeaderElements.ROTATE_LEFT_BUTTON,
|
||||
img: this._convertPath('/assets/icons/general/rotate-left.svg'),
|
||||
onClick: () => {
|
||||
this._pageRotationService.addRotation(this.utils.currentPage, RotationTypes.LEFT);
|
||||
this.documentViewer.rotateCounterClockwise(this.utils.currentPage);
|
||||
this._showRotationConfirmationButtons();
|
||||
},
|
||||
onClick: () => this._pageRotationService.addRotation(RotationTypes.LEFT),
|
||||
},
|
||||
{
|
||||
type: 'actionButton',
|
||||
element: 'tooltips',
|
||||
dataElement: headerElements.ROTATE_RIGHT_BUTTON,
|
||||
dataElement: HeaderElements.ROTATE_RIGHT_BUTTON,
|
||||
img: this._convertPath('/assets/icons/general/rotate-right.svg'),
|
||||
onClick: () => {
|
||||
this._pageRotationService.addRotation(this.utils.currentPage, RotationTypes.RIGHT);
|
||||
this.documentViewer.rotateClockwise(this.utils.currentPage);
|
||||
this._showRotationConfirmationButtons();
|
||||
},
|
||||
onClick: () => this._pageRotationService.addRotation(RotationTypes.RIGHT),
|
||||
},
|
||||
applyRotation,
|
||||
discardRotation,
|
||||
@ -512,9 +464,9 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
});
|
||||
|
||||
this.instance.UI.disableElements([
|
||||
headerElements.CLOSE_COMPARE_BUTTON,
|
||||
headerElements.APPLY_ROTATION,
|
||||
headerElements.DISCARD_ROTATION,
|
||||
HeaderElements.CLOSE_COMPARE_BUTTON,
|
||||
HeaderElements.APPLY_ROTATION,
|
||||
HeaderElements.DISCARD_ROTATION,
|
||||
]);
|
||||
|
||||
const dossierTemplateId = this.dossier.dossierTemplateId;
|
||||
@ -527,16 +479,6 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
});
|
||||
}
|
||||
|
||||
private _showRotationConfirmationButtons() {
|
||||
const rotationElements = [headerElements.APPLY_ROTATION, headerElements.DISCARD_ROTATION];
|
||||
|
||||
if (this._pageRotationService.hasRotations()) {
|
||||
this.instance.UI.enableElements(rotationElements);
|
||||
} else {
|
||||
this.instance.UI.disableElements(rotationElements);
|
||||
}
|
||||
}
|
||||
|
||||
private _configureAnnotationSpecificActions(viewerAnnotations: Annotation[]) {
|
||||
if (!this.canPerformActions) {
|
||||
return;
|
||||
@ -591,7 +533,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this.instance.UI.annotationPopup.add([
|
||||
{
|
||||
type: 'actionButton',
|
||||
dataElement: textPopups.ADD_RECTANGLE,
|
||||
dataElement: TextPopups.ADD_RECTANGLE,
|
||||
img: this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'),
|
||||
title: this.#getTitle(ManualRedactionEntryTypes.REDACTION),
|
||||
onClick: () => this._addRectangleManualRedaction(),
|
||||
@ -611,8 +553,8 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
}
|
||||
|
||||
private _cleanUpSelectionAndButtonState() {
|
||||
const rectangleElements = [headerElements.SHAPE_TOOL_GROUP_BUTTON];
|
||||
this.utils.deselectAllAnnotations();
|
||||
const rectangleElements = [HeaderElements.SHAPE_TOOL_GROUP_BUTTON];
|
||||
this.pdf.deselectAllAnnotations();
|
||||
this.instance.UI.disableElements(rectangleElements);
|
||||
this.instance.UI.enableElements(rectangleElements);
|
||||
}
|
||||
@ -642,7 +584,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
if (this._userPreferenceService.areDevFeaturesEnabled) {
|
||||
popups.push({
|
||||
type: 'actionButton',
|
||||
dataElement: textPopups.ADD_FALSE_POSITIVE,
|
||||
dataElement: TextPopups.ADD_FALSE_POSITIVE,
|
||||
img: this._convertPath('/assets/icons/general/pdftron-action-false-positive.svg'),
|
||||
title: this.#getTitle(ManualRedactionEntryTypes.FALSE_POSITIVE),
|
||||
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.FALSE_POSITIVE),
|
||||
@ -651,14 +593,14 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
popups.push({
|
||||
type: 'actionButton',
|
||||
dataElement: textPopups.ADD_REDACTION,
|
||||
dataElement: TextPopups.ADD_REDACTION,
|
||||
img: this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'),
|
||||
title: this.#getTitle(ManualRedactionEntryTypes.REDACTION),
|
||||
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.REDACTION),
|
||||
});
|
||||
popups.push({
|
||||
type: 'actionButton',
|
||||
dataElement: textPopups.ADD_DICTIONARY,
|
||||
dataElement: TextPopups.ADD_DICTIONARY,
|
||||
img: this._convertPath('/assets/icons/general/pdftron-action-add-dict.svg'),
|
||||
title: this.#getTitle(ManualRedactionEntryTypes.DICTIONARY),
|
||||
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.DICTIONARY),
|
||||
@ -683,16 +625,16 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
private async _handleCustomActions() {
|
||||
this.instance.UI.setToolMode('AnnotationEdit');
|
||||
const elementsToToggle = [
|
||||
textPopups.ADD_REDACTION,
|
||||
textPopups.ADD_RECTANGLE,
|
||||
textPopups.ADD_FALSE_POSITIVE,
|
||||
headerElements.SHAPE_TOOL_GROUP_BUTTON,
|
||||
headerElements.ANNOTATION_POPUP,
|
||||
headerElements.ROTATE_LEFT_BUTTON,
|
||||
headerElements.ROTATE_RIGHT_BUTTON,
|
||||
TextPopups.ADD_REDACTION,
|
||||
TextPopups.ADD_RECTANGLE,
|
||||
TextPopups.ADD_FALSE_POSITIVE,
|
||||
HeaderElements.SHAPE_TOOL_GROUP_BUTTON,
|
||||
HeaderElements.ANNOTATION_POPUP,
|
||||
HeaderElements.ROTATE_LEFT_BUTTON,
|
||||
HeaderElements.ROTATE_RIGHT_BUTTON,
|
||||
];
|
||||
|
||||
const isCurrentPageExcluded = this.utils.isCurrentPageExcluded(await this.stateService.file);
|
||||
const isCurrentPageExcluded = this.pdf.isCurrentPageExcluded(await this.stateService.file);
|
||||
|
||||
if (this.canPerformActions && !isCurrentPageExcluded) {
|
||||
try {
|
||||
@ -703,20 +645,20 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this.instance.UI.enableElements(elementsToToggle);
|
||||
|
||||
if (this._selectedText.length > 2) {
|
||||
this.instance.UI.enableElements([textPopups.ADD_DICTIONARY, textPopups.ADD_FALSE_POSITIVE]);
|
||||
this.instance.UI.enableElements([TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let elementsToDisable = [...elementsToToggle, textPopups.ADD_RECTANGLE];
|
||||
let elementsToDisable = [...elementsToToggle, TextPopups.ADD_RECTANGLE];
|
||||
|
||||
if (isCurrentPageExcluded) {
|
||||
const allowedActionsWhenPageExcluded: string[] = [
|
||||
headerElements.ANNOTATION_POPUP,
|
||||
textPopups.ADD_RECTANGLE,
|
||||
textPopups.ADD_REDACTION,
|
||||
headerElements.SHAPE_TOOL_GROUP_BUTTON,
|
||||
HeaderElements.ANNOTATION_POPUP,
|
||||
TextPopups.ADD_RECTANGLE,
|
||||
TextPopups.ADD_REDACTION,
|
||||
HeaderElements.SHAPE_TOOL_GROUP_BUTTON,
|
||||
];
|
||||
elementsToDisable = elementsToDisable.filter(element => !allowedActionsWhenPageExcluded.includes(element));
|
||||
} else {
|
||||
@ -737,7 +679,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
for (const quad of quads[key]) {
|
||||
const page = parseInt(key, 10);
|
||||
const pageHeight = this.documentViewer.getPageHeight(page);
|
||||
entry.positions.push(toPosition(page, pageHeight, convertQuads ? this.utils.translateQuad(page, quad) : quad));
|
||||
entry.positions.push(toPosition(page, pageHeight, convertQuads ? this.pdf.translateQuad(page, quad) : quad));
|
||||
}
|
||||
}
|
||||
|
||||
@ -752,7 +694,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
private _setReadyAndInitialState(): void {
|
||||
this._ngZone.run(() => {
|
||||
this.utils.ready = true;
|
||||
this.pdf.ready = true;
|
||||
this.viewerReady.emit(this.instance);
|
||||
const routePageNumber: number = this._activatedRoute.snapshot.queryParams.page;
|
||||
this.pageChanged.emit(routePageNumber || 1);
|
||||
|
||||
@ -11,6 +11,7 @@ import { PdfViewerDataService } from '../../services/pdf-viewer-data.service';
|
||||
import { AnnotationReferencesService } from './services/annotation-references.service';
|
||||
import { FilterService } from '../../../../../../../../libs/common-ui/src';
|
||||
import { PageRotationService } from './services/page-rotation.service';
|
||||
import { PdfViewer } from './services/pdf-viewer.service';
|
||||
|
||||
export const filePreviewScreenProviders = [
|
||||
FilterService,
|
||||
@ -26,4 +27,5 @@ export const filePreviewScreenProviders = [
|
||||
PdfViewerDataService,
|
||||
AnnotationReferencesService,
|
||||
PageRotationService,
|
||||
PdfViewer,
|
||||
];
|
||||
|
||||
@ -297,18 +297,18 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
selectAnnotations(annotations?: AnnotationWrapper[]) {
|
||||
if (annotations) {
|
||||
const annotationsToSelect = this.multiSelectService.isActive ? [...this.selectedAnnotations, ...annotations] : annotations;
|
||||
this.viewerComponent?.utils?.selectAnnotations(annotationsToSelect, this.multiSelectService.isActive);
|
||||
this.viewerComponent?.pdf?.selectAnnotations(annotationsToSelect, this.multiSelectService.isActive);
|
||||
} else {
|
||||
this.viewerComponent?.utils?.deselectAllAnnotations();
|
||||
this.viewerComponent?.pdf?.deselectAllAnnotations();
|
||||
}
|
||||
}
|
||||
|
||||
deselectAnnotations(annotations: AnnotationWrapper[]) {
|
||||
this.viewerComponent.utils.deselectAnnotations(annotations);
|
||||
this.viewerComponent.pdf.deselectAnnotations(annotations);
|
||||
}
|
||||
|
||||
selectPage(pageNumber: number) {
|
||||
this.viewerComponent.utils.navigateToPage(pageNumber);
|
||||
this.viewerComponent.pdf.navigateToPage(pageNumber);
|
||||
this._workloadComponent?.scrollAnnotationsToPage(pageNumber, 'always');
|
||||
this._lastPage = pageNumber.toString();
|
||||
}
|
||||
@ -467,7 +467,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
#deactivateMultiSelect(): void {
|
||||
this.multiSelectService.deactivate();
|
||||
this.viewerComponent?.utils?.deselectAllAnnotations();
|
||||
this.viewerComponent?.pdf?.deselectAllAnnotations();
|
||||
this.handleAnnotationSelected([]);
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { RotationType } from '@red/domain';
|
||||
import { RotationType, RotationTypes } from '@red/domain';
|
||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { log } from '@iqser/common-ui';
|
||||
import { PdfViewer } from './pdf-viewer.service';
|
||||
import { HeaderElements } from '../shared/constants';
|
||||
|
||||
const confirmationButtons = [HeaderElements.APPLY_ROTATION, HeaderElements.DISCARD_ROTATION];
|
||||
const oneRotationDegree = 90;
|
||||
|
||||
@Injectable()
|
||||
export class PageRotationService {
|
||||
@ -15,6 +19,7 @@ export class PageRotationService {
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _fileManagementService: FileManagementService,
|
||||
private readonly _screenState: FilePreviewStateService,
|
||||
private readonly _pdf: PdfViewer,
|
||||
) {}
|
||||
|
||||
get canRotate() {
|
||||
@ -41,14 +46,49 @@ export class PageRotationService {
|
||||
return firstValueFrom(request);
|
||||
}
|
||||
|
||||
addRotation(pageNumber: number, rotation: RotationType): void {
|
||||
discardRotation() {
|
||||
const rotations = this.rotations$.value;
|
||||
|
||||
for (const page of Object.keys(rotations)) {
|
||||
const times = rotations[page] / oneRotationDegree;
|
||||
for (let i = 1; i <= times; i++) {
|
||||
this._pdf.documentViewer.rotateCounterClockwise(Number(page));
|
||||
}
|
||||
}
|
||||
|
||||
this.clearRotations();
|
||||
}
|
||||
|
||||
addRotation(rotation: RotationType): void {
|
||||
const pageNumber = this._pdf.currentPage;
|
||||
const pageRotation = this.rotations$.value[pageNumber];
|
||||
const rotationValue = pageRotation ? (pageRotation + Number(rotation)) % 360 : rotation;
|
||||
|
||||
this.rotations$.next({ ...this.rotations$.value, [pageNumber]: rotationValue });
|
||||
|
||||
if (rotation === RotationTypes.LEFT) {
|
||||
this._pdf.documentViewer.rotateCounterClockwise(pageNumber);
|
||||
} else {
|
||||
this._pdf.documentViewer.rotateClockwise(pageNumber);
|
||||
}
|
||||
|
||||
if (this.hasRotations()) {
|
||||
this.#showConfirmationButtons();
|
||||
} else {
|
||||
this.#hideConfirmationButtons();
|
||||
}
|
||||
}
|
||||
|
||||
clearRotations() {
|
||||
this.rotations$.next({});
|
||||
this.#hideConfirmationButtons();
|
||||
}
|
||||
|
||||
#showConfirmationButtons() {
|
||||
this._pdf.UI.enableElements(confirmationButtons);
|
||||
}
|
||||
|
||||
#hideConfirmationButtons() {
|
||||
this._pdf.UI.disableElements(confirmationButtons);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
import { translateQuads } from '@utils/pdf-coordinates';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { ViewModeService } from '../screens/file-preview-screen/services/view-mode.service';
|
||||
import { translateQuads } from '../../../../../utils/pdf-coordinates';
|
||||
import { AnnotationWrapper } from '../../../../../models/file/annotation.wrapper';
|
||||
import WebViewer, { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { ViewModeService } from './view-mode.service';
|
||||
import { File } from '@red/domain';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { BASE_HREF } from '../../../../../tokens';
|
||||
import { environment } from '../../../../../../environments/environment';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
import DocumentViewer = Core.DocumentViewer;
|
||||
import AnnotationManager = Core.AnnotationManager;
|
||||
|
||||
const DISABLED_HOTKEYS = [
|
||||
'CTRL+SHIFT+EQUAL',
|
||||
@ -38,10 +43,18 @@ const DISABLED_HOTKEYS = [
|
||||
'U',
|
||||
] as const;
|
||||
|
||||
export class PdfViewerUtils {
|
||||
@Injectable()
|
||||
export class PdfViewer {
|
||||
ready = false;
|
||||
instance: WebViewerInstance;
|
||||
documentViewer: DocumentViewer;
|
||||
annotationManager: AnnotationManager;
|
||||
|
||||
constructor(readonly instance: WebViewerInstance, readonly viewModeService: ViewModeService) {}
|
||||
constructor(@Inject(BASE_HREF) private readonly _baseHref: string, readonly viewModeService: ViewModeService) {}
|
||||
|
||||
get UI() {
|
||||
return this.instance.UI;
|
||||
}
|
||||
|
||||
get paginationOffset() {
|
||||
return this.viewModeService.isCompare ? 2 : 1;
|
||||
@ -83,6 +96,24 @@ export class PdfViewerUtils {
|
||||
return this.instance?.Core.documentViewer?.getPageCount();
|
||||
}
|
||||
|
||||
async loadViewer(htmlElement: HTMLElement) {
|
||||
this.instance = await WebViewer(
|
||||
{
|
||||
licenseKey: environment.licenseKey ? atob(environment.licenseKey) : null,
|
||||
fullAPI: true,
|
||||
path: this.#convertPath('/assets/wv-resources'),
|
||||
css: this.#convertPath('/assets/pdftron/stylesheet.css'),
|
||||
backendType: 'ems',
|
||||
},
|
||||
htmlElement,
|
||||
);
|
||||
|
||||
this.documentViewer = this.instance.Core.documentViewer;
|
||||
this.annotationManager = this.instance.Core.annotationManager;
|
||||
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
isCurrentPageExcluded(file: File) {
|
||||
const currentPage = this.currentPage;
|
||||
return !!file?.excludedPages?.includes(currentPage);
|
||||
@ -147,4 +178,8 @@ export class PdfViewerUtils {
|
||||
private _getAnnotationById(id: string): Annotation {
|
||||
return this._annotationManager.getAnnotationById(id);
|
||||
}
|
||||
|
||||
#convertPath(path: string) {
|
||||
return `${this._baseHref}${path}`;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
export const ALLOWED_KEYBOARD_SHORTCUTS: readonly string[] = ['+', '-', 'p', 'r', 'Escape'] as const;
|
||||
export const HeaderElements = {
|
||||
SHAPE_TOOL_GROUP_BUTTON: 'shapeToolGroupButton',
|
||||
ROTATE_LEFT_BUTTON: 'rotateLeftButton',
|
||||
ROTATE_RIGHT_BUTTON: 'rotateRightButton',
|
||||
APPLY_ROTATION: 'applyRotation',
|
||||
DISCARD_ROTATION: 'discardRotation',
|
||||
TOGGLE_TOOLTIPS: 'toggle-tooltips',
|
||||
ANNOTATION_POPUP: 'annotationPopup',
|
||||
COMPARE_BUTTON: 'compareButton',
|
||||
CLOSE_COMPARE_BUTTON: 'closeCompareButton',
|
||||
} as const;
|
||||
|
||||
export const TextPopups = {
|
||||
ADD_REDACTION: 'add-redaction',
|
||||
ADD_DICTIONARY: 'add-dictionary',
|
||||
ADD_RECTANGLE: 'add-rectangle',
|
||||
ADD_FALSE_POSITIVE: 'add-false-positive',
|
||||
} as const;
|
||||
Loading…
x
Reference in New Issue
Block a user