mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[ACS-10884] Keyboard interactions for crop tool in image viewer (#11522)
* [ACS-10884] Keyboard interactions for crop tool in image viewer * [ACS-10884] Sonarqube fix * [ACS-10884] MD formatting fix
This commit is contained in:
@@ -107,12 +107,14 @@ See the [Custom layout](#custom-layout) section for full details of all availabl
|
|||||||
|
|
||||||
## Keyboard shortcuts
|
## Keyboard shortcuts
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
|--------|---------------------------------------|
|
|-------------------|---------------------------------------------------------------|
|
||||||
| Esc | Close the viewer (overlay mode only). |
|
| Esc | Close the viewer (overlay mode only). |
|
||||||
| Left | Invoke 'Navigate before' action. |
|
| Left | Invoke 'Navigate before' action. Disabled in image edit mode. |
|
||||||
| Right | Invoke 'Navigate next' action. |
|
| Right | Invoke 'Navigate next' action. Disabled in image edit mode. |
|
||||||
| Ctrl+F | Activate full-screen mode. |
|
| Shift + Arrow Key | Increase image crop area. Active only in image edit mode. |
|
||||||
|
| Alt + Arrow Key | Decrease image crop area. Active only in image edit mode. |
|
||||||
|
| Ctrl+F | Activate full-screen mode. |
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
|||||||
@@ -76,12 +76,14 @@ Using with file [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob):
|
|||||||
|
|
||||||
## Keyboard shortcuts
|
## Keyboard shortcuts
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ---- | ----------- |
|
| ----------------- | ------------------------------------------------------------- |
|
||||||
| Esc | Close the viewer (overlay mode only). |
|
| Esc | Close the viewer (overlay mode only). |
|
||||||
| Left | Invoke 'Navigate before' action. |
|
| Left | Invoke 'Navigate before' action. Disabled in image edit mode. |
|
||||||
| Right | Invoke 'Navigate next' action. |
|
| Right | Invoke 'Navigate next' action. Disabled in image edit mode. |
|
||||||
| Ctrl+F | Activate full-screen mode. |
|
| Shift + Arrow Key | Increase image crop area. Active only in image edit mode. |
|
||||||
|
| Alt + Arrow Key | Decrease image crop area. Active only in image edit mode. |
|
||||||
|
| Ctrl+F | Activate full-screen mode. |
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
|||||||
@@ -105,12 +105,14 @@ See the [Custom layout](#custom-layout) section for full details of all availabl
|
|||||||
|
|
||||||
## Keyboard shortcuts
|
## Keyboard shortcuts
|
||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ---- | ----------- |
|
| ----------------- | ------------------------------------------------------------- |
|
||||||
| Esc | Close the viewer (overlay mode only). |
|
| Esc | Close the viewer (overlay mode only). |
|
||||||
| Left | Invoke 'Navigate before' action. |
|
| Left | Invoke 'Navigate before' action. Disabled in image edit mode. |
|
||||||
| Right | Invoke 'Navigate next' action. |
|
| Right | Invoke 'Navigate next' action. Disabled in image edit mode. |
|
||||||
| Ctrl+F | Activate full-screen mode. |
|
| Shift + Arrow Key | Increase image crop area. Active only in image edit mode. |
|
||||||
|
| Alt + Arrow Key | Decrease image crop area. Active only in image edit mode. |
|
||||||
|
| Ctrl+F | Activate full-screen mode. |
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,26 @@ describe('Test Img viewer component ', () => {
|
|||||||
return new Blob([data], { type: 'image/png' });
|
return new Blob([data], { type: 'image/png' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dispatchKeyboardEvent = (key: string, shiftKey = false, altKey = false): KeyboardEvent => {
|
||||||
|
const event = new KeyboardEvent('keyup', {
|
||||||
|
key,
|
||||||
|
shiftKey,
|
||||||
|
altKey
|
||||||
|
});
|
||||||
|
spyOn(event, 'preventDefault');
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
return event;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getExpectedCropBoxData = (cropper: Cropper, left: number, width: number, top: number, height: number): Cropper.CropBoxData => {
|
||||||
|
const cropBoxData = cropper.getCropBoxData();
|
||||||
|
cropBoxData.left += left;
|
||||||
|
cropBoxData.top += top;
|
||||||
|
cropBoxData.width += width;
|
||||||
|
cropBoxData.height += height;
|
||||||
|
return cropBoxData;
|
||||||
|
};
|
||||||
|
|
||||||
describe('Zoom customization', () => {
|
describe('Zoom customization', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
urlService = TestBed.inject(UrlService);
|
urlService = TestBed.inject(UrlService);
|
||||||
@@ -375,4 +395,134 @@ describe('Test Img viewer component ', () => {
|
|||||||
expect(testingUtils.getByCSS('#viewer-crop-button')).toBeNull('Crop button should not be visible when disallowed');
|
expect(testingUtils.getByCSS('#viewer-crop-button')).toBeNull('Crop button should not be visible when disallowed');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('keyboard interactions', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ImgViewerComponent);
|
||||||
|
testingUtils = new UnitTestingUtils(fixture.debugElement);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should rotate the image when r key is pressed', () => {
|
||||||
|
spyOn(component, 'rotateImage');
|
||||||
|
dispatchKeyboardEvent('r');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.rotateImage).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should zoom the image out when o key is pressed', () => {
|
||||||
|
spyOn(component, 'zoomOut');
|
||||||
|
dispatchKeyboardEvent('o');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.zoomOut).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should zoom the image in when i key is pressed', () => {
|
||||||
|
spyOn(component, 'zoomIn');
|
||||||
|
dispatchKeyboardEvent('i');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.zoomIn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should move the cropper when arrow keys are pressed', () => {
|
||||||
|
spyOn(component.cropper, 'move');
|
||||||
|
dispatchKeyboardEvent('ArrowLeft');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.move).toHaveBeenCalledWith(-3, 0);
|
||||||
|
|
||||||
|
dispatchKeyboardEvent('ArrowRight');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.move).toHaveBeenCalledWith(3, 0);
|
||||||
|
|
||||||
|
dispatchKeyboardEvent('ArrowUp');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.move).toHaveBeenCalledWith(0, -3);
|
||||||
|
|
||||||
|
dispatchKeyboardEvent('ArrowDown');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.move).toHaveBeenCalledWith(0, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should increase crop box area when arrow keys with shift are pressed', () => {
|
||||||
|
component.cropImage();
|
||||||
|
spyOn(component.cropper, 'setCropBoxData');
|
||||||
|
let expectedCropBoxData = getExpectedCropBoxData(component.cropper, -3, 3, 0, 0);
|
||||||
|
dispatchKeyboardEvent('ArrowLeft', true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.setCropBoxData).toHaveBeenCalledWith(expectedCropBoxData);
|
||||||
|
|
||||||
|
expectedCropBoxData = getExpectedCropBoxData(component.cropper, 0, 3, 0, 0);
|
||||||
|
dispatchKeyboardEvent('ArrowRight', true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.setCropBoxData).toHaveBeenCalledWith(expectedCropBoxData);
|
||||||
|
|
||||||
|
expectedCropBoxData = getExpectedCropBoxData(component.cropper, 0, 0, -3, 3);
|
||||||
|
dispatchKeyboardEvent('ArrowUp', true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.setCropBoxData).toHaveBeenCalledWith(expectedCropBoxData);
|
||||||
|
|
||||||
|
expectedCropBoxData = getExpectedCropBoxData(component.cropper, 0, 0, 0, 3);
|
||||||
|
dispatchKeyboardEvent('ArrowDown', true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.setCropBoxData).toHaveBeenCalledWith(expectedCropBoxData);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should decrease crop box area when arrow keys with alt are pressed', () => {
|
||||||
|
component.cropImage();
|
||||||
|
spyOn(component.cropper, 'setCropBoxData');
|
||||||
|
let expectedCropBoxData = getExpectedCropBoxData(component.cropper, 3, -3, 0, 0);
|
||||||
|
dispatchKeyboardEvent('ArrowLeft', false, true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.setCropBoxData).toHaveBeenCalledWith(expectedCropBoxData);
|
||||||
|
|
||||||
|
expectedCropBoxData = getExpectedCropBoxData(component.cropper, 0, -3, 0, 0);
|
||||||
|
dispatchKeyboardEvent('ArrowRight', false, true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.setCropBoxData).toHaveBeenCalledWith(expectedCropBoxData);
|
||||||
|
|
||||||
|
expectedCropBoxData = getExpectedCropBoxData(component.cropper, 0, 0, 3, -3);
|
||||||
|
dispatchKeyboardEvent('ArrowUp', false, true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.setCropBoxData).toHaveBeenCalledWith(expectedCropBoxData);
|
||||||
|
|
||||||
|
expectedCropBoxData = getExpectedCropBoxData(component.cropper, 0, 0, 0, -3);
|
||||||
|
dispatchKeyboardEvent('ArrowDown', false, true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.cropper.setCropBoxData).toHaveBeenCalledWith(expectedCropBoxData);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prevent default for all arrow keys events', () => {
|
||||||
|
const leftEvent = dispatchKeyboardEvent('ArrowLeft');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(leftEvent.preventDefault).toHaveBeenCalled();
|
||||||
|
|
||||||
|
const rightEvent = dispatchKeyboardEvent('ArrowRight');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(rightEvent.preventDefault).toHaveBeenCalled();
|
||||||
|
|
||||||
|
const upEvent = dispatchKeyboardEvent('ArrowUp');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(upEvent.preventDefault).toHaveBeenCalled();
|
||||||
|
|
||||||
|
const downEvent = dispatchKeyboardEvent('ArrowDown');
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(downEvent.preventDefault).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -85,27 +85,23 @@ export class ImgViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
|||||||
@ViewChild('image', { static: false })
|
@ViewChild('image', { static: false })
|
||||||
imageElement: ElementRef;
|
imageElement: ElementRef;
|
||||||
|
|
||||||
@HostListener('document:keydown', ['$event'])
|
@HostListener('document:keyup', ['$event'])
|
||||||
onKeyDown(event: KeyboardEvent) {
|
onKeyDown(event: KeyboardEvent) {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case 'ArrowLeft': {
|
case 'ArrowLeft': {
|
||||||
event.preventDefault();
|
this.handleArrowLeftKey(event);
|
||||||
this.cropper.move(-3, 0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'ArrowUp': {
|
case 'ArrowUp': {
|
||||||
event.preventDefault();
|
this.handleArrowUpKey(event);
|
||||||
this.cropper.move(0, -3);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'ArrowRight': {
|
case 'ArrowRight': {
|
||||||
event.preventDefault();
|
this.handleArrowRightKey(event);
|
||||||
this.cropper.move(3, 0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'ArrowDown': {
|
case 'ArrowDown': {
|
||||||
event.preventDefault();
|
this.handleArrowDownKey(event);
|
||||||
this.cropper.move(0, 3);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'i': {
|
case 'i': {
|
||||||
@@ -255,4 +251,57 @@ export class ImgViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
|||||||
onImageError() {
|
onImageError() {
|
||||||
this.error.emit();
|
this.error.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleArrowLeftKey(event: KeyboardEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.shiftKey) {
|
||||||
|
this.changeCropBoxArea(-3, 3, 0, 0);
|
||||||
|
} else if (event.altKey) {
|
||||||
|
this.changeCropBoxArea(3, -3, 0, 0);
|
||||||
|
} else {
|
||||||
|
this.cropper.move(-3, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleArrowUpKey(event: KeyboardEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.shiftKey) {
|
||||||
|
this.changeCropBoxArea(0, 0, -3, 3);
|
||||||
|
} else if (event.altKey) {
|
||||||
|
this.changeCropBoxArea(0, 0, 3, -3);
|
||||||
|
} else {
|
||||||
|
this.cropper.move(0, -3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleArrowRightKey(event: KeyboardEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.shiftKey) {
|
||||||
|
this.changeCropBoxArea(0, 3, 0, 0);
|
||||||
|
} else if (event.altKey) {
|
||||||
|
this.changeCropBoxArea(0, -3, 0, 0);
|
||||||
|
} else {
|
||||||
|
this.cropper.move(3, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleArrowDownKey(event: KeyboardEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.shiftKey) {
|
||||||
|
this.changeCropBoxArea(0, 0, 0, 3);
|
||||||
|
} else if (event.altKey) {
|
||||||
|
this.changeCropBoxArea(0, 0, 0, -3);
|
||||||
|
} else {
|
||||||
|
this.cropper.move(0, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private changeCropBoxArea(left: number, width: number, top: number, height: number) {
|
||||||
|
const cropBoxData = this.cropper.getCropBoxData();
|
||||||
|
cropBoxData.left += left;
|
||||||
|
cropBoxData.width += width;
|
||||||
|
cropBoxData.top += top;
|
||||||
|
cropBoxData.height += height;
|
||||||
|
this.cropper.setCropBoxData(cropBoxData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { AppExtensionService, ExtensionsModule, ViewerExtensionRef, PreviewExtensionComponent } from '@alfresco/adf-extensions';
|
import { AppExtensionService, ExtensionsModule, ViewerExtensionRef, PreviewExtensionComponent } from '@alfresco/adf-extensions';
|
||||||
import { NgForOf, NgTemplateOutlet } from '@angular/common';
|
import { NgForOf, NgTemplateOutlet } from '@angular/common';
|
||||||
import { Component, EventEmitter, Injector, Input, OnChanges, OnInit, Output, TemplateRef, ViewEncapsulation } from '@angular/core';
|
import { Component, EventEmitter, Injector, Input, OnChanges, OnInit, Output, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { TranslatePipe } from '@ngx-translate/core';
|
import { TranslatePipe } from '@ngx-translate/core';
|
||||||
@@ -129,6 +129,9 @@ export class ViewerRenderComponent implements OnChanges, OnInit {
|
|||||||
@Output()
|
@Output()
|
||||||
isSaving = new EventEmitter<boolean>();
|
isSaving = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
@ViewChild(ImgViewerComponent)
|
||||||
|
imgViewer: ImgViewerComponent;
|
||||||
|
|
||||||
extensionTemplates: { template: TemplateRef<any>; isVisible: boolean }[] = [];
|
extensionTemplates: { template: TemplateRef<any>; isVisible: boolean }[] = [];
|
||||||
extensionsSupportedByTemplates: string[] = [];
|
extensionsSupportedByTemplates: string[] = [];
|
||||||
extension: string;
|
extension: string;
|
||||||
|
|||||||
@@ -53,6 +53,20 @@ describe('ViewerComponent', () => {
|
|||||||
const getFileName = (): string => testingUtils.getByCSS('#adf-viewer-display-name').nativeElement.textContent;
|
const getFileName = (): string => testingUtils.getByCSS('#adf-viewer-display-name').nativeElement.textContent;
|
||||||
const getTitle = (): string => testingUtils.getByCSS('.adf-viewer__title-value')?.nativeElement?.textContent;
|
const getTitle = (): string => testingUtils.getByCSS('.adf-viewer__title-value')?.nativeElement?.textContent;
|
||||||
const getDividers = (): DebugElement[] => testingUtils.getAllByCSS('.adf-toolbar-divider');
|
const getDividers = (): DebugElement[] => testingUtils.getAllByCSS('.adf-toolbar-divider');
|
||||||
|
const mockImgViewerEditMode = (isEditing: boolean) => {
|
||||||
|
const imgViewerMock = jasmine.createSpyObj('ImgViewerComponent', [], {
|
||||||
|
isEditing
|
||||||
|
});
|
||||||
|
component.viewerRenderer.imgViewer = imgViewerMock;
|
||||||
|
};
|
||||||
|
const dispatchKeyboardEvent = (key: string): KeyboardEvent => {
|
||||||
|
const event = new KeyboardEvent('keyup', {
|
||||||
|
key
|
||||||
|
});
|
||||||
|
spyOn(event, 'preventDefault');
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
return event;
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -750,4 +764,79 @@ describe('ViewerComponent', () => {
|
|||||||
expect(component.downloadFile.emit).toHaveBeenCalled();
|
expect(component.downloadFile.emit).toHaveBeenCalled();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('keyboard events', () => {
|
||||||
|
it('should do nothing when default was already prevented', () => {
|
||||||
|
spyOn(component, 'onNavigateBeforeClick').and.callThrough();
|
||||||
|
spyOn(component, 'onNavigateNextClick').and.callThrough();
|
||||||
|
spyOn(component, 'enterFullScreen').and.callThrough();
|
||||||
|
|
||||||
|
const event = new KeyboardEvent('keyup', {
|
||||||
|
key: 'a'
|
||||||
|
});
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.onNavigateBeforeClick).not.toHaveBeenCalled();
|
||||||
|
expect(component.onNavigateNextClick).not.toHaveBeenCalled();
|
||||||
|
expect(component.enterFullScreen).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enter full screen mode when ctrl + F is pressed', () => {
|
||||||
|
spyOn(component, 'enterFullScreen').and.callThrough();
|
||||||
|
|
||||||
|
const event = new KeyboardEvent('keyup', {
|
||||||
|
code: 'KeyF',
|
||||||
|
ctrlKey: true
|
||||||
|
});
|
||||||
|
spyOn(event, 'preventDefault');
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(event.preventDefault).toHaveBeenCalled();
|
||||||
|
expect(component.enterFullScreen).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate before when left arrow is pressed', () => {
|
||||||
|
component.canNavigateBefore = true;
|
||||||
|
spyOn(component, 'onNavigateBeforeClick').and.callThrough();
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
mockImgViewerEditMode(true);
|
||||||
|
const event = dispatchKeyboardEvent('ArrowLeft');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(event.preventDefault).not.toHaveBeenCalled();
|
||||||
|
expect(component.onNavigateBeforeClick).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
mockImgViewerEditMode(false);
|
||||||
|
const event2 = dispatchKeyboardEvent('ArrowLeft');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(event2.preventDefault).toHaveBeenCalled();
|
||||||
|
expect(component.onNavigateBeforeClick).toHaveBeenCalledWith(event2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate next when right arrow is pressed', () => {
|
||||||
|
component.canNavigateNext = true;
|
||||||
|
spyOn(component, 'onNavigateNextClick').and.callThrough();
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
mockImgViewerEditMode(true);
|
||||||
|
const event = dispatchKeyboardEvent('ArrowRight');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(event.preventDefault).not.toHaveBeenCalled();
|
||||||
|
expect(component.onNavigateNextClick).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
mockImgViewerEditMode(false);
|
||||||
|
const event2 = dispatchKeyboardEvent('ArrowRight');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(event2.preventDefault).toHaveBeenCalled();
|
||||||
|
expect(component.onNavigateNextClick).toHaveBeenCalledWith(event2);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
Output,
|
Output,
|
||||||
SimpleChanges,
|
SimpleChanges,
|
||||||
TemplateRef,
|
TemplateRef,
|
||||||
|
ViewChild,
|
||||||
ViewEncapsulation
|
ViewEncapsulation
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
@@ -299,6 +300,9 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
|||||||
@Output()
|
@Output()
|
||||||
submitFile = new EventEmitter<Blob>();
|
submitFile = new EventEmitter<Blob>();
|
||||||
|
|
||||||
|
@ViewChild(ViewerRenderComponent)
|
||||||
|
viewerRenderer: ViewerRenderComponent;
|
||||||
|
|
||||||
private closeViewer = true;
|
private closeViewer = true;
|
||||||
private keyDown$ = fromEvent<KeyboardEvent>(document, 'keydown');
|
private keyDown$ = fromEvent<KeyboardEvent>(document, 'keydown');
|
||||||
private isDialogVisible = false;
|
private isDialogVisible = false;
|
||||||
@@ -437,14 +441,16 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'ArrowLeft' && this.canNavigateBefore) {
|
if (!this.viewerRenderer?.imgViewer?.isEditing) {
|
||||||
event.preventDefault();
|
if (event.key === 'ArrowLeft' && this.canNavigateBefore) {
|
||||||
this.onNavigateBeforeClick(event);
|
event.preventDefault();
|
||||||
}
|
this.onNavigateBeforeClick(event);
|
||||||
|
}
|
||||||
|
|
||||||
if (event.key === 'ArrowRight' && this.canNavigateNext) {
|
if (event.key === 'ArrowRight' && this.canNavigateNext) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.onNavigateNextClick(event);
|
this.onNavigateNextClick(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code === 'KeyF' && event.ctrlKey) {
|
if (event.code === 'KeyF' && event.ctrlKey) {
|
||||||
|
|||||||
Reference in New Issue
Block a user