From 0cb4ffd8b41f2f844a1f72fe62a03b198194512e Mon Sep 17 00:00:00 2001 From: Nicoleta Panaghiu Date: Wed, 4 Oct 2023 15:27:18 +0300 Subject: [PATCH] RED-7605: fixed search again. --- .../file-preview-screen.component.ts | 7 +- .../pdf-viewer/services/pdf-viewer.service.ts | 83 ++++++++++++++----- .../app/modules/pdf-viewer/utils/constants.ts | 9 -- 3 files changed, 62 insertions(+), 37 deletions(-) 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 4740a39d9..63cd208ca 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 @@ -347,7 +347,7 @@ export class FilePreviewScreenComponent } } - @HostListener('window:keyup', ['$event']) + @HostListener('document:keyup', ['$event']) handleKeyEvent($event: KeyboardEvent) { if (this._router.url.indexOf('/file/') < 0) { return; @@ -361,17 +361,14 @@ export class FilePreviewScreenComponent $event.preventDefault(); this.fullScreen = false; this.closeFullScreen(); - this.pdf.deactivateSearch(); - this.pdf.focusViewer(); this._changeRef.markForCheck(); } - if (['f', 'F'].includes($event.key) && !$event.ctrlKey) { + if (!$event.ctrlKey && !$event.metaKey && ['f', 'F'].includes($event.key)) { // if you type in an input, don't toggle full-screen if ($event.target instanceof HTMLInputElement || $event.target instanceof HTMLTextAreaElement) { return; } - this.toggleFullScreen(); return; } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts index e8cfbe893..b99aff4ee 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts @@ -7,7 +7,7 @@ import { map, startWith } from 'rxjs/operators'; import { BehaviorSubject, combineLatest, fromEvent, Observable, switchMap } from 'rxjs'; import { ConfigService } from '@services/config.service'; import { NGXLogger } from 'ngx-logger'; -import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, SEARCH_OPTIONS, USELESS_ELEMENTS } from '../utils/constants'; +import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, USELESS_ELEMENTS } from '../utils/constants'; import { Rgb } from '../utils/types'; import { asList } from '../utils/functions'; import { TranslateService } from '@ngx-translate/core'; @@ -43,6 +43,15 @@ export class PdfViewer { compareMode$: Observable; totalPages$: Observable; + searchOptions = { + caseSensitive: true, // match case + wholeWord: true, // match whole words only + wildcard: false, // allow using '*' as a wildcard value + regex: false, // string is treated as a regular expression + searchUp: false, // search from the end of the document upwards + ambientString: true, // return ambient string as part of the result + }; + constructor( private readonly _logger: NGXLogger, private readonly _injector: Injector, @@ -103,18 +112,15 @@ export class PdfViewer { } activateSearch() { - this.#instance.UI.openElements(['searchPanel']); + this.#instance.UI.searchTextFull('', this.searchOptions); } deactivateSearch() { - this.#clearSearchResultsWhenVisibilityChanged(); + this.instance.UI.iframeWindow.document.getElementById('SearchPanel__input').blur(); + this.#updateSearchOptions(); this.#instance.UI.closeElements(['searchPanel']); } - focusViewer() { - this.instance.UI.iframeWindow.focus(); - } - resetAnnotationActions() { if (this.#instance.UI.annotationPopup.getItems().length) { this.#instance.UI.annotationPopup.update([]); @@ -163,8 +169,9 @@ export class PdfViewer { this.#setSelectionMode(); this.#configureElements(); this.#disableHotkeys(); - this.#clearSearchResultsWhenVisibilityChanged(); this.#listenForCommandF(); + this.#listenForEsc(); + this.#clearSearchResultsWhenVisibilityChanged(); return this.#instance; } @@ -241,6 +248,42 @@ export class PdfViewer { this.#instance.UI.textPopup.update([...popups, this.#searchButton, { dataElement: 'copyTextButton' }]); } + #listenForCommandF() { + this.#instance.UI.hotkeys.on('command+f, ctrl+f', e => { + e.preventDefault(); + if (!this.#isElementActive('searchPanel')) { + this.activateSearch(); + } + if (this.documentViewer.getSelectedText()) { + this.#updateSearchOptions(); + this.#searchForSelectedText(); + } + setTimeout(() => this.#focusSearch(), 30); + }); + } + + #listenForEsc() { + this.#instance.UI.hotkeys.on('esc', e => { + e.preventDefault(); + if (this.#isElementActive('searchPanel')) { + this.#focusViewer(); + this.deactivateSearch(); + } + }); + } + + #getSearchOption(optionId: string): boolean { + const iframeWindow = this.#instance.UI.iframeWindow; + const checkbox = iframeWindow.document.getElementById(optionId) as HTMLInputElement; + return checkbox.checked; + } + + #updateSearchOptions() { + const wholeWord = this.#getSearchOption('whole-word-option'); + const caseSensitive = this.#getSearchOption('case-sensitive-option'); + this.searchOptions = { ...this.searchOptions, wholeWord: wholeWord, caseSensitive: caseSensitive }; + } + #adjustPage(page: number) { if (this.isCompare) { if (page % 2 === 1) { @@ -255,7 +298,7 @@ export class PdfViewer { #searchForSelectedText() { const selected = [...new Set(this.documentViewer.getSelectedText().split('\n'))].join('\n'); - this.#instance.UI.searchTextFull(selected, SEARCH_OPTIONS); + this.#instance.UI.searchTextFull(selected, this.searchOptions); } #clearSearchResultsWhenVisibilityChanged() { @@ -267,7 +310,9 @@ export class PdfViewer { const inputElement = iframeWindow.document.getElementById('SearchPanel__input') as HTMLInputElement; - setTimeout(() => (inputElement.value = ''), 0); + if (inputElement) { + setTimeout(() => (inputElement.value = ''), 0); + } if (!event.detail.isVisible) { this.documentViewer.clearSearchResults(); @@ -275,19 +320,6 @@ export class PdfViewer { }); } - #listenForCommandF() { - this.#instance.UI.hotkeys.on('command+f, ctrl+f', e => { - e.preventDefault(); - if (!this.#isElementActive('searchPanel')) { - this.activateSearch(); - } - if (this.documentViewer.getSelectedText()) { - this.#searchForSelectedText(); - } - setTimeout(() => this.#focusSearch(), 250); - }); - } - #navigateTo(pageNumber: number) { if (this.#currentInternalPage !== pageNumber) { this.documentViewer.displayPageLocation(pageNumber, 0, 0); @@ -337,4 +369,9 @@ export class PdfViewer { input.select(); } } + + #focusViewer() { + this.instance.UI.iframeWindow.document.getElementById('SearchPanel__input').blur(); + this.instance.UI.iframeWindow.focus(); + } } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts b/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts index f6f552f57..f263448d5 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/utils/constants.ts @@ -19,15 +19,6 @@ export const ALLOWED_KEYBOARD_SHORTCUTS: List = ['+', '-', 'p', 'r', 'Escape'] a export const DOCUMENT_LOADING_ERROR = new CustomError(_('error.file-preview.label'), _('error.file-preview.action'), 'iqser:refresh'); -export const SEARCH_OPTIONS = { - caseSensitive: true, // match case - wholeWord: true, // match whole words only - wildcard: false, // allow using '*' as a wildcard value - regex: false, // string is treated as a regular expression - searchUp: false, // search from the end of the document upwards - ambientString: true, // return ambient string as part of the result -}; - export const ViewerEvents = { LOAD_ALL_ANNOTATIONS: 'LOAD_ALL_ANNOTATIONS', } as const;