RED-3858 - Incorrect annotations sort in workload on landscape pages

This commit is contained in:
Valentin Mihai 2023-04-13 22:42:35 +03:00
parent 498dd84ddd
commit 0914f96322
5 changed files with 88 additions and 12 deletions

View File

@ -32,6 +32,7 @@ import { AnnotationsListingService } from '../../services/annotations-listing.se
import { REDDocumentViewer } from '../../../pdf-viewer/services/document-viewer.service';
import { SuggestionsService } from '../../services/suggestions.service';
import { ListItem } from '@models/file/list-item';
import { PageRotationService } from '../../../pdf-viewer/services/page-rotation.service';
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
@ -76,6 +77,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
private readonly _annotationProcessingService: AnnotationProcessingService,
private readonly _viewModeService: ViewModeService,
private readonly _suggestionsService: SuggestionsService,
private readonly _pageRotationService: PageRotationService,
) {
super();
@ -160,6 +162,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
secondary$,
this.listingService.selected$,
this.multiSelectService.active$,
this._pageRotationService.rotations$,
]).pipe(
delay(0),
map(([annotations, primary, secondary]) => this._filterAnnotations(annotations, primary, secondary)),

View File

@ -10,6 +10,13 @@ import { DefaultColorsService } from '@services/entity-services/default-colors.s
import { of } from 'rxjs';
import { ViewedPagesMapService } from '@services/files/viewed-pages-map.service';
import { FileDataService } from './file-data.service';
import { PageRotationService } from '../../pdf-viewer/services/page-rotation.service';
import {
sortBottomLeftToTopRight,
sortBottomRightToTopLeft,
sortTopLeftToBottomRight,
sortTopRightToBottomLeft,
} from '../utils/sort-by-page-rotation.utils';
@Injectable()
export class AnnotationProcessingService {
@ -18,6 +25,7 @@ export class AnnotationProcessingService {
private readonly _fileDataService: FileDataService,
private readonly _state: FilePreviewStateService,
private readonly _defaultColorsService: DefaultColorsService,
private readonly _pageRotationService: PageRotationService,
) {}
get secondaryAnnotationFilters(): INestedFilter[] {
@ -155,7 +163,7 @@ export class AnnotationProcessingService {
obj.forEach((values, page) => {
if (!values[0].isEarmark) {
obj.set(page, this._sortAnnotations(values));
obj.set(page, this.#sortAnnotations(values));
}
});
@ -223,18 +231,24 @@ export class AnnotationProcessingService {
private _checkByFilterKey = (filter: NestedFilter | IFilter, annotation: AnnotationWrapper) => filter.id === annotation.filterKey;
private _sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] {
#sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] {
const pageRotation = this._pageRotationService.currentPageRotation;
return annotations.sort((first, second) => {
if (first.pageNumber === second.pageNumber) {
if (first.y > second.y) {
return -1;
switch (pageRotation) {
case 0: {
return sortTopLeftToBottomRight(first, second);
}
case 90: {
return sortBottomLeftToTopRight(first, second);
}
case 180: {
return sortBottomRightToTopLeft(first, second);
}
case 270: {
return sortTopRightToBottomLeft(first, second);
}
}
if (first.y < second.y) {
return 1;
}
return first.x < second.x ? -1 : 1;
}
return first.pageNumber < second.pageNumber ? -1 : 1;
});

View File

@ -0,0 +1,41 @@
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
export const sortTopLeftToBottomRight = (a1: AnnotationWrapper, a2: AnnotationWrapper): number => {
if (a1.y > a2.y) {
return -1;
}
if (a1.y < a2.y) {
return 1;
}
return a1.x < a2.x ? -1 : 1;
};
export const sortBottomLeftToTopRight = (a1: AnnotationWrapper, a2: AnnotationWrapper): number => {
if (a1.x < a2.x) {
return -1;
}
if (a1.x > a2.x) {
return 1;
}
return a1.y < a2.y ? -1 : 1;
};
export const sortBottomRightToTopLeft = (a1: AnnotationWrapper, a2: AnnotationWrapper): number => {
if (a1.y < a2.y) {
return -1;
}
if (a1.y > a2.y) {
return 1;
}
return a1.x > a2.x ? -1 : 1;
};
export const sortTopRightToBottomLeft = (a1: AnnotationWrapper, a2: AnnotationWrapper): number => {
if (a1.x > a2.x) {
return -1;
}
if (a1.x < a2.x) {
return 1;
}
return a1.y > a2.y ? -1 : 1;
};

View File

@ -60,6 +60,10 @@ export class REDDocumentViewer {
);
}
get currentPageRotation() {
return this.document?.getPageRotation(this.#document.getCurrentPage());
}
get #keyUp$() {
return fromEvent<KeyboardEvent>(this.#document, 'keyUp').pipe(
tap(stopAndPreventIfNotAllowed),

View File

@ -1,5 +1,5 @@
import { Injectable, Injector } from '@angular/core';
import { BehaviorSubject, firstValueFrom, of } from 'rxjs';
import { BehaviorSubject, firstValueFrom, Observable, of } from 'rxjs';
import { RotationType } from '@red/domain';
import { FileManagementService } from '@services/files/file-management.service';
import { distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
@ -22,6 +22,7 @@ import { REDDocumentViewer } from './document-viewer.service';
@Injectable()
export class PageRotationService {
readonly #rotations$ = new BehaviorSubject<Record<number, number>>({});
readonly rotations$: Observable<Record<number, number>>;
constructor(
private readonly _pdf: PdfViewer,
@ -32,12 +33,21 @@ export class PageRotationService {
private readonly _filesService: FilesService,
private readonly _filesMapService: FilesMapService,
private readonly _documentViewer: REDDocumentViewer,
) {}
) {
this.rotations$ = this.#rotations$.asObservable();
}
get hasRotations() {
return Object.values(this.#rotations$.value).filter(v => !!v).length > 0;
}
get currentPageRotation() {
const savedRotation = this._documentViewer.currentPageRotation;
const currentRotation = this.#rotations[this._pdf.currentPage] ?? 0;
const rotationsSum = savedRotation + currentRotation;
return Math.abs(rotationsSum < 360 ? rotationsSum : 360 - rotationsSum);
}
isRotated$(page: number) {
return this.#rotations$.pipe(
map(rotations => !!rotations[page]),
@ -91,6 +101,10 @@ export class PageRotationService {
return this.hasRotations ? this.#showConfirmationDialog() : of(false);
}
get #rotations() {
return this.#rotations$.value;
}
#showConfirmationDialog() {
const ref = this._injector.get(MatDialog).open(ConfirmationDialogComponent, {
...defaultDialogConfig,