RED-6829: run in ng zone

This commit is contained in:
Dan Percic 2023-06-11 02:06:18 +03:00
parent e89d317fa0
commit f3e7811523
7 changed files with 53 additions and 61 deletions

View File

@ -134,7 +134,7 @@
<iqser-circle-button
(action)="hideAnnotation()"
*ngIf="isImage && (isVisible$ | async)"
*ngIf="isImage && isVisible()"
[tooltipPosition]="tooltipPosition"
[tooltip]="'annotation-actions.hide' | translate"
[type]="buttonType"
@ -143,7 +143,7 @@
<iqser-circle-button
(action)="showAnnotation()"
*ngIf="isImage && (isVisible$ | async) === false"
*ngIf="isImage && !isVisible()"
[tooltipPosition]="tooltipPosition"
[tooltip]="'annotation-actions.show' | translate"
[type]="buttonType"

View File

@ -1,4 +1,4 @@
import { Component, Input, OnChanges } from '@angular/core';
import { Component, computed, Input, OnChanges } from '@angular/core';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { PermissionsService } from '@services/permissions.service';
import { AnnotationPermissions } from '@models/file/annotation.permissions';
@ -6,11 +6,10 @@ import { AnnotationActionsService } from '../../services/annotation-actions.serv
import { AnnotationReferencesService } from '../../services/annotation-references.service';
import { MultiSelectService } from '../../services/multi-select.service';
import { FilePreviewStateService } from '../../services/file-preview-state.service';
import { HelpModeService, IqserPermissionsService, shareLast } from '@iqser/common-ui';
import { HelpModeService, IqserPermissionsService } from '@iqser/common-ui';
import { ViewModeService } from '../../services/view-mode.service';
import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service';
import { Roles } from '@users/roles';
import { map } from 'rxjs';
export const AnnotationButtonTypes = {
dark: 'dark',
@ -34,11 +33,11 @@ export class AnnotationActionsComponent implements OnChanges {
annotationPermissions: AnnotationPermissions;
isImage = true;
protected _annotationId = '';
#annotations: AnnotationWrapper[];
readonly isVisible$ = this._annotationManager.hidden$.pipe(
map(hidden => this.#annotations.reduce((acc, annotation) => !hidden.has(annotation.id) && acc, true)),
shareLast(),
);
#annotations: AnnotationWrapper[] = [];
readonly isVisible = computed(() => {
const hidden = this._annotationManager.hidden();
return this.#annotations.reduce((acc, annotation) => !hidden.has(annotation.id) && acc, true);
});
constructor(
readonly viewModeService: ViewModeService,

View File

@ -14,7 +14,7 @@ import {
IqserEventTarget,
} from '@iqser/common-ui';
import { combineLatest, delay, Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { ExcludedPagesService } from '../../services/excluded-pages.service';
import { MultiSelectService } from '../../services/multi-select.service';
import { DocumentInfoService } from '../../services/document-info.service';
@ -137,7 +137,6 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
delay(0),
map(([annotations, primary, secondary]) => this._filterAnnotations(annotations, primary, secondary)),
map(annotations => this._mapListItemsFromAnnotationWrapperArray(annotations)),
tap(() => setTimeout(() => this._changeDetectorRef.detectChanges())),
);
}

View File

@ -97,14 +97,13 @@ export class PdfProxyService {
get #annotationSelected$() {
return this._annotationManager.annotationSelected$.pipe(
map(value => this.#processSelectedAnnotations(...value)),
tap(annotations => this.handleAnnotationSelected(annotations)),
map(value => this._ngZone.run(() => this.#processSelectedAnnotations(...value))),
tap(annotations => this._ngZone.run(() => this.handleAnnotationSelected(annotations))),
);
}
handleAnnotationSelected(annotationIds: string[]) {
this._listingService.setSelected(annotationIds.map(id => this._fileDataService.find(id)).filter(ann => ann !== undefined));
this._changeDetectorRef.markForCheck();
}
configureElements() {
@ -120,7 +119,7 @@ export class PdfProxyService {
dataElement: TextPopups.ADD_RECTANGLE,
img: this.#addRedactionIcon,
title: this.#getTitle(ManualRedactionEntryTypes.REDACTION),
onClick: () => this._addRectangleManualRedaction(),
onClick: () => this._ngZone.run(() => this._addRectangleManualRedaction()),
};
this._pdf.instance.UI.annotationPopup.add([addRectangleButton]);
@ -153,7 +152,7 @@ export class PdfProxyService {
dataElement: TextPopups.ADD_FALSE_POSITIVE,
img: this.#falsePositiveIcon,
title: this.#getTitle(ManualRedactionEntryTypes.FALSE_POSITIVE),
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.FALSE_POSITIVE),
onClick: () => this._ngZone.run(() => this._addManualRedactionOfType(ManualRedactionEntryTypes.FALSE_POSITIVE)),
});
}
@ -163,7 +162,7 @@ export class PdfProxyService {
dataElement: TextPopups.ADD_REDACTION,
img: this.#addRedactionIcon,
title: this.#getTitle(ManualRedactionEntryTypes.REDACTION),
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.REDACTION),
onClick: () => this._ngZone.run(() => this._addManualRedactionOfType(ManualRedactionEntryTypes.REDACTION)),
});
if (!this._iqserPermissionsService.has(Roles.getRss)) {
@ -172,7 +171,7 @@ export class PdfProxyService {
dataElement: TextPopups.ADD_DICTIONARY,
img: this.#addDictIcon,
title: this.#getTitle(ManualRedactionEntryTypes.DICTIONARY),
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.DICTIONARY),
onClick: () => this._ngZone.run(() => this._addManualRedactionOfType(ManualRedactionEntryTypes.DICTIONARY)),
});
}
}

View File

@ -1,9 +1,9 @@
import { Injectable } from '@angular/core';
import { Injectable, signal } from '@angular/core';
import { Core } from '@pdftron/webviewer';
import type { List } from '@iqser/common-ui';
import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { BehaviorSubject, fromEvent, Observable } from 'rxjs';
import { fromEvent, Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { asList, getId, isStringOrWrapper } from '../utils/functions';
import { getLast } from '@utils/functions';
@ -15,8 +15,8 @@ import Annotation = Core.Annotations.Annotation;
export class REDAnnotationManager {
annotationSelected$: Observable<[Annotation[], string]>;
resizingAnnotationId?: string = undefined;
readonly #hidden$ = new BehaviorSubject<Set<string>>(new Set<string>());
readonly hidden$ = this.#hidden$.asObservable();
readonly #hidden = signal(new Set<string>());
readonly hidden = this.#hidden.asReadonly();
#manager: AnnotationManager;
@ -28,21 +28,17 @@ export class REDAnnotationManager {
return this.#get();
}
get hidden() {
return this.#hidden$.value;
}
get #annotationSelected$() {
const onSelect$ = fromEvent<[Annotation[], string]>(this.#manager, 'annotationSelected');
return onSelect$.pipe(tap(value => console.log('Annotation selected: ', value)));
}
addToHidden(value: string) {
this.#hidden$.next(new Set([...this.hidden, value]));
this.#hidden.mutate(set => set.add(value));
}
removeFromHidden(value: string) {
this.#hidden$.next(new Set([...this.hidden].filter(v => v !== value)));
this.#hidden.mutate(set => set.delete(value));
}
init(annotationManager: AnnotationManager) {
@ -52,7 +48,7 @@ export class REDAnnotationManager {
}
isHidden(annotationId: string) {
return this.hidden.has(annotationId);
return this.hidden().has(annotationId);
}
delete(annotations?: List | List<AnnotationWrapper> | string | AnnotationWrapper) {
@ -122,7 +118,7 @@ export class REDAnnotationManager {
}
showHidden() {
const hidden = this.#getByIds([...this.hidden.values()]);
const hidden = this.#getByIds([...this.hidden().values()]);
this.show(hidden);
}

View File

@ -84,7 +84,6 @@ export class PageRotationService {
const rotationValue = pageRotation ? (pageRotation + Number(rotation)) % 360 : rotation;
this.#rotations.update(value => ({ ...value, [pageNumber]: rotationValue }));
this._documentViewer.rotate(rotation);
}

View File

@ -1,4 +1,4 @@
import { inject, Injectable } from '@angular/core';
import { inject, Injectable, NgZone } from '@angular/core';
import { IHeaderElement, RotationTypes } from '@red/domain';
import { HeaderElements, HeaderElementType } from '../../file-preview/utils/constants';
import { TranslateService } from '@ngx-translate/core';
@ -9,7 +9,6 @@ import { PdfViewer } from './pdf-viewer.service';
import { ROTATION_ACTION_BUTTONS, ROTATION_BUTTONS, ViewerEvents } from '../utils/constants';
import { FilesMapService } from '@services/files/files-map.service';
import { REDDocumentViewer } from './document-viewer.service';
import { UserPreferenceService } from '@users/user-preference.service';
import { fromEvent, Observable, Subject } from 'rxjs';
import { ViewerEvent, VisibilityChangedEvent } from '../utils/types';
import { ReadableRedactionsService } from './readable-redactions.service';
@ -48,7 +47,7 @@ export class ViewerHeaderService {
private readonly _rotationService: PageRotationService,
private readonly _tooltipsService: TooltipsService,
private readonly _readableRedactionsService: ReadableRedactionsService,
private readonly _userPreferenceService: UserPreferenceService,
private readonly _ngZone: NgZone,
) {
this.events$ = this.#events$.asObservable();
}
@ -70,9 +69,7 @@ export class ViewerHeaderService {
dataElement: HeaderElements.TOGGLE_TOOLTIPS,
title: this._tooltipsService.toggleTooltipsBtnTitle,
img: this._tooltipsService.toggleTooltipsBtnIcon,
onClick: async () => {
await this._tooltipsService.toggleTooltips();
},
onClick: () => this._ngZone.run(() => this._tooltipsService.toggleTooltips()),
};
}
@ -83,9 +80,7 @@ export class ViewerHeaderService {
dataElement: HeaderElements.TOGGLE_READABLE_REDACTIONS,
title: this._readableRedactionsService.toggleReadableRedactionsBtnTitle,
img: this._readableRedactionsService.toggleReadableRedactionsBtnIcon,
onClick: () => {
this._readableRedactionsService.toggleReadableRedactions();
},
onClick: () => this._ngZone.run(() => this._readableRedactionsService.toggleReadableRedactions()),
};
}
@ -94,7 +89,7 @@ export class ViewerHeaderService {
type: 'actionButton',
title: this._translateService.instant('viewer-header.load-all-annotations'),
img: this._convertPath('/assets/icons/general/pdftron-action-load-all-annotations.svg'),
onClick: () => this.#events$.next({ type: ViewerEvents.LOAD_ALL_ANNOTATIONS }),
onClick: () => this._ngZone.run(() => this.#events$.next({ type: ViewerEvents.LOAD_ALL_ANNOTATIONS })),
dataElement: HeaderElements.LOAD_ALL_ANNOTATIONS,
};
}
@ -106,7 +101,7 @@ export class ViewerHeaderService {
dataElement: HeaderElements.CLOSE_COMPARE_BUTTON,
img: this._convertPath('/assets/icons/general/pdftron-action-close-compare.svg'),
title: 'Leave Compare Mode',
onClick: () => this._closeCompareMode(),
onClick: () => this._ngZone.run(() => this._closeCompareMode()),
};
}
@ -117,10 +112,11 @@ export class ViewerHeaderService {
dataElement: HeaderElements.ROTATE_LEFT_BUTTON,
img: this._convertPath('/assets/icons/general/rotate-left.svg'),
title: 'Rotate page left',
onClick: () => {
this._rotationService.addRotation(RotationTypes.LEFT);
this.#toggleRotationActionButtons();
},
onClick: () =>
this._ngZone.run(() => {
this._rotationService.addRotation(RotationTypes.LEFT);
this.#toggleRotationActionButtons();
}),
};
}
@ -138,10 +134,12 @@ export class ViewerHeaderService {
cursor: pointer;
margin: 0 12px;
`;
paragraph.addEventListener('click', async () => {
await this._rotationService.applyRotation();
this.disable(ROTATION_ACTION_BUTTONS);
});
paragraph.addEventListener('click', () =>
this._ngZone.run(async () => {
await this._rotationService.applyRotation();
this.disable(ROTATION_ACTION_BUTTONS);
}),
);
return paragraph;
},
};
@ -161,7 +159,7 @@ export class ViewerHeaderService {
cursor: pointer;
opacity: 0.7;
`;
paragraph.addEventListener('click', () => this.#discardRotation());
paragraph.addEventListener('click', () => this._ngZone.run(() => this.#discardRotation()));
return paragraph;
},
};
@ -174,10 +172,11 @@ export class ViewerHeaderService {
dataElement: HeaderElements.ROTATE_RIGHT_BUTTON,
img: this._convertPath('/assets/icons/general/rotate-right.svg'),
title: 'Rotate page right',
onClick: () => {
this._rotationService.addRotation(RotationTypes.RIGHT);
this.#toggleRotationActionButtons();
},
onClick: () =>
this._ngZone.run(() => {
this._rotationService.addRotation(RotationTypes.RIGHT);
this.#toggleRotationActionButtons();
}),
};
}
@ -188,10 +187,11 @@ export class ViewerHeaderService {
dataElement: HeaderElements.COMPARE_BUTTON,
img: this._convertPath('/assets/icons/general/pdftron-action-compare.svg'),
title: 'Compare',
onClick: async () => {
document.getElementById('compareFileInput').click();
this.#docBeforeCompare = await this._documentViewer.blob();
},
onClick: () =>
this._ngZone.run(async () => {
document.getElementById('compareFileInput').click();
this.#docBeforeCompare = await this._documentViewer.blob();
}),
};
}
@ -293,7 +293,7 @@ export class ViewerHeaderService {
enableLoadAllAnnotations(): void {
this._pdf.instance.UI.updateElement(HeaderElements.LOAD_ALL_ANNOTATIONS, {
img: this._convertPath('/assets/icons/general/pdftron-action-load-all-annotations.svg'),
onClick: () => this.#events$.next({ type: ViewerEvents.LOAD_ALL_ANNOTATIONS }),
onClick: () => this._ngZone.run(() => this.#events$.next({ type: ViewerEvents.LOAD_ALL_ANNOTATIONS })),
});
}