Fix issues with grid key naviation

It should only navigate now when focussed.
Same logic applies to the gallery.
The focus is kept when changing between the gallery and
the grid.

TG-48 #closed

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent 08632080cb
commit a86aaef510

@ -43,14 +43,12 @@ export class CoreComponent {
this.stateService.state.subscribe(state => {
this.appState = state;
console.log("new state", state);
if (this.appState.tabs.value.length === 0) {
this.addTab();
}
state.tabs.subscribe(tabs => {
console.log("new tabs", tabs);
this.tabs = tabs;
console.log(tabs);
if (this.tabs.length === 0) {
this.addTab();
}
@ -101,7 +99,6 @@ export class CoreComponent {
}
public async onMouseClickTabLabel(tab: TabState, event: MouseEvent) {
console.log(event);
if (event.button === 1) { // middle mouse button
await this.closeTab(tab);
}

@ -15,6 +15,7 @@ import {MatMenuModule} from "@angular/material/menu";
import {
ContentAwareImageComponent
} from "./content-aware-image/content-aware-image.component";
import { InputReceiverDirective } from "./input-receiver/input-receiver.directive";
@NgModule({
@ -23,12 +24,14 @@ import {
BusyIndicatorComponent,
ContextMenuComponent,
ContentAwareImageComponent,
InputReceiverDirective,
],
exports: [
ConfirmDialogComponent,
BusyIndicatorComponent,
ContextMenuComponent,
ContentAwareImageComponent,
InputReceiverDirective,
],
imports: [
CommonModule,

@ -0,0 +1,8 @@
import { InputReceiverDirective } from './input-receiver.directive';
describe('InputReceiverDirective', () => {
it('should create an instance', () => {
const directive = new InputReceiverDirective();
expect(directive).toBeTruthy();
});
});

@ -0,0 +1,32 @@
import {
Directive,
EventEmitter,
HostBinding,
HostListener,
Output
} from "@angular/core";
@Directive({
selector: "[appInputReceiver]"
})
export class InputReceiverDirective {
constructor() {
}
@Output() keyDownEvent = new EventEmitter<KeyboardEvent>();
@Output() keyUpEvent = new EventEmitter<KeyboardEvent>();
@HostBinding("tabindex") tabIndex = 1;
@HostListener("keydown", ["$event"])
onKeyDown(event: KeyboardEvent) {
this.keyDownEvent.emit(event);
}
@HostListener("keyup", ["$event"])
onKeyUp(event: KeyboardEvent) {
this.keyUpEvent.emit(event);
}
}

@ -1,4 +1,4 @@
<div class="gallery-container" fxLayout="column">
<div class="gallery-container" #inner fxLayout="column" appInputReceiver (keyDownEvent)="handleKeydownEvent($event)">
<button (click)="this.closeEvent.emit(this)" class="close-button" mat-icon-button>
<ng-icon name="mat-close"></ng-icon>
</button>

@ -1,5 +1,6 @@
import {
Component,
AfterContentInit, AfterViewInit,
Component, ElementRef,
EventEmitter,
HostListener,
Input,
@ -21,7 +22,7 @@ import {TabService} from "../../../../../services/tab/tab.service";
templateUrl: "./file-gallery.component.html",
styleUrls: ["./file-gallery.component.scss"]
})
export class FileGalleryComponent implements OnChanges, OnInit {
export class FileGalleryComponent implements OnChanges, OnInit, AfterViewInit {
@Input() files: File[] = [];
@Input() preselectedFile: File | undefined;
@ -31,6 +32,7 @@ export class FileGalleryComponent implements OnChanges, OnInit {
entries: Selectable<File>[] = [];
@ViewChild("virtualScroll") virtualScroll!: CdkVirtualScrollViewport;
@ViewChild("inner") inner!: ElementRef<HTMLDivElement>;
public selectedFile: Selectable<File> | undefined;
public fileContentUrl: SafeResourceUrl | undefined;
@ -50,6 +52,10 @@ export class FileGalleryComponent implements OnChanges, OnInit {
}
}
public ngAfterViewInit(): void {
this.focus();
}
public async ngOnChanges(changes: SimpleChanges): Promise<void> {
if (changes["files"]) {
this.entries = this.files.map(
@ -138,6 +144,24 @@ export class FileGalleryComponent implements OnChanges, OnInit {
}
}
public focus() {
this.inner.nativeElement.focus();
}
public async handleKeydownEvent(event: KeyboardEvent) {
switch (event.key) {
case "ArrowRight":
await this.nextItem();
break;
case "ArrowLeft":
await this.previousItem();
break;
case "Escape":
this.onEscapeClick();
break;
}
}
private scrollToSelection(): void {
if (this.selectedFile) {
const selectedIndex = this.entries.indexOf(this.selectedFile);
@ -174,20 +198,4 @@ export class FileGalleryComponent implements OnChanges, OnInit {
setTimeout(() => this.escapeCount--, 500);
}
}
@HostListener("window:keydown", ["$event"])
private async handleKeydownEvent(event: KeyboardEvent) {
switch (event.key) {
case "ArrowRight":
await this.nextItem();
break;
case "ArrowLeft":
await this.previousItem();
break;
case "Escape":
this.onEscapeClick();
break;
}
}
}

@ -1,4 +1,4 @@
<div class="file-gallery-inner">
<div class="file-gallery-inner" #inner appInputReceiver (keyDownEvent)="handleKeydownEvent($event)" (keyUpEvent)="handleKeyupEvent($event)">
<cdk-virtual-scroll-viewport #virtualScrollGrid class="file-scroll" itemSize="260" maxBufferPx="2000"
minBufferPx="500">
<div *cdkVirtualFor="let rowEntry of partitionedGridEntries">
@ -15,7 +15,7 @@
</div>
<app-file-context-menu #fileContextMenu>
<button (click)="this.fileOpenEvent.emit(fileContextMenu.file)" mat-menu-item content-before>Open</button>
<button (click)="this.fileOpenEvent.emit(fileContextMenu.file)" mat-menu-item content-before="">Open</button>
<button (click)="this.regenerateThumbnail(fileContextMenu.file)" mat-menu-item>Regenerate thumbnail</button>
</app-file-context-menu>

@ -1,4 +1,5 @@
import {
AfterContentInit, AfterViewInit,
Component,
ElementRef,
EventEmitter,
@ -22,7 +23,7 @@ import {Selectable} from "../../../../../models/Selectable";
templateUrl: "./file-grid.component.html",
styleUrls: ["./file-grid.component.scss"]
})
export class FileGridComponent implements OnChanges, OnInit {
export class FileGridComponent implements OnChanges, OnInit, AfterViewInit {
@Input() files: File[] = [];
@Input() columns: number = 6;
@ -31,7 +32,7 @@ export class FileGridComponent implements OnChanges, OnInit {
@Output() fileSelectEvent = new EventEmitter<File[]>();
@ViewChild("virtualScrollGrid") virtualScroll!: CdkVirtualScrollViewport;
@ViewChild("galleryWrapper") galleryWrapper!: ElementRef<HTMLDivElement>;
@ViewChild("inner") inner!: ElementRef<HTMLDivElement>;
selectedEntries: Selectable<File>[] = [];
partitionedGridEntries: Selectable<File>[][] = [];
@ -52,6 +53,10 @@ export class FileGridComponent implements OnChanges, OnInit {
this.setPartitionedGridEntries();
}
public ngAfterViewInit(): void {
this.focus();
}
ngOnChanges(changes: SimpleChanges): void {
if (changes["files"]) {
this.gridEntries = this.files.map(
@ -211,7 +216,6 @@ export class FileGridComponent implements OnChanges, OnInit {
const viewportSize = this.virtualScroll.getViewportSize();
let offsetTop = this.virtualScroll.measureScrollOffset("top");
const contentOffset = Math.floor(selectedIndex / this.columns) * 260;
console.log(offsetTop, contentOffset, viewportSize);
if (contentOffset > offsetTop + viewportSize - 300 || contentOffset < offsetTop) {
this.virtualScroll.scrollToIndex(Math.floor(selectedIndex / this.columns));
@ -224,22 +228,11 @@ export class FileGridComponent implements OnChanges, OnInit {
}
}
private pageDown() {
if (this.virtualScroll) {
const offsetTop = this.virtualScroll.measureScrollOffset("top");
this.virtualScroll.scrollToOffset(offsetTop + this.virtualScroll.getViewportSize());
}
}
private pageUp() {
if (this.virtualScroll) {
const offsetTop = this.virtualScroll.measureScrollOffset("top");
this.virtualScroll.scrollToOffset(offsetTop - this.virtualScroll.getViewportSize());
}
public focus() {
this.inner.nativeElement.focus();
}
@HostListener("window:keydown", ["$event"])
private handleKeydownEvent(event: KeyboardEvent) {
public handleKeydownEvent(event: KeyboardEvent) {
this.shiftClicked ||= event.shiftKey;
this.ctrlClicked ||= event.ctrlKey;
@ -279,9 +272,22 @@ export class FileGridComponent implements OnChanges, OnInit {
}
}
@HostListener("window:keyup", ["$event"])
private handleKeyupEvent(event: KeyboardEvent) {
public handleKeyupEvent(event: KeyboardEvent) {
this.shiftClicked = event.shiftKey? false : this.shiftClicked;
this.ctrlClicked = event.ctrlKey? false : this.ctrlClicked;
}
private pageDown() {
if (this.virtualScroll) {
const offsetTop = this.virtualScroll.measureScrollOffset("top");
this.virtualScroll.scrollToOffset(offsetTop + this.virtualScroll.getViewportSize());
}
}
private pageUp() {
if (this.virtualScroll) {
const offsetTop = this.virtualScroll.measureScrollOffset("top");
this.virtualScroll.scrollToOffset(offsetTop - this.virtualScroll.getViewportSize());
}
}
}

@ -1,7 +1,7 @@
<app-file-grid (fileOpenEvent)="this.onFileOpen($event)" (fileSelectEvent)="this.onFileSelect($event)"
<app-file-grid #fileGrid (fileOpenEvent)="this.onFileOpen($event)" (fileSelectEvent)="this.onFileSelect($event)"
*ngIf="this.mode === 'grid'"
[files]="this.files" [preselectedFile]="this.preselectedFile"></app-file-grid>
<app-file-gallery (closeEvent)="this.mode = 'grid'" (fileSelectEvent)="this.onSinglefileSelect($event)"
<app-file-gallery #fileGallery (closeEvent)="this.mode = 'grid'" (fileSelectEvent)="this.onSinglefileSelect($event)"
*ngIf="this.mode === 'gallery'"
[files]="this.files"
[preselectedFile]="this.preselectedFile"></app-file-gallery>

@ -1,5 +1,14 @@
import {Component, EventEmitter, Input, Output} from "@angular/core";
import {
Component,
ElementRef,
EventEmitter,
Input,
Output,
ViewChild
} from "@angular/core";
import {File} from "../../../../models/File";
import {FileGalleryComponent} from "./file-gallery/file-gallery.component";
import {FileGridComponent} from "./file-grid/file-grid.component";
@Component({
selector: "app-file-multiview",
@ -14,6 +23,9 @@ export class FileMultiviewComponent {
@Output() fileOpenEvent = new EventEmitter<File>();
@Output() fileSelectEvent = new EventEmitter<File[]>();
@ViewChild(FileGalleryComponent) fileGallery!: FileGalleryComponent;
@ViewChild(FileGridComponent) fileGrid!: FileGridComponent;
public selectedFiles: File[] = [];
public preselectedFile: File | undefined;

@ -20,7 +20,6 @@ export class FileService {
}
public async findFiles(filters: FilterExpression[], sortBy: SortKey[]): Promise<File[]> {
console.log(filters);
let backendFilters = filters.map(f => f.toBackendType());
return await invoke<File[]>("plugin:mediarepo|find_files",
{

Loading…
Cancel
Save