RED-10144: fixed multi-selection randomly activating.

This commit is contained in:
Nicoleta Panaghiu 2024-10-09 16:54:38 +03:00
parent 428f1dd5fb
commit 4526138fae
3 changed files with 30 additions and 24 deletions

View File

@ -58,6 +58,7 @@ import { PageExclusionComponent } from '../page-exclusion/page-exclusion.compone
import { PagesComponent } from '../pages/pages.component'; import { PagesComponent } from '../pages/pages.component';
import { ReadonlyBannerComponent } from '../readonly-banner/readonly-banner.component'; import { ReadonlyBannerComponent } from '../readonly-banner/readonly-banner.component';
import { DocumentInfoComponent } from '../document-info/document-info.component'; import { DocumentInfoComponent } from '../document-info/document-info.component';
import { getLast } from '@utils/functions';
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape']; const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
@ -348,6 +349,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
this.pdf.navigateTo(this.#nextPageWithAnnotations()); this.pdf.navigateTo(this.#nextPageWithAnnotations());
} }
@Debounce(15)
navigateAnnotations($event: KeyboardEvent) { navigateAnnotations($event: KeyboardEvent) {
const currentPage = untracked(this.pdf.currentPage); const currentPage = untracked(this.pdf.currentPage);
const activeAnnotations = untracked(this.activeAnnotations); const activeAnnotations = untracked(this.activeAnnotations);
@ -366,7 +368,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
const prevPage = this.#prevPageWithAnnotations(); const prevPage = this.#prevPageWithAnnotations();
const prevPageAnnotations = this.displayedAnnotations.get(prevPage); const prevPageAnnotations = this.displayedAnnotations.get(prevPage);
return this.listingService.selectAnnotations(prevPageAnnotations[prevPageAnnotations.length - 1]); return this.listingService.selectAnnotations(getLast(prevPageAnnotations));
} }
const page = this._firstSelectedAnnotation.pageNumber; const page = this._firstSelectedAnnotation.pageNumber;
@ -403,7 +405,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
for (let i = previousPageIdx; i >= 0; i--) { for (let i = previousPageIdx; i >= 0; i--) {
const prevPageAnnotations = this.displayedAnnotations.get(this.displayedPages[i]); const prevPageAnnotations = this.displayedAnnotations.get(this.displayedPages[i]);
if (prevPageAnnotations) { if (prevPageAnnotations) {
this.listingService.selectAnnotations(prevPageAnnotations[prevPageAnnotations.length - 1]); this.listingService.selectAnnotations(getLast(prevPageAnnotations));
break; break;
} }
} }

View File

@ -1,17 +1,16 @@
import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { Injectable, OnDestroy } from '@angular/core'; import { effect, Injectable, untracked } from '@angular/core';
import { EntitiesService, ListingService, SearchService } from '@iqser/common-ui'; import { EntitiesService, ListingService, SearchService } from '@iqser/common-ui';
import { filter, tap } from 'rxjs/operators';
import { MultiSelectService } from './multi-select.service'; import { MultiSelectService } from './multi-select.service';
import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service'; import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service';
import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service'; import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service';
import { Subscription } from 'rxjs';
import { FilterService } from '@iqser/common-ui/lib/filtering'; import { FilterService } from '@iqser/common-ui/lib/filtering';
import { SortingService } from '@iqser/common-ui/lib/sorting'; import { SortingService } from '@iqser/common-ui/lib/sorting';
import { toSignal } from '@angular/core/rxjs-interop';
@Injectable() @Injectable()
export class AnnotationsListingService extends ListingService<AnnotationWrapper> implements OnDestroy { export class AnnotationsListingService extends ListingService<AnnotationWrapper> {
readonly #subscriptions: Subscription; readonly selectedLength = toSignal(this.selectedLength$);
constructor( constructor(
protected readonly _filterService: FilterService, protected readonly _filterService: FilterService,
@ -24,23 +23,22 @@ export class AnnotationsListingService extends ListingService<AnnotationWrapper>
) { ) {
super(_filterService, _searchService, _entitiesService, _sortingService); super(_filterService, _searchService, _entitiesService, _sortingService);
this.#subscriptions = this.selectedLength$ effect(
.pipe( () => {
filter(length => length > 1), if (this.selectedLength() > 1) {
tap(() => this._multiSelectService.activate()), this._multiSelectService.activate();
)
.subscribe();
} }
},
ngOnDestroy() { { allowSignalWrites: true },
this.#subscriptions.unsubscribe(); );
} }
selectAnnotations(annotations: AnnotationWrapper[] | AnnotationWrapper) { selectAnnotations(annotations: AnnotationWrapper[] | AnnotationWrapper) {
annotations = Array.isArray(annotations) ? annotations : [annotations]; annotations = Array.isArray(annotations) ? annotations : [annotations];
const pageNumber = annotations[annotations.length - 1].pageNumber; const pageNumber = annotations[annotations.length - 1].pageNumber;
const annotationsToSelect = this._multiSelectService.active() ? [...this.selected, ...annotations] : annotations; const multiSelectActive = untracked(this._multiSelectService.active);
const annotationsToSelect = multiSelectActive ? [...this.selected, ...annotations] : annotations;
this.#selectAnnotations(annotationsToSelect, pageNumber); this.#selectAnnotations(annotationsToSelect, pageNumber);
} }
@ -49,16 +47,18 @@ export class AnnotationsListingService extends ListingService<AnnotationWrapper>
return; return;
} }
if (this._multiSelectService.inactive()) { const multiSelectInactive = untracked(this._multiSelectService.inactive);
if (multiSelectInactive) {
this._annotationManager.deselect(); this._annotationManager.deselect();
} }
if (pageNumber === this._pdf.currentPage()) { const currentPage = untracked(this._pdf.currentPage);
if (pageNumber === currentPage) {
return this._annotationManager.jumpAndSelect(annotations); return this._annotationManager.jumpAndSelect(annotations);
} }
this._pdf.navigateTo(pageNumber); this._pdf.navigateTo(pageNumber);
// wait for page to be loaded and to draw annotations // wait for page to be loaded and to draw annotations
setTimeout(() => this._annotationManager.jumpAndSelect(annotations), 300); setTimeout(() => this._annotationManager.jumpAndSelect(annotations), 10);
} }
} }

View File

@ -1,4 +1,4 @@
import { computed, Injectable, Signal, signal } from '@angular/core'; import { computed, Injectable, Signal, signal, untracked } from '@angular/core';
import { ViewModeService } from './view-mode.service'; import { ViewModeService } from './view-mode.service';
import { FilePreviewStateService } from './file-preview-state.service'; import { FilePreviewStateService } from './file-preview-state.service';
import { ViewMode, ViewModes } from '@red/domain'; import { ViewMode, ViewModes } from '@red/domain';
@ -13,13 +13,17 @@ export class MultiSelectService {
readonly #active = signal(false); readonly #active = signal(false);
constructor(protected readonly _viewModeService: ViewModeService, protected readonly _state: FilePreviewStateService) { constructor(
protected readonly _viewModeService: ViewModeService,
protected readonly _state: FilePreviewStateService,
) {
this.active = this.#active.asReadonly(); this.active = this.#active.asReadonly();
this.inactive = computed(() => !this.#active()); this.inactive = computed(() => !this.#active());
} }
activate() { activate() {
if (this.enabled()) { const enabled = untracked(this.enabled);
if (enabled) {
this.#active.set(true); this.#active.set(true);
} }
} }