feat: Display/hide left keyboard half and merged/unmerged state (#987)
* feat: Display/hide left keyboard half and merged/unmerged state * feat: improve the animation * feat: decrease left fade animation time
This commit is contained in:
committed by
László Monda
parent
a409c219d8
commit
cbccaba1c5
@@ -1,7 +1,7 @@
|
||||
<svg-keyboard *ngFor="let layer of layers; let index = index; trackBy: trackKeyboard"
|
||||
[@layerState]="layerAnimationState[index]"
|
||||
[moduleConfig]="layer.modules"
|
||||
[halvesSplit]="halvesSplit"
|
||||
[halvesInfo]="halvesInfo"
|
||||
[capturingEnabled]="capturingEnabled"
|
||||
[selectedKey]="selectedKey"
|
||||
[selected]="selectedKey?.layerId === index"
|
||||
|
||||
|
Before Width: | Height: | Size: 833 B After Width: | Height: | Size: 831 B |
@@ -1,5 +1,5 @@
|
||||
svg-keyboard {
|
||||
width: 95%;
|
||||
width: 99%;
|
||||
max-width: 1400px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { animate, keyframes, state, style, transition, trigger } from '@angular/animations';
|
||||
import { Layer } from 'uhk-common';
|
||||
import { HalvesInfo, Layer } from 'uhk-common';
|
||||
|
||||
import { KeyboardLayout } from '../../../keyboard/keyboard-layout.enum';
|
||||
import {
|
||||
@@ -83,7 +83,7 @@ export class KeyboardSliderComponent implements OnChanges {
|
||||
@Input() layers: Layer[];
|
||||
@Input() currentLayer: number;
|
||||
@Input() capturingEnabled: boolean;
|
||||
@Input() halvesSplit: boolean;
|
||||
@Input() halvesInfo: HalvesInfo;
|
||||
@Input() selectedKey: { layerId: number, moduleId: number, keyId: number };
|
||||
@Input() keyboardLayout = KeyboardLayout.ANSI;
|
||||
@Input() description: string;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[deletable]="deletable$ | async"
|
||||
(downloadClick)="downloadKeymap()"></keymap-header>
|
||||
<svg-keyboard-wrap [keymap]="keymap"
|
||||
[halvesSplit]="keyboardSplit"
|
||||
[halvesInfo]="halvesInfo$ | async"
|
||||
[keyboardLayout]="keyboardLayout$ | async"
|
||||
[allowLayerDoubleTap]="allowLayerDoubleTap$ | async"
|
||||
[lastEditedKey]="lastEditedKey$ | async"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, OnDestroy } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Keymap } from 'uhk-common';
|
||||
import { HalvesInfo, Keymap } from 'uhk-common';
|
||||
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { combineLatest, first, map, pluck, switchMap } from 'rxjs/operators';
|
||||
@@ -15,7 +15,8 @@ import {
|
||||
layerDoubleTapSupported,
|
||||
AppState,
|
||||
getKeyboardLayout,
|
||||
lastEditedKey
|
||||
lastEditedKey,
|
||||
getHalvesInfo
|
||||
} from '../../../store';
|
||||
import { KeyboardLayout } from '../../../keyboard/keyboard-layout.enum';
|
||||
import { EditDescriptionAction, SelectKeymapAction } from '../../../store/actions/keymap';
|
||||
@@ -33,13 +34,12 @@ import { LastEditedKey } from '../../../models';
|
||||
})
|
||||
export class KeymapEditComponent implements OnDestroy {
|
||||
|
||||
keyboardSplit: boolean;
|
||||
|
||||
deletable$: Observable<boolean>;
|
||||
keymap$: Observable<Keymap>;
|
||||
keyboardLayout$: Observable<KeyboardLayout>;
|
||||
allowLayerDoubleTap$: Observable<boolean>;
|
||||
lastEditedKey$: Observable<LastEditedKey>;
|
||||
halvesInfo$: Observable<HalvesInfo>;
|
||||
keymap: Keymap;
|
||||
|
||||
private routeSubscription: Subscription;
|
||||
@@ -67,6 +67,7 @@ export class KeymapEditComponent implements OnDestroy {
|
||||
this.keyboardLayout$ = store.select(getKeyboardLayout);
|
||||
this.allowLayerDoubleTap$ = store.select(layerDoubleTapSupported);
|
||||
this.lastEditedKey$ = store.select(lastEditedKey);
|
||||
this.halvesInfo$ = store.select(getHalvesInfo);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -94,11 +95,6 @@ export class KeymapEditComponent implements OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('window:keydown.alt.s', ['$event'])
|
||||
toggleKeyboardSplit() {
|
||||
this.keyboardSplit = !this.keyboardSplit;
|
||||
}
|
||||
|
||||
descriptionChanged(event: ChangeKeymapDescription): void {
|
||||
this.store.dispatch(new EditDescriptionAction(event));
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[keyActions]="moduleConfig[i].keyActions"
|
||||
[selectedKey]="selectedKey"
|
||||
[@split]="moduleAnimationStates[i]"
|
||||
[@fadeKeyboard]="moduleVisibilityAnimationStates[i]"
|
||||
[selected]="selectedKey?.moduleId === i"
|
||||
[lastEdited]="lastEditedKey?.moduleId === i"
|
||||
[lastEditedKeyId]="lastEditedKey?.key"
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -1,7 +1,7 @@
|
||||
import { Component, EventEmitter, Input, Output, SimpleChanges, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { animate, state, trigger, style, transition } from '@angular/animations';
|
||||
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
|
||||
import { Module } from 'uhk-common';
|
||||
import { HalvesInfo, Module } from 'uhk-common';
|
||||
|
||||
import { SvgModule } from '../module';
|
||||
import { SvgModuleProviderService } from '../../../services/svg-module-provider.service';
|
||||
@@ -23,13 +23,23 @@ import { LastEditedKey } from '../../../models';
|
||||
animations: [
|
||||
trigger('split', [
|
||||
state('rotateLeft', style({
|
||||
transform: 'translate(-3%, 15%) rotate(4deg) scale(0.92, 0.92)'
|
||||
transform: 'translate(2%, 30%) rotate(10.8deg) scale(0.80, 0.80)'
|
||||
})),
|
||||
state('rotateRight', style({
|
||||
transform: 'translate(3%, 15%) rotate(-4deg) scale(0.92, 0.92)'
|
||||
transform: 'translate(-2%, 30.7%) rotate(-10deg) scale(0.80, 0.80)'
|
||||
})),
|
||||
transition('* <=> *', animate(500))
|
||||
]),
|
||||
trigger('fadeKeyboard', [
|
||||
state('visible', style({
|
||||
opacity: 1
|
||||
})),
|
||||
state('invisible', style({
|
||||
opacity: 0
|
||||
})),
|
||||
transition('visible => invisible', animate(500)),
|
||||
transition('invisible => visible', animate(500))
|
||||
]),
|
||||
trigger('fadeSeparator', [
|
||||
state('visible', style({
|
||||
opacity: 1
|
||||
@@ -37,8 +47,8 @@ import { LastEditedKey } from '../../../models';
|
||||
state('invisible', style({
|
||||
opacity: 0
|
||||
})),
|
||||
transition('visible => invisible', animate(500)),
|
||||
transition('invisible => visible', animate(1500))
|
||||
transition('visible => invisible', animate('200ms')),
|
||||
transition('invisible => visible', animate('200ms 500ms'))
|
||||
])
|
||||
]
|
||||
})
|
||||
@@ -47,7 +57,7 @@ export class SvgKeyboardComponent {
|
||||
@Input() capturingEnabled: boolean;
|
||||
@Input() selectedKey: { layerId: number, moduleId: number, keyId: number };
|
||||
@Input() selected: boolean;
|
||||
@Input() halvesSplit: boolean;
|
||||
@Input() halvesInfo: HalvesInfo;
|
||||
@Input() keyboardLayout = KeyboardLayout.ANSI;
|
||||
@Input() description: string;
|
||||
@Input() showDescription = false;
|
||||
@@ -60,6 +70,7 @@ export class SvgKeyboardComponent {
|
||||
modules: SvgModule[];
|
||||
viewBox: string;
|
||||
moduleAnimationStates: string[];
|
||||
moduleVisibilityAnimationStates: string[];
|
||||
separator: SvgSeparator;
|
||||
separatorStyle: SafeStyle;
|
||||
separatorAnimation = 'visible';
|
||||
@@ -68,7 +79,6 @@ export class SvgKeyboardComponent {
|
||||
private sanitizer: DomSanitizer) {
|
||||
this.modules = [];
|
||||
this.viewBox = '-520 582 1100 470';
|
||||
this.halvesSplit = false;
|
||||
this.moduleAnimationStates = [];
|
||||
}
|
||||
|
||||
@@ -77,7 +87,7 @@ export class SvgKeyboardComponent {
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes.halvesSplit) {
|
||||
if (changes.halvesInfo) {
|
||||
this.updateModuleAnimationStates();
|
||||
}
|
||||
|
||||
@@ -110,12 +120,19 @@ export class SvgKeyboardComponent {
|
||||
}
|
||||
|
||||
private updateModuleAnimationStates() {
|
||||
if (this.halvesSplit) {
|
||||
this.moduleAnimationStates = ['rotateRight', 'rotateLeft'];
|
||||
this.separatorAnimation = 'invisible';
|
||||
} else {
|
||||
if (this.halvesInfo.areHalvesMerged) {
|
||||
this.moduleAnimationStates = [];
|
||||
this.separatorAnimation = 'visible';
|
||||
} else {
|
||||
this.moduleAnimationStates = ['rotateRight', 'rotateLeft'];
|
||||
this.separatorAnimation = 'invisible';
|
||||
}
|
||||
|
||||
if (this.halvesInfo.isLeftHalfConnected) {
|
||||
this.moduleVisibilityAnimationStates = ['visible', 'visible'];
|
||||
} else {
|
||||
this.moduleVisibilityAnimationStates = ['visible', 'invisible'];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[currentLayer]="currentLayer"
|
||||
[capturingEnabled]="popoverEnabled"
|
||||
[selectedKey]="selectedKey"
|
||||
[halvesSplit]="halvesSplit"
|
||||
[halvesInfo]="halvesInfo"
|
||||
[keyboardLayout]="keyboardLayout"
|
||||
[description]="keymap.description"
|
||||
[lastEditedKey]="lastEditedKey"
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Store } from '@ngrx/store';
|
||||
import {
|
||||
camelCaseToSentence,
|
||||
capitalizeFirstLetter,
|
||||
HalvesInfo,
|
||||
KeyAction,
|
||||
Keymap,
|
||||
KeystrokeAction,
|
||||
@@ -65,7 +66,7 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges {
|
||||
@Input() keymap: Keymap;
|
||||
@Input() popoverEnabled: boolean = true;
|
||||
@Input() tooltipEnabled: boolean = false;
|
||||
@Input() halvesSplit: boolean;
|
||||
@Input() halvesInfo: HalvesInfo;
|
||||
@Input() keyboardLayout: KeyboardLayout.ANSI;
|
||||
@Input() allowLayerDoubleTap: boolean;
|
||||
@Input() lastEditedKey: LastEditedKey;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Router } from '@angular/router';
|
||||
import { Action, Store } from '@ngrx/store';
|
||||
import { Actions, Effect, ofType } from '@ngrx/effects';
|
||||
import { EMPTY, Observable, of, timer } from 'rxjs';
|
||||
import { map, mergeMap, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { distinctUntilChanged, map, mergeMap, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
import {
|
||||
FirmwareUpgradeIpcResponse,
|
||||
@@ -73,6 +73,14 @@ export class DeviceEffects {
|
||||
|
||||
return this.router.navigate(['/detection']);
|
||||
}),
|
||||
distinctUntilChanged((
|
||||
[prevAction, prevRoute, prevConnected],
|
||||
[currAction, currRoute, currConnected]) => {
|
||||
|
||||
return prevConnected === currConnected &&
|
||||
prevAction.payload.hasPermission === currAction.payload.hasPermission &&
|
||||
prevAction.payload.zeroInterfaceAvailable === currAction.payload.zeroInterfaceAvailable;
|
||||
}),
|
||||
switchMap(([action, route, connected]) => {
|
||||
const payload = action.payload;
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ export const bootloaderActive = createSelector(deviceState, fromDevice.bootloade
|
||||
export const firmwareUpgradeFailed = createSelector(deviceState, fromDevice.firmwareUpgradeFailed);
|
||||
export const firmwareUpgradeSuccess = createSelector(deviceState, fromDevice.firmwareUpgradeSuccess);
|
||||
export const getUpdateUdevRules = createSelector(deviceState, fromDevice.updateUdevRules);
|
||||
export const getHalvesInfo = createSelector(deviceState, fromDevice.halvesInfo);
|
||||
|
||||
export const getPrivilegePageState = createSelector(appState, getUpdateUdevRules, (app, updateUdevRules): PrivilagePageSate => {
|
||||
const permissionSetupFailed = !!app.permissionError;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { HardwareModules, UdevRulesInfo } from 'uhk-common';
|
||||
import { HardwareModules, UdevRulesInfo, HalvesInfo } from 'uhk-common';
|
||||
|
||||
import * as Device from '../actions/device';
|
||||
import * as App from '../actions/app';
|
||||
@@ -24,6 +24,7 @@ export interface State {
|
||||
log: Array<XtermLog>;
|
||||
restoringUserConfiguration: boolean;
|
||||
hasBackupUserConfiguration: boolean;
|
||||
halvesInfo: HalvesInfo;
|
||||
}
|
||||
|
||||
export const initialState: State = {
|
||||
@@ -47,7 +48,8 @@ export const initialState: State = {
|
||||
},
|
||||
log: [{ message: '', cssClass: XtermCssClass.standard }],
|
||||
restoringUserConfiguration: false,
|
||||
hasBackupUserConfiguration: false
|
||||
hasBackupUserConfiguration: false,
|
||||
halvesInfo: { isLeftHalfConnected: true, areHalvesMerged: true }
|
||||
};
|
||||
|
||||
export function reducer(state = initialState, action: Action): State {
|
||||
@@ -60,7 +62,8 @@ export function reducer(state = initialState, action: Action): State {
|
||||
hasPermission: data.hasPermission,
|
||||
zeroInterfaceAvailable: data.zeroInterfaceAvailable,
|
||||
bootloaderActive: data.bootloaderActive,
|
||||
udevRuleInfo: data.udevRulesInfo
|
||||
udevRuleInfo: data.udevRulesInfo,
|
||||
halvesInfo: data.halvesInfo
|
||||
};
|
||||
}
|
||||
|
||||
@@ -249,3 +252,4 @@ export const bootloaderActive = (state: State) => state.bootloaderActive;
|
||||
export const firmwareUpgradeFailed = (state: State) => state.firmwareUpdateFailed;
|
||||
export const firmwareUpgradeSuccess = (state: State) => state.firmwareUpdateSuccess;
|
||||
export const updateUdevRules = (state: State) => state.udevRuleInfo === UdevRulesInfo.Different;
|
||||
export const halvesInfo = (state: State) => state.halvesInfo;
|
||||
|
||||
Reference in New Issue
Block a user