RED-3837: finish select annotations on multiple pages
This commit is contained in:
parent
c1e3d342fa
commit
85f9cd85cf
@ -9,6 +9,7 @@ import {
|
||||
Debounce,
|
||||
ErrorService,
|
||||
FilterService,
|
||||
List,
|
||||
LoadingService,
|
||||
NestedFilter,
|
||||
OnAttach,
|
||||
@ -26,7 +27,7 @@ import { File, ViewMode, ViewModes } from '@red/domain';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { combineLatest, firstValueFrom, from, of, pairwise } from 'rxjs';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { download, handleFilterDelta } from '../../utils';
|
||||
import { byId, byPage, download, handleFilterDelta } from '../../utils';
|
||||
import { FilesService } from '@services/files/files.service';
|
||||
import { FileManagementService } from '@services/files/file-management.service';
|
||||
import { catchError, filter, map, startWith, switchMap, tap } from 'rxjs/operators';
|
||||
@ -361,8 +362,15 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return this.viewerReady();
|
||||
}),
|
||||
);
|
||||
|
||||
const currentPageAnnotations$ = combineLatest([this.pdf.currentPage$, this._fileDataService.annotations$]).pipe(
|
||||
map(([page, annotations]) => annotations.filter(annotation => annotation.pageNumber === page)),
|
||||
map(([, annotations]) => annotations),
|
||||
startWith([] as List<AnnotationWrapper>),
|
||||
pairwise(),
|
||||
map(([oldAnnotations, newAnnotations]) => {
|
||||
const page = this.pdf.currentPage;
|
||||
return [oldAnnotations.filter(byPage(page)), newAnnotations.filter(byPage(page))] as const;
|
||||
}),
|
||||
);
|
||||
|
||||
let start;
|
||||
@ -370,8 +378,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
filter(([, loaded]) => loaded),
|
||||
tap(() => (start = new Date().getTime())),
|
||||
map(([annotations]) => annotations),
|
||||
startWith([] as AnnotationWrapper[]),
|
||||
pairwise(),
|
||||
tap(annotations => this.deleteAnnotations(...annotations)),
|
||||
switchMap(annotations => this.drawChangedAnnotations(...annotations)),
|
||||
tap(([, newAnnotations]) => this.#highlightSelectedAnnotations(newAnnotations)),
|
||||
@ -381,28 +387,20 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
deleteAnnotations(oldAnnotations: AnnotationWrapper[], newAnnotations: AnnotationWrapper[]) {
|
||||
const annotationsToDelete = oldAnnotations.filter(
|
||||
oldAnnotation => !newAnnotations.some(newAnnotation => newAnnotation.id === oldAnnotation.id),
|
||||
);
|
||||
const annotationsToDelete = oldAnnotations.filter(oldAnnotation => !newAnnotations.some(byId(oldAnnotation.id)));
|
||||
|
||||
if (annotationsToDelete.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._logger.info('[ANNOTATIONS] To delete: ', annotationsToDelete);
|
||||
this._annotationManager.delete(annotationsToDelete);
|
||||
const toDelete = annotationsToDelete.filter(byPage(this.pdf.currentPage));
|
||||
|
||||
this._logger.info('[ANNOTATIONS] To delete: ', toDelete);
|
||||
this._annotationManager.delete(toDelete);
|
||||
}
|
||||
|
||||
async drawChangedAnnotations(oldAnnotations: AnnotationWrapper[], newAnnotations: AnnotationWrapper[]) {
|
||||
let annotationsToDraw: readonly AnnotationWrapper[];
|
||||
const annotations = this._annotationManager.annotations;
|
||||
const ann = annotations.map(a => oldAnnotations.some(oldAnnotation => oldAnnotation.id === a.Id));
|
||||
const hasAnnotations = ann.filter(a => !!a).length > 0;
|
||||
|
||||
if (hasAnnotations) {
|
||||
annotationsToDraw = this.#getAnnotationsToDraw(newAnnotations, oldAnnotations);
|
||||
} else {
|
||||
annotationsToDraw = newAnnotations;
|
||||
}
|
||||
const annotationsToDraw = this.#getAnnotationsToDraw(oldAnnotations, newAnnotations);
|
||||
|
||||
if (annotationsToDraw.length === 0) {
|
||||
return [oldAnnotations, newAnnotations];
|
||||
@ -423,6 +421,18 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return ActionsHelpModeKeys[type];
|
||||
}
|
||||
|
||||
#getAnnotationsToDraw(oldAnnotations: AnnotationWrapper[], newAnnotations: AnnotationWrapper[]) {
|
||||
const annotations = this._annotationManager.annotations;
|
||||
const ann = annotations.map(a => oldAnnotations.some(byId(a.Id)));
|
||||
const hasAnnotations = ann.filter(a => !!a).length > 0;
|
||||
|
||||
if (hasAnnotations) {
|
||||
return this.#findAnnotationsToDraw(newAnnotations, oldAnnotations);
|
||||
} else {
|
||||
return newAnnotations;
|
||||
}
|
||||
}
|
||||
|
||||
#rebuildFilters() {
|
||||
const startTime = new Date().getTime();
|
||||
|
||||
@ -457,7 +467,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
#getAnnotationsToDraw(newAnnotations: AnnotationWrapper[], oldAnnotations: AnnotationWrapper[]) {
|
||||
#findAnnotationsToDraw(newAnnotations: AnnotationWrapper[], oldAnnotations: AnnotationWrapper[]) {
|
||||
return newAnnotations.filter(newAnnotation => {
|
||||
const oldAnnotation = oldAnnotations.find(annotation => annotation.id === newAnnotation.id);
|
||||
if (!oldAnnotation) {
|
||||
|
||||
@ -26,19 +26,15 @@ export class AnnotationsListingService extends ListingService<AnnotationWrapper>
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
selectAnnotations(annotation: AnnotationWrapper);
|
||||
selectAnnotations(annotations?: AnnotationWrapper[]);
|
||||
selectAnnotations(annotations?: AnnotationWrapper[] | AnnotationWrapper) {
|
||||
if (!annotations) {
|
||||
return this._annotationManager.deselect();
|
||||
}
|
||||
selectAnnotations(annotations: AnnotationWrapper[] | AnnotationWrapper) {
|
||||
annotations = Array.isArray(annotations) ? annotations : [annotations];
|
||||
const pageNumber = annotations[annotations.length - 1].pageNumber;
|
||||
|
||||
const annotationsToSelect = this._multiSelectService.isActive ? [...this.selected, ...annotations] : annotations;
|
||||
this.#selectAnnotations(annotationsToSelect);
|
||||
this.#selectAnnotations(annotationsToSelect, pageNumber);
|
||||
}
|
||||
|
||||
#selectAnnotations(annotations: AnnotationWrapper[]) {
|
||||
#selectAnnotations(annotations: AnnotationWrapper[], pageNumber: number) {
|
||||
if (!annotations.length) {
|
||||
return;
|
||||
}
|
||||
@ -47,8 +43,6 @@ export class AnnotationsListingService extends ListingService<AnnotationWrapper>
|
||||
this._annotationManager.deselect();
|
||||
}
|
||||
|
||||
const pageNumber = annotations[0].pageNumber;
|
||||
|
||||
if (pageNumber === this._pdf.currentPage) {
|
||||
return this._annotationManager.jumpAndSelect(annotations);
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ import { shareDistinctLast } from '@iqser/common-ui';
|
||||
import { toPosition } from '../utils/pdf-calculation.utils';
|
||||
import { MultiSelectService } from './multi-select.service';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { filter, map, tap } from 'rxjs/operators';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { HeaderElements, TextPopups } from '../utils/constants';
|
||||
import { FileDataService } from './file-data.service';
|
||||
import { ViewerHeaderService } from '../../pdf-viewer/services/viewer-header.service';
|
||||
@ -89,7 +89,6 @@ export class PdfProxyService {
|
||||
|
||||
get #annotationSelected$() {
|
||||
return this._annotationManager.annotationSelected$.pipe(
|
||||
filter(([, action]) => !(this._multiSelectService.isActive && action === 'deselected')),
|
||||
map(value => this.#processSelectedAnnotations(...value)),
|
||||
tap(annotations => this.handleAnnotationSelected(annotations)),
|
||||
);
|
||||
|
||||
@ -6,6 +6,7 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { fromEvent, Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { asList, getId, isStringOrWrapper } from '../utils/functions';
|
||||
import { getLast } from '@utils/functions';
|
||||
import AnnotationManager = Core.AnnotationManager;
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
@ -79,7 +80,7 @@ export class REDAnnotationManager {
|
||||
jumpAndSelect(annotations: List | List<AnnotationWrapper>) {
|
||||
const annotationsFromViewer = this.get(annotations);
|
||||
|
||||
this.#manager.jumpToAnnotation(annotationsFromViewer[0]);
|
||||
this.#manager.jumpToAnnotation(getLast(annotationsFromViewer));
|
||||
this.#manager.selectAnnotations(annotationsFromViewer);
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import { File, IHeaderElement } from '@red/domain';
|
||||
import { ErrorService, shareDistinctLast } from '@iqser/common-ui';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { BehaviorSubject, combineLatest, fromEvent, Observable } from 'rxjs';
|
||||
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';
|
||||
@ -70,8 +70,9 @@ export class PdfViewer {
|
||||
|
||||
get pageCount() {
|
||||
try {
|
||||
return this.#instance.Core.documentViewer.getPageCount();
|
||||
} catch {
|
||||
return this.documentViewer.getPageCount();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
// might throw Error: getPageCount was called before the 'documentLoaded' event
|
||||
return 1;
|
||||
}
|
||||
@ -83,7 +84,8 @@ export class PdfViewer {
|
||||
|
||||
get #totalPages$() {
|
||||
const layoutChanged$ = fromEvent(this.documentViewer, 'layoutChanged').pipe(startWith(''));
|
||||
const pageCount$ = layoutChanged$.pipe(map(() => this.pageCount));
|
||||
const docLoaded$ = fromEvent(this.documentViewer, 'documentLoaded');
|
||||
const pageCount$ = docLoaded$.pipe(switchMap(() => layoutChanged$.pipe(map(() => this.pageCount))));
|
||||
const docChanged$ = combineLatest([pageCount$, this.compareMode$]);
|
||||
|
||||
return docChanged$.pipe(map(([pageCount]) => this.#adjustPage(pageCount)));
|
||||
@ -99,10 +101,7 @@ export class PdfViewer {
|
||||
|
||||
get #pageChanged$() {
|
||||
const page$ = fromEvent<number>(this.documentViewer, 'pageNumberUpdated');
|
||||
return page$.pipe(
|
||||
// tap(() => this._annotationManager.deselect()),
|
||||
map(page => this.#adjustPage(page)),
|
||||
);
|
||||
return page$.pipe(map(page => this.#adjustPage(page)));
|
||||
}
|
||||
|
||||
navigateTo(page: string | number) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { List } from '@iqser/common-ui';
|
||||
import type { List } from '@iqser/common-ui';
|
||||
import type { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
|
||||
export function groupBy(xs: List<unknown>, key: string) {
|
||||
return xs.reduce((rv, x) => {
|
||||
@ -92,3 +93,10 @@ export function compareLists(l1: string[], l2: string[]) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export const byPage = (page: number) => (annotation: AnnotationWrapper) => annotation.pageNumber === page;
|
||||
export const byId = (id: string) => (annotation: AnnotationWrapper) => annotation.annotationId === id;
|
||||
|
||||
export function getLast<T>(list: List<T>) {
|
||||
return list[list.length - 1];
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user