RED-7397 fix resizing issues

This commit is contained in:
Dan Percic 2023-08-30 20:25:33 +03:00
parent 991dfae106
commit 983c7144d9
8 changed files with 64 additions and 73 deletions

View File

@ -131,7 +131,7 @@ export const appModuleFactory = (config: AppConfig) => {
features: {
ANNOTATIONS: {
color: 'aqua',
enabled: false,
enabled: true,
level: NgxLoggerLevel.DEBUG,
},
FILTERS: {
@ -147,7 +147,7 @@ export const appModuleFactory = (config: AppConfig) => {
enabled: true,
},
FILE: {
enabled: true,
enabled: false,
},
CHANGES: {
enabled: false,

View File

@ -205,7 +205,6 @@ export class AnnotationActionsService {
if (annotationWrapper.rectangle || annotationWrapper.imported || annotationWrapper.isImage) {
this._annotationManager.delete(annotationWrapper);
const rectangleAnnotation = this.#generateRectangle(annotationWrapper);
console.log(rectangleAnnotation);
return this._annotationManager.add(rectangleAnnotation);
}
@ -267,11 +266,9 @@ export class AnnotationActionsService {
async cancelResize(annotationWrapper: AnnotationWrapper) {
this._annotationManager.resizingAnnotationId = undefined;
this._annotationManager.resizingHasStarted = false;
this._annotationManager.delete(annotationWrapper);
await this._annotationDrawService.draw([annotationWrapper], this._skippedService.hideSkipped(), this._state.dossierTemplateId);
this._annotationManager.deselect();
await this._fileDataService.annotationsChanged();
}
#generateRectangle(annotationWrapper: AnnotationWrapper) {

View File

@ -31,17 +31,14 @@ export class PdfAnnotationActionsService {
const firstAnnotation = annotations[0];
// if we already entered resize-mode previously
if (firstAnnotation.id === this.#annotationManager.resizingAnnotationId) {
if (this.#annotationManager.resizingHasStarted) {
const acceptResizeButton = this.#getButton('check', _('annotation-actions.resize-accept.label'), () =>
this.#annotationActionsService.acceptResize(firstAnnotation),
);
const cancelResizeButton = this.#getButton('close', _('annotation-actions.resize-cancel.label'), () =>
this.#annotationActionsService.cancelResize(firstAnnotation),
);
const acceptResizeButton = this.#getButton('check', _('annotation-actions.resize-accept.label'), () =>
this.#annotationActionsService.acceptResize(firstAnnotation),
);
const cancelResizeButton = this.#getButton('close', _('annotation-actions.resize-cancel.label'), () =>
this.#annotationActionsService.cancelResize(firstAnnotation),
);
return [acceptResizeButton, cancelResizeButton];
}
return [];
return [acceptResizeButton, cancelResizeButton];
}
const resizeButton = this.#getButton('resize', _('annotation-actions.resize.label'), () =>

View File

@ -286,7 +286,7 @@ export class PdfProxyService {
this.handleAnnotationSelected([]);
}
#processSelectedAnnotations(annotations: Annotation[], action) {
#processSelectedAnnotations(annotations: Annotation[], action: string) {
let nextAnnotations: Annotation[];
if (action === 'deselected') {
@ -313,7 +313,10 @@ export class PdfProxyService {
nextAnnotations = this._annotationManager.selected;
}
this.#configureAnnotationSpecificActions(nextAnnotations);
const annotationWasResized = this._annotationManager.resizingAnnotationId && action === 'modify';
if (!this._annotationManager.resizingAnnotationId || annotationWasResized) {
this.#configureAnnotationSpecificActions(nextAnnotations);
}
if (!(annotations.length === 1 && annotations[0].ReadOnly)) {
this._pdf.enable(TextPopups.ADD_RECTANGLE);
@ -344,7 +347,6 @@ export class PdfProxyService {
// which is automatically converted to redaction when resized,
// so the original annotation(wrapper) is removed
this._annotationManager.resizingAnnotationId = undefined;
this._annotationManager.resizingHasStarted = false;
return;
}
@ -359,20 +361,20 @@ export class PdfProxyService {
}
#configureAnnotationSpecificActions(viewerAnnotations: Annotation[]) {
this._pdf.resetAnnotationActions();
if (!this.canPerformActions()) {
return this._pdf.resetAnnotationActions();
return;
}
const annotationWrappers = viewerAnnotations.map(va => this._fileDataService.find(va.Id)).filter(va => !!va);
this._pdf.resetAnnotationActions();
if (annotationWrappers.length === 0) {
return this.#configureRectangleAnnotationPopup(viewerAnnotations[0]);
}
// Add hide action as last item
const allAnnotationsHaveImageAction = annotationWrappers.reduce((acc, next) => acc && next.isImage, true);
if (allAnnotationsHaveImageAction) {
const allAreImage = annotationWrappers.reduce((acc, next) => acc && next.isImage, true);
if (allAreImage && !this._annotationManager.resizingAnnotationId) {
const allAreVisible = viewerAnnotations.reduce((acc, next) => next.isVisible() && acc, true);
const visibilityButton = {

View File

@ -4,8 +4,6 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { Core } from '@pdftron/webviewer';
import { IRectangle, ISectionRectangle, SuperTypes } from '@red/domain';
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
import { RedactionLogService } from '@services/files/redaction-log.service';
import { UserPreferenceService } from '@users/user-preference.service';
import { hexToRgb } from '@utils/functions';
import { BoundingBox, Table } from '../../file-preview/services/tables.service';
import { REDAnnotationManager } from './annotation-manager.service';
@ -31,8 +29,6 @@ export function getSectionRectangle(box: BoundingBox): ISectionRectangle {
@Injectable()
export class AnnotationDrawService {
constructor(
private readonly _redactionLogService: RedactionLogService,
private readonly _userPreferenceService: UserPreferenceService,
private readonly _annotationManager: REDAnnotationManager,
private readonly _pdf: PdfViewer,
private readonly _documentViewer: REDDocumentViewer,
@ -41,7 +37,7 @@ export class AnnotationDrawService {
async draw(annotations: List<AnnotationWrapper>, hideSkipped: boolean, dossierTemplateId: string) {
try {
return this._pdf.runWithCleanup(() => this._draw(annotations, hideSkipped, dossierTemplateId));
return this._pdf.runWithCleanup(() => this.#draw(annotations, hideSkipped, dossierTemplateId));
} catch (e) {
console.error(e);
}
@ -70,7 +66,7 @@ export class AnnotationDrawService {
async drawTables(tables: Table[], page: number, dossierTemplateId: string) {
const sections: Core.Annotations.RectangleAnnotation[] = [];
tables.forEach(table => {
const section = this._computeSection(page, getSectionRectangle(table.boundingBox), dossierTemplateId);
const section = this.#computeSection(page, getSectionRectangle(table.boundingBox), dossierTemplateId);
if (table.experimental) {
section.StrokeColor = this.convertColor('#800080');
} else {
@ -80,7 +76,7 @@ export class AnnotationDrawService {
table.cellsPerRow
.flatMap(row => row)
.forEach(row => {
const cellSection = this._computeSection(page, getSectionRectangle(row.boundingBox), dossierTemplateId);
const cellSection = this.#computeSection(page, getSectionRectangle(row.boundingBox), dossierTemplateId);
if (table.experimental) {
cellSection.StrokeColor = this.convertColor('#800080');
} else {
@ -93,10 +89,10 @@ export class AnnotationDrawService {
await this._annotationManager.add(sections);
}
private async _draw(annotationWrappers: List<AnnotationWrapper>, hideSkipped: boolean, dossierTemplateId: string) {
async #draw(annotationWrappers: List<AnnotationWrapper>, hideSkipped: boolean, dossierTemplateId: string) {
const totalPages = this._pdf.totalPages();
const annotations = annotationWrappers
?.map(annotation => this._computeAnnotation(annotation, hideSkipped, totalPages, dossierTemplateId))
?.map(annotation => this.#computeAnnotation(annotation, hideSkipped, totalPages, dossierTemplateId))
.filterTruthy();
if (!this._documentViewer.loaded()) {
return;
@ -104,7 +100,7 @@ export class AnnotationDrawService {
await this._annotationManager.add(annotations);
}
private _computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dossierTemplateId: string) {
#computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dossierTemplateId: string) {
const rectangleAnnot = this._pdf.rectangle();
const pageHeight = this._documentViewer.getHeight(pageNumber);
const rectangle: IRectangle = {
@ -125,7 +121,7 @@ export class AnnotationDrawService {
return rectangleAnnot;
}
private _computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dossierTemplateId: string) {
#computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dossierTemplateId: string) {
const pageNumber = this._pdf.isCompareMode() ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber;
if (pageNumber > totalPages) {
// skip imported annotations from files that have more pages than the current one
@ -150,7 +146,7 @@ export class AnnotationDrawService {
}
const annotation = this._pdf.textHighlight();
annotation.Quads = this._rectanglesToQuads(annotationWrapper.positions, pageNumber);
annotation.Quads = this.#rectanglesToQuads(annotationWrapper.positions, pageNumber);
annotation.Opacity = annotationWrapper.isChangeLogRemoved ? DEFAULT_REMOVED_ANNOTATION_OPACITY : DEFAULT_TEXT_ANNOTATION_OPACITY;
annotation.setContents(annotationWrapper.content);
annotation.PageNumber = pageNumber;
@ -190,12 +186,12 @@ export class AnnotationDrawService {
return annotation;
}
private _rectanglesToQuads(positions: IRectangle[], pageNumber: number): Quad[] {
#rectanglesToQuads(positions: IRectangle[], pageNumber: number): Quad[] {
const pageHeight = this._documentViewer.getHeight(pageNumber);
return positions.map(p => this._rectangleToQuad(p, pageHeight));
return positions.map(p => this.#rectangleToQuad(p, pageHeight));
}
private _rectangleToQuad(rectangle: IRectangle, pageHeight: number): Quad {
#rectangleToQuad(rectangle: IRectangle, pageHeight: number): Quad {
const x1 = rectangle.topLeft.x;
const y1 = pageHeight - (rectangle.topLeft.y + rectangle.height);

View File

@ -1,13 +1,13 @@
import { inject, Injectable, signal } from '@angular/core';
import { Core } from '@pdftron/webviewer';
import type { List } from '@iqser/common-ui/lib/utils';
import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { Subject } from 'rxjs';
import { asList, getId, isStringOrWrapper } from '../utils/functions';
import { Core } from '@pdftron/webviewer';
import { getLast } from '@utils/functions';
import { AnnotationToolNames } from '../utils/constants';
import { NGXLogger } from 'ngx-logger';
import { Subject } from 'rxjs';
import { AnnotationToolNames } from '../utils/constants';
import { asList, getId, isStringOrWrapper } from '../utils/functions';
import { AnnotationPredicate, DeleteAnnotationsOptions } from '../utils/types';
import AnnotationManager = Core.AnnotationManager;
import Annotation = Core.Annotations.Annotation;
@ -19,7 +19,6 @@ export class REDAnnotationManager {
readonly #annotationSelected$ = new Subject<[Annotation[], string]>();
readonly annotationSelected$ = this.#annotationSelected$.asObservable();
resizingAnnotationId?: string = undefined;
resizingHasStarted = false;
readonly hidden = this.#hidden.asReadonly();
get selected() {
@ -141,14 +140,12 @@ export class REDAnnotationManager {
// when a rectangle is drawn,
// it returns one annotation with tool name 'AnnotationCreateRectangle;
// this will auto select rectangle after drawing
if (annotations.length === 1 && annotations[0].ToolName === AnnotationToolNames.AnnotationCreateRectangle) {
this.#manager.selectAnnotations(annotations);
annotations[0].disableRotationControl();
}
if (action === 'modify' && options.source === 'resize' && !this.resizingHasStarted) {
this.resizingHasStarted = true;
this.#annotationSelected$.next([annotations, action]);
const annotation = annotations.length === 1 ? annotations[0] : undefined;
if (annotation && annotation.ToolName === AnnotationToolNames.AnnotationCreateRectangle) {
this.#manager.selectAnnotation(annotation);
annotation.disableRotationControl();
}
this.#annotationSelected$.next([annotations, action]);
});
}

View File

@ -1,18 +1,18 @@
import { effect, inject, Injectable, Signal, signal } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router';
import { log } from '@iqser/common-ui/lib/utils';
import { Core } from '@pdftron/webviewer';
import { RotationType, RotationTypes } from '@red/domain';
import { UserPreferenceService } from '@users/user-preference.service';
import { NGXLogger } from 'ngx-logger';
import { BehaviorSubject, fromEvent, Observable } from 'rxjs';
import { filter, tap } from 'rxjs/operators';
import { ActivatedRoute } from '@angular/router';
import { PdfViewer } from './pdf-viewer.service';
import { UserPreferenceService } from '@users/user-preference.service';
import { log } from '@iqser/common-ui/lib/utils';
import { stopAndPrevent, stopAndPreventIfNotAllowed } from '../utils/functions';
import { RotationType, RotationTypes } from '@red/domain';
import { AnnotationToolNames } from '../utils/constants';
import { toObservable } from '@angular/core/rxjs-interop';
import DocumentViewer = Core.DocumentViewer;
import { stopAndPrevent, stopAndPreventIfNotAllowed } from '../utils/functions';
import { PdfViewer } from './pdf-viewer.service';
import Color = Core.Annotations.Color;
import DocumentViewer = Core.DocumentViewer;
import Quad = Core.Math.Quad;
@Injectable()

View File

@ -1,26 +1,26 @@
import { DestroyRef, inject, Injectable, signal, Signal } from '@angular/core';
import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/webviewer';
import { ErrorService, getConfig } from '@iqser/common-ui';
import { AppConfig, File, IHeaderElement } from '@red/domain';
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router';
import { map, startWith } from 'rxjs/operators';
import { combineLatest, fromEvent, Observable } from 'rxjs';
import { NGXLogger } from 'ngx-logger';
import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, SEARCH_OPTIONS, USELESS_ELEMENTS } from '../utils/constants';
import { Rgb } from '../utils/types';
import { asList } from '../utils/functions';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { environment } from '@environments/environment';
import { ErrorService, getConfig } from '@iqser/common-ui';
import { BASE_HREF_FN, shareDistinctLast } from '@iqser/common-ui/lib/utils';
import { TranslateService } from '@ngx-translate/core';
import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/webviewer';
import { AppConfig, File, IHeaderElement } from '@red/domain';
import { LicenseService } from '@services/license.service';
import { UserPreferenceService } from '@users/user-preference.service';
import { environment } from '@environments/environment';
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { BASE_HREF_FN, shareDistinctLast } from '@iqser/common-ui/lib/utils';
import TextTool = Core.Tools.TextTool;
import { NGXLogger } from 'ngx-logger';
import { combineLatest, fromEvent, Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { DISABLED_HOTKEYS, DOCUMENT_LOADING_ERROR, SEARCH_OPTIONS, USELESS_ELEMENTS } from '../utils/constants';
import { asList } from '../utils/functions';
import { Rgb } from '../utils/types';
import Annotation = Core.Annotations.Annotation;
import TextHighlightAnnotation = Core.Annotations.TextHighlightAnnotation;
import DocumentViewer = Core.DocumentViewer;
import Quad = Core.Math.Quad;
import TextTool = Core.Tools.TextTool;
@Injectable()
export class PdfViewer {
@ -40,6 +40,7 @@ export class PdfViewer {
},
};
readonly #destroyRef = inject(DestroyRef);
readonly #logger = inject(NGXLogger);
readonly #totalPages = signal<number>(0);
readonly currentPage$ = inject(ActivatedRoute).queryParamMap.pipe(
map(params => Number(params.get('page') ?? '1')),
@ -118,6 +119,7 @@ export class PdfViewer {
resetAnnotationActions() {
if (this.#instance.UI.annotationPopup.getItems().length) {
this.#logger.info('[PDF] Reset annotation actions');
this.#instance.UI.annotationPopup.update([]);
}
}