From 428975cd4ea2597bf48a3114d040a4127a951e00 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 20 May 2022 15:37:50 +0300 Subject: [PATCH] RED-3988: make tooltips service global --- .../pdf-paginator/pdf-paginator.component.ts | 83 ++++++++----------- .../file-preview/file-preview-providers.ts | 2 - .../file-preview-screen.component.ts | 1 + .../services/viewer-header-config.service.ts | 2 +- .../reusable-pdf-viewer/pdf-viewer.service.ts | 23 ++++- .../reusable-pdf-viewer}/tooltips.service.ts | 35 ++++---- 6 files changed, 73 insertions(+), 73 deletions(-) rename apps/red-ui/src/app/modules/{file-preview/services => shared/components/reusable-pdf-viewer}/tooltips.service.ts (50%) diff --git a/apps/red-ui/src/app/modules/file-preview/components/pdf-paginator/pdf-paginator.component.ts b/apps/red-ui/src/app/modules/file-preview/components/pdf-paginator/pdf-paginator.component.ts index 77059304e..ed1b0d8b8 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/pdf-paginator/pdf-paginator.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/pdf-paginator/pdf-paginator.component.ts @@ -39,7 +39,6 @@ import { loadCompareDocumentWrapper } from '../../utils/compare-mode.utils'; import { from } from 'rxjs'; import { FileDataService } from '../../services/file-data.service'; import { ViewerHeaderConfigService } from '../../services/viewer-header-config.service'; -import { TooltipsService } from '../../services/tooltips.service'; import { ManualRedactionService } from '../../services/manual-redaction.service'; import { PdfViewer } from '../../../shared/components/reusable-pdf-viewer/pdf-viewer.service'; import { REDAnnotationManager } from '../../../shared/components/reusable-pdf-viewer/annotation-manager.service'; @@ -54,7 +53,7 @@ import Annotation = Core.Annotations.Annotation; export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, OnChanges { @Input() dossier: Dossier; @Input() canPerformActions = false; - @Output() readonly annotationSelected = new EventEmitter(); + @Output() readonly annotationSelected = this.#annotationSelected$; @Output() readonly manualAnnotationRequested = new EventEmitter(); @Output() readonly pageChanged = new EventEmitter(); @Output() readonly keyUp = new EventEmitter(); @@ -78,7 +77,6 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On private readonly _pageRotationService: PageRotationService, private readonly _fileDataService: FileDataService, private readonly _headerConfigService: ViewerHeaderConfigService, - private readonly _tooltipsService: TooltipsService, private readonly _errorService: ErrorService, private readonly _annotationManager: REDAnnotationManager, readonly pdf: PdfViewer, @@ -88,8 +86,11 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On super(); } + get #annotationSelected$() { + return this._annotationManager.annotationSelected$.pipe(map(value => this.#processSelectedAnnotations(...value))); + } + ngOnInit() { - this._setReadyAndInitialState = this._setReadyAndInitialState.bind(this); this._loadViewer(); this.addActiveScreenSubscription = this.stateService.blob$ @@ -178,6 +179,36 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On fileReader.readAsArrayBuffer(fileToCompare); } + #processSelectedAnnotations(annotations: Annotation[], action) { + let nextAnnotations: Annotation[]; + + if (action === 'deselected') { + // Remove deselected annotations from selected list + nextAnnotations = this.annotationManager.getSelectedAnnotations().filter(ann => !annotations.some(a => a.Id === ann.Id)); + } else if (!this.multiSelectService.isEnabled) { + // Only choose the last selected annotation, to bypass viewer multi select + nextAnnotations = annotations; + } else { + // Get selected annotations from the manager, no intervention needed + nextAnnotations = this.annotationManager.getSelectedAnnotations(); + } + + // this.annotationSelected.emit(nextAnnotations.map(ann => ann.Id)); + if (action === 'deselected') { + this._toggleRectangleAnnotationAction(true); + return nextAnnotations.map(ann => ann.Id); + } + + if (!this.multiSelectService.isEnabled) { + const notSelected = this._fileDataService.all.filter(wrapper => !nextAnnotations.some(ann => ann.Id === wrapper.id)); + this._annotationManager.deselectAnnotations(notSelected); + } + + this.#configureAnnotationSpecificActions(annotations); + this._toggleRectangleAnnotationAction(annotations.length === 1 && annotations[0].ReadOnly); + return nextAnnotations.map(ann => ann.Id); + } + private _loadViewer() { this.instance = this.pdf.instance; this.documentViewer = this.pdf.documentViewer; @@ -186,33 +217,6 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On this._configureElements(); this._configureTextPopup(); - this.annotationManager.addEventListener('annotationSelected', (annotations: Annotation[], action) => { - let nextAnnotations: Annotation[]; - - if (action === 'deselected') { - // Remove deselected annotations from selected list - nextAnnotations = this.annotationManager.getSelectedAnnotations().filter(ann => !annotations.some(a => a.Id === ann.Id)); - } else if (!this.multiSelectService.isEnabled) { - // Only choose the last selected annotation, to bypass viewer multi select - nextAnnotations = annotations; - } else { - // Get selected annotations from the manager, no intervention needed - nextAnnotations = this.annotationManager.getSelectedAnnotations(); - } - - this.annotationSelected.emit(nextAnnotations.map(ann => ann.Id)); - if (action === 'deselected') { - return this._toggleRectangleAnnotationAction(true); - } - - if (!this.multiSelectService.isEnabled) { - const notSelected = this._fileDataService.all.filter(wrapper => !nextAnnotations.some(ann => ann.Id === wrapper.id)); - this._annotationManager.deselectAnnotations(notSelected); - } - this.#configureAnnotationSpecificActions(annotations); - this._toggleRectangleAnnotationAction(annotations.length === 1 && annotations[0].ReadOnly); - }); - this.annotationManager.addEventListener('annotationChanged', (annotations: Annotation[]) => { // when a rectangle is drawn, // it returns one annotation with tool name 'AnnotationCreateRectangle; @@ -225,12 +229,11 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On this.documentViewer.addEventListener('pageNumberUpdated', (pageNumber: number) => { this._annotationManager.deselectAnnotations(); + console.log(pageNumber); this._ngZone.run(() => this.pageChanged.emit(pageNumber)); return this._handleCustomActions(); }); - this.documentViewer.addEventListener('documentLoaded', this._setReadyAndInitialState); - this.documentViewer.addEventListener('keyUp', ($event: KeyboardEvent) => { // arrows and full-screen if (($event.target as HTMLElement)?.tagName?.toLowerCase() !== 'input') { @@ -280,13 +283,6 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On }); } - private _setInitialDisplayMode() { - this.instance.UI.setFitMode('FitPage'); - const instanceDisplayMode = this.documentViewer.getDisplayModeManager().getDisplayMode(); - instanceDisplayMode.mode = this.pdf.isCompare ? 'Facing' : 'Single'; - this.documentViewer.getDisplayModeManager().setDisplayMode(instanceDisplayMode); - } - private _convertPath(path: string): string { return this._baseHref + path; } @@ -520,11 +516,4 @@ export class PdfPaginatorComponent extends AutoUnsubscribe implements OnInit, On const rotation = this.pdf.documentViewer.getCompleteRotation(page); return translateQuads(page, rotation, quad); } - - private _setReadyAndInitialState() { - this._ngZone.run(() => { - this._setInitialDisplayMode(); - this._tooltipsService.updateTooltipsVisibility(); - }); - } } diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts index e5d898bdd..9795d5679 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts @@ -14,7 +14,6 @@ import { dossiersServiceProvider } from '@services/entity-services/dossiers.serv import { PageRotationService } from './services/page-rotation.service'; import { FileDataService } from './services/file-data.service'; import { ViewerHeaderConfigService } from './services/viewer-header-config.service'; -import { TooltipsService } from './services/tooltips.service'; import { AnnotationsListingService } from './services/annotations-listing.service'; import { StampService } from './services/stamp.service'; @@ -36,7 +35,6 @@ export const filePreviewScreenProviders = [ { provide: EntitiesService, useExisting: FileDataService }, dossiersServiceProvider, ViewerHeaderConfigService, - TooltipsService, AnnotationsListingService, { provide: ListingService, useExisting: AnnotationsListingService }, SearchService, 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 e2f3aee50..4c675fd97 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 @@ -230,6 +230,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } handleAnnotationSelected(annotationIds: string[]) { + console.log(annotationIds); this.listingService.setSelected(annotationIds.map(id => this._fileDataService.find(id)).filter(ann => ann !== undefined)); this._changeDetectorRef.markForCheck(); } 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 2593df85f..a7ef7b323 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 @@ -3,7 +3,7 @@ import { IHeaderElement, RotationTypes } from '@red/domain'; import { HeaderElements, HeaderElementType } from '../utils/constants'; import { TranslateService } from '@ngx-translate/core'; import { BASE_HREF } from '../../../tokens'; -import { TooltipsService } from './tooltips.service'; +import { TooltipsService } from '../../shared/components/reusable-pdf-viewer/tooltips.service'; import { environment } from '@environments/environment'; import { FilePreviewStateService } from './file-preview-state.service'; import { PageRotationService } from './page-rotation.service'; diff --git a/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/pdf-viewer.service.ts b/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/pdf-viewer.service.ts index 080711071..334e80f95 100644 --- a/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/pdf-viewer.service.ts +++ b/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/pdf-viewer.service.ts @@ -11,6 +11,7 @@ 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 { UserPreferenceService } from '@services/user-preference.service'; import AnnotationManager = Core.AnnotationManager; import TextTool = Core.Tools.TextTool; import Annotation = Core.Annotations.Annotation; @@ -42,6 +43,7 @@ export class PdfViewer { constructor( private readonly _logger: NGXLogger, private readonly _activatedRoute: ActivatedRoute, + private readonly _userPreferenceService: UserPreferenceService, private readonly _injector: Injector, ) {} @@ -101,9 +103,13 @@ export class PdfViewer { get #documentLoaded$() { const event$ = fromEvent(this.documentViewer, 'documentLoaded'); const toBool$ = event$.pipe(map(() => true)); - const updateCurrentPage$ = toBool$.pipe(tap(() => this.#setCurrentPage())); - return updateCurrentPage$.pipe(tap(() => this._logger.info('[PDF] Document loaded'))); + return toBool$.pipe( + tap(() => this.#setCurrentPage()), + tap(() => this.#setInitialDisplayMode()), + tap(() => this.updateTooltipsVisibility()), + tap(() => this._logger.info('[PDF] Document loaded')), + ); } get #documentUnloaded$() { @@ -204,6 +210,11 @@ export class PdfViewer { this.#instance.UI.loadDocument(document, { filename: file?.filename + '.pdf' ?? 'document.pdf', onError }); } + updateTooltipsVisibility(): void { + const current = this._userPreferenceService.getFilePreviewTooltipsPreference(); + this.#instance.UI.setAnnotationContentOverlayHandler(() => (current ? undefined : false)); + } + quad(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number) { return new this.#instance.Core.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4); } @@ -224,6 +235,14 @@ export class PdfViewer { return annotation instanceof this.#instance.Core.Annotations.TextHighlightAnnotation; } + #setInitialDisplayMode() { + this.#instance.UI.setFitMode('FitPage'); + const displayModeManager = this.documentViewer.getDisplayModeManager(); + const instanceDisplayMode = displayModeManager.getDisplayMode(); + instanceDisplayMode.mode = this.isCompare ? 'Facing' : 'Single'; + displayModeManager.setDisplayMode(instanceDisplayMode); + } + #navigateTo(pageNumber: number) { if (this.#currentInternalPage !== pageNumber) { this.documentViewer.displayPageLocation(pageNumber, 0, 0); diff --git a/apps/red-ui/src/app/modules/file-preview/services/tooltips.service.ts b/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/tooltips.service.ts similarity index 50% rename from apps/red-ui/src/app/modules/file-preview/services/tooltips.service.ts rename to apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/tooltips.service.ts index c6ec6615a..f13e63c6e 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/tooltips.service.ts +++ b/apps/red-ui/src/app/modules/shared/components/reusable-pdf-viewer/tooltips.service.ts @@ -1,15 +1,20 @@ import { Inject, Injectable } from '@angular/core'; -import { UserPreferenceService } from '@services/user-preference.service'; -import { HeaderElements } from '../utils/constants'; +import { UserPreferenceService } from '../../../../services/user-preference.service'; +import { HeaderElements } from '../../../file-preview/utils/constants'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { TranslateService } from '@ngx-translate/core'; -import { BASE_HREF } from '../../../tokens'; -import { PdfViewer } from '../../shared/components/reusable-pdf-viewer/pdf-viewer.service'; +import { BASE_HREF_FN, BaseHrefFn } from '../../../../tokens'; +import { PdfViewer } from './pdf-viewer.service'; -@Injectable() +@Injectable({ + providedIn: 'root', +}) export class TooltipsService { + readonly #enableIcon = this._convertPath('/assets/icons/general/pdftron-action-enable-tooltips.svg'); + readonly #disableIcon = this._convertPath('/assets/icons/general/pdftron-action-disable-tooltips.svg'); + constructor( - @Inject(BASE_HREF) private readonly _baseHref: string, + @Inject(BASE_HREF_FN) private readonly _convertPath: BaseHrefFn, private readonly _pdf: PdfViewer, private readonly _userPreferenceService: UserPreferenceService, private readonly _translateService: TranslateService, @@ -22,28 +27,16 @@ export class TooltipsService { } get toggleTooltipsBtnIcon(): string { - return this._convertPath( - this._userPreferenceService.getFilePreviewTooltipsPreference() - ? '/assets/icons/general/pdftron-action-enable-tooltips.svg' - : '/assets/icons/general/pdftron-action-disable-tooltips.svg', - ); - } - - updateTooltipsVisibility(): void { - const current = this._userPreferenceService.getFilePreviewTooltipsPreference(); - this._pdf.instance.UI.setAnnotationContentOverlayHandler(() => (current ? undefined : false)); + const tooltipsDisabled = this._userPreferenceService.getFilePreviewTooltipsPreference(); + return tooltipsDisabled ? this.#enableIcon : this.#disableIcon; } async toggleTooltips(): Promise { await this._userPreferenceService.toggleFilePreviewTooltipsPreference(); - this.updateTooltipsVisibility(); + this._pdf.updateTooltipsVisibility(); this._pdf.instance.UI.updateElement(HeaderElements.TOGGLE_TOOLTIPS, { title: this.toggleTooltipsBtnTitle, img: this.toggleTooltipsBtnIcon, }); } - - private _convertPath(path: string): string { - return this._baseHref + path; - } }