From c0edce517a873985a3c73431feb483906666241d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 23 Oct 2020 20:59:40 +0300 Subject: [PATCH] Working arrow navigation --- .../base-screen/base-screen.component.scss | 25 ++++ .../file-preview-screen.component.html | 4 +- .../file-preview-screen.component.scss | 4 + .../file-preview-screen.component.ts | 119 ++++++++++++++---- .../src/assets/styles/red-page-layout.scss | 22 ---- 5 files changed, 129 insertions(+), 45 deletions(-) diff --git a/apps/red-ui/src/app/screens/base-screen/base-screen.component.scss b/apps/red-ui/src/app/screens/base-screen/base-screen.component.scss index e69de29bb..647662bef 100644 --- a/apps/red-ui/src/app/screens/base-screen/base-screen.component.scss +++ b/apps/red-ui/src/app/screens/base-screen/base-screen.component.scss @@ -0,0 +1,25 @@ +@import "../../../assets/styles/red-variables"; +@import "../../../assets/styles/red-mixins"; + +.breadcrumbs-container { + display: flex; + gap: 8px; + + .breadcrumb { + text-decoration: none; + color: $accent; + font-weight: 600; + width: fit-content; + white-space: nowrap; + + &:last-child { + color: $primary; + @include line-clamp(1); + } + + .mat-icon { + vertical-align: middle; + width: 6px; + } + } +} diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html index 432656490..1c391c203 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html @@ -126,7 +126,7 @@
-
+
-
+
{{page}} diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss index 5c054bb30..f2701b6c9 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss @@ -69,6 +69,10 @@ redaction-pdf-viewer { width: 0; background: transparent; /* Chrome/Safari/Webkit */ } + + &.activePanel { + background-color: #FAFAFA; + } } .pages { diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts index 6bd5c696c..5e23a6307 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts @@ -1,19 +1,19 @@ -import {ChangeDetectorRef, Component, ElementRef, HostListener, NgZone, OnInit, ViewChild} from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; -import {ManualRedactionEntry, ReanalysisControllerService} from '@redaction/red-ui-http'; -import {AppStateService} from '../../../state/app-state.service'; -import {Annotations, WebViewerInstance} from '@pdftron/webviewer'; -import {PdfViewerComponent} from '../pdf-viewer/pdf-viewer.component'; -import {AnnotationUtils} from '../../../utils/annotation-utils'; -import {UserService} from '../../../user/user.service'; -import {debounce} from '../../../utils/debounce'; +import { ChangeDetectorRef, Component, ElementRef, HostListener, NgZone, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { ManualRedactionEntry, ReanalysisControllerService } from '@redaction/red-ui-http'; +import { AppStateService } from '../../../state/app-state.service'; +import { Annotations, WebViewerInstance } from '@pdftron/webviewer'; +import { PdfViewerComponent } from '../pdf-viewer/pdf-viewer.component'; +import { AnnotationUtils } from '../../../utils/annotation-utils'; +import { UserService } from '../../../user/user.service'; +import { debounce } from '../../../utils/debounce'; import scrollIntoView from 'scroll-into-view-if-needed'; -import {AnnotationFilters} from '../../../utils/types'; -import {FiltersService} from '../service/filters.service'; -import {FileDownloadService} from '../service/file-download.service'; -import {saveAs} from 'file-saver'; -import {FileType} from '../model/file-type'; -import {DialogService} from '../../../dialogs/dialog.service'; +import { AnnotationFilters } from '../../../utils/types'; +import { FiltersService } from '../service/filters.service'; +import { FileDownloadService } from '../service/file-download.service'; +import { saveAs } from 'file-saver'; +import { FileType } from '../model/file-type'; +import { DialogService } from '../../../dialogs/dialog.service'; @Component({ selector: 'redaction-file-preview-screen', @@ -37,6 +37,7 @@ export class FilePreviewScreenComponent implements OnInit { public selectedAnnotation: Annotations.Annotation; public filters: AnnotationFilters; public expandedFilters: AnnotationFilters = {hint: false}; + public pagesPanelActive = false; private instance: WebViewerInstance; constructor( @@ -167,7 +168,6 @@ export class FilePreviewScreenComponent implements OnInit { } - get activeViewerPage() { return this.instance.docViewer.getCurrentPage(); } @@ -274,8 +274,35 @@ export class FilePreviewScreenComponent implements OnInit { handleKeyEvent($event: KeyboardEvent) { $event.preventDefault(); - if (!this.selectedAnnotation) { - this.selectAnnotation(this.displayedAnnotations[this.displayedPages[0]].annotations[0]); + if ($event.key === 'ArrowLeft' || $event.key === 'ArrowRight') { + this.pagesPanelActive = !this.pagesPanelActive; + this._changeDetectorRef.detectChanges(); + return; + } + + if (!this.pagesPanelActive) { + this._navigateAnnotations($event); + } else { + this._navigatePages($event); + } + } + + private _navigateAnnotations($event: KeyboardEvent) { + if (!this.selectedAnnotation || this.activeViewerPage !== this.selectedAnnotation.getPageNumber()) { + const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); + if (pageIdx !== -1) { // Displayed page has annotations + this.selectAnnotation(this.displayedAnnotations[this.activeViewerPage].annotations[0]); + } else { // Displayed page doesn't have annotations + if ($event.key === 'ArrowDown') { + const nextPage = this._nextPageWithAnnotations(); + this.selectAnnotation(this.displayedAnnotations[nextPage].annotations[0]); + } else { + const prevPage = this._prevPageWithAnnotations(); + const prevPageAnnotations = this.displayedAnnotations[prevPage].annotations; + this.selectAnnotation(prevPageAnnotations[prevPageAnnotations.length - 1]); + } + } + } else { const page = this.selectedAnnotation.getPageNumber(); const pageIdx = this.displayedPages.indexOf(page); @@ -289,9 +316,7 @@ export class FilePreviewScreenComponent implements OnInit { const nextPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx + 1]].annotations; this.selectAnnotation(nextPageAnnotations[0]); } - } - - if ($event.key === 'ArrowUp') { + } else { if (idx !== 0) { // If not first item in page this.selectAnnotation(annotationsOnPage[idx - 1]); } else if (pageIdx) { // If not first page @@ -302,6 +327,58 @@ export class FilePreviewScreenComponent implements OnInit { } } + private _navigatePages($event: KeyboardEvent) { + const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); + + if ($event.key === 'ArrowDown') { + if (pageIdx !== -1) { // If active page has annotations + if (pageIdx !== this.displayedPages.length - 1) { + this.selectPage(this.displayedPages[pageIdx + 1]); + } + } else { // If active page doesn't have annotations + const nextPage = this._nextPageWithAnnotations(); + if (nextPage) { + this.selectPage(nextPage); + } + } + } else { + if (pageIdx !== -1) { // If active page has annotations + if (pageIdx !== 0) { + this.selectPage(this.displayedPages[pageIdx - 1]); + } + } else { // If active page doesn't have annotations + const prevPage = this._prevPageWithAnnotations(); + if (prevPage) { + this.selectPage(prevPage); + } + } + } + } + + private _nextPageWithAnnotations() { + let idx = 0; + for (const page of this.displayedPages) { + if (page > this.activeViewerPage) { + break; + } + ++idx; + } + return idx < this.displayedPages.length ? this.displayedPages[idx] : null; + } + + private _prevPageWithAnnotations() { + let idx = this.displayedPages.length - 1; + for (const page of this.displayedPages.reverse()) { + if (page < this.activeViewerPage) { + this.selectPage(this.displayedPages[idx]); + this._scrollAnnotations(); + break; + } + --idx; + } + return idx >= 0 ? this.displayedPages[idx] : null; + } + viewerPageChanged($event: number) { this._scrollViews(); this._changeDetectorRef.detectChanges(); diff --git a/apps/red-ui/src/assets/styles/red-page-layout.scss b/apps/red-ui/src/assets/styles/red-page-layout.scss index e003252a3..93dd96f44 100644 --- a/apps/red-ui/src/assets/styles/red-page-layout.scss +++ b/apps/red-ui/src/assets/styles/red-page-layout.scss @@ -1,5 +1,4 @@ @import "red-variables"; -@import "red-mixins"; html, body { margin: 0; @@ -172,27 +171,6 @@ html, body { } } - .breadcrumbs-container { - display: flex; - gap: 8px; - - .breadcrumb { - text-decoration: none; - color: $accent; - font-weight: 600; - - &:last-child { - color: $primary; - @include line-clamp(1); - } - - .mat-icon { - vertical-align: middle; - width: 6px; - } - } - } - .divider { height: 1px; opacity: 0.15;