Add hotkey help dialog, auto-meta key for macOS

This commit is contained in:
shamoon
2024-04-04 22:04:20 -07:00
parent 5bb577ab20
commit 2a818162d7
10 changed files with 182 additions and 15 deletions

View File

@@ -7,7 +7,6 @@
autocomplete="off" spellcheck="false"
[(ngModel)]="query" (ngModelChange)="this.queryDebounce.next($event)" (keydown)="searchInputKeyDown($event)" ngbDropdownAnchor>
<div class="position-absolute top-50 end-0 translate-middle">
<span class="badge d-none d-lg-inline text-muted position-absolute top-50 start-100 translate-middle ms-n4 fw-normal">⌘K</span>
@if (loading) {
<div class="spinner-border spinner-border-sm text-muted mt-1"></div>
}

View File

@@ -87,12 +87,11 @@ export class GlobalSearchComponent implements OnInit {
}
ngOnInit() {
this.hotkeyService.addShortcut({ keys: 'meta.k' }).subscribe(() => {
this.searchInput.nativeElement.focus()
})
this.hotkeyService.addShortcut({ keys: 'control.k' }).subscribe(() => {
this.searchInput.nativeElement.focus()
})
this.hotkeyService
.addShortcut({ keys: 'control.k', description: $localize`Global search` })
.subscribe(() => {
this.searchInput.nativeElement.focus()
})
}
private search(query: string) {

View File

@@ -0,0 +1,23 @@
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
<button type="button" class="btn-close" aria-label="Close" (click)="close()"></button>
</div>
<div class="modal-body">
<table class="table">
<tbody>
@for (key of hotkeys.entries(); track key[0]) {
<tr>
<td>{{ key[1] }}</td>
<td class="d-flex justify-content-end">
<kbd [innerHTML]="formatKey(key[0])"></kbd>
@if (key[0].includes('control')) {
&nbsp;(macOS&nbsp;<kbd [innerHTML]="formatKey(key[0], true)"></kbd>)
}
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="modal-footer">
</div>

View File

@@ -0,0 +1,35 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { HotkeyDialogComponent } from './hotkey-dialog.component'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
describe('HotkeyDialogComponent', () => {
let component: HotkeyDialogComponent
let fixture: ComponentFixture<HotkeyDialogComponent>
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [HotkeyDialogComponent],
providers: [NgbActiveModal],
}).compileComponents()
fixture = TestBed.createComponent(HotkeyDialogComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
it('should create', () => {
expect(component).toBeTruthy()
})
it('should support close', () => {
const closeSpy = jest.spyOn(component.activeModal, 'close')
component.close()
expect(closeSpy).toHaveBeenCalled()
})
it('should format keys', () => {
expect(component.formatKey('control.a')).toEqual('&#8963; + a') // ⌃ + a
expect(component.formatKey('control.a', true)).toEqual('&#8984; + a') // ⌘ + a
})
})

View File

@@ -0,0 +1,34 @@
import { Component } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
const SYMBOLS = {
meta: '&#8984;', // ⌘
control: '&#8963;', // ⌃
shift: '&#8679;', // ⇧
}
@Component({
selector: 'pngx-hotkey-dialog',
templateUrl: './hotkey-dialog.component.html',
styleUrl: './hotkey-dialog.component.scss',
})
export class HotkeyDialogComponent {
public title: string = $localize`Keyboard shortcuts`
public hotkeys: Map<string, string> = new Map()
constructor(public activeModal: NgbActiveModal) {}
public close(): void {
this.activeModal.close()
}
public formatKey(key: string, macOS: boolean = false): string {
if (macOS) {
key = key.replace('control', 'meta')
}
return key
.split('.')
.map((k) => SYMBOLS[k] || k)
.join(' + ')
}
}