diff --git a/packages/uhk-common/src/config-serializer/config-items/user-configuration.ts b/packages/uhk-common/src/config-serializer/config-items/user-configuration.ts index 67dd09cf..29880f96 100644 --- a/packages/uhk-common/src/config-serializer/config-items/user-configuration.ts +++ b/packages/uhk-common/src/config-serializer/config-items/user-configuration.ts @@ -1,9 +1,11 @@ -import { assertUInt8, assertUInt16 } from '../assert'; +import { assertUInt16, assertUInt8 } from '../assert'; import { UhkBuffer } from '../uhk-buffer'; import { Keymap } from './keymap'; import { Macro } from './macro'; import { ModuleConfiguration } from './module-configuration'; import { ConfigSerializer } from '../config-serializer'; +import { KeystrokeAction } from './key-action'; +import { SecondaryRoleAction } from './secondary-role-action'; export class UserConfiguration { @@ -102,7 +104,9 @@ export class UserConfiguration { return macro; }); this.keymaps = jsonObject.keymaps.map((keymap: any) => new Keymap().fromJsonObject(keymap, this.macros)); + this.clean(); this.recalculateConfigurationLength(); + return this; } @@ -138,6 +142,8 @@ export class UserConfiguration { this.keymaps = buffer.readArray(uhkBuffer => new Keymap().fromBinary(uhkBuffer, this.macros)); ConfigSerializer.resolveSwitchKeymapActions(this.keymaps); + this.clean(); + if (this.userConfigurationLength === 0) { this.recalculateConfigurationLength(); } @@ -222,4 +228,30 @@ export class UserConfiguration { this.deviceName = 'My UHK'; } } + + /* Remove not allowed settings/bugs + * 1. Layer Switcher secondary roles allowed only on base layers + */ + private clean(): void { + for (const keymap of this.keymaps) { + for (let layerId = 1; layerId < keymap.layers.length; layerId++) { + const layer = keymap.layers[layerId]; + + for (const module of layer.modules) { + for (let keyActionId = 0; keyActionId < module.keyActions.length; keyActionId++) { + const keyAction = module.keyActions[keyActionId]; + if (!keyAction || !(keyAction instanceof KeystrokeAction)) { + continue; + } + + if (keyAction.secondaryRoleAction === SecondaryRoleAction.fn || + keyAction.secondaryRoleAction === SecondaryRoleAction.mod || + keyAction.secondaryRoleAction === SecondaryRoleAction.mouse) { + (keyAction as any)._secondaryRoleAction = undefined; + } + } + } + } + } + } } diff --git a/packages/uhk-web/src/app/components/popover/popover.component.html b/packages/uhk-web/src/app/components/popover/popover.component.html index 0cbc25c5..07dc9ab3 100644 --- a/packages/uhk-web/src/app/components/popover/popover.component.html +++ b/packages/uhk-web/src/app/components/popover/popover.component.html @@ -48,11 +48,13 @@
-
diff --git a/packages/uhk-web/src/app/components/popover/popover.component.scss b/packages/uhk-web/src/app/components/popover/popover.component.scss index 1be4d3c7..b2e543e1 100644 --- a/packages/uhk-web/src/app/components/popover/popover.component.scss +++ b/packages/uhk-web/src/app/components/popover/popover.component.scss @@ -125,5 +125,10 @@ label { margin-right: 5px; + + &.disabled { + cursor: not-allowed; + color: #959595; + } } } diff --git a/packages/uhk-web/src/app/components/popover/popover.component.ts b/packages/uhk-web/src/app/components/popover/popover.component.ts index ecf6a09a..f22b8070 100644 --- a/packages/uhk-web/src/app/components/popover/popover.component.ts +++ b/packages/uhk-web/src/app/components/popover/popover.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectionStrategy, + ChangeDetectorRef, Component, ElementRef, EventEmitter, @@ -24,6 +25,7 @@ import { KeystrokeAction, MouseAction, PlayMacroAction, + SecondaryRoleAction, SwitchKeymapAction, SwitchLayerAction } from 'uhk-common'; @@ -104,10 +106,13 @@ export class PopoverComponent implements OnChanges { topPosition: number = 0; leftPosition: number = 0; animationState: string; + shadowKeyAction: KeyAction; + disableRemapOnAllLayer = false; private readonly currentKeymap$ = new BehaviorSubject(undefined); - constructor(store: Store) { + constructor(private store: Store, + private cdRef: ChangeDetectorRef) { this.animationState = 'closed'; this.keymaps$ = store.let(getKeymaps()) .combineLatest(this.currentKeymap$) @@ -123,8 +128,10 @@ export class PopoverComponent implements OnChanges { if (change['defaultKeyAction']) { let tab: TabName; + this.disableRemapOnAllLayer = false; if (this.defaultKeyAction instanceof KeystrokeAction) { + this.keystrokeActionChange(this.defaultKeyAction); tab = TabName.Keypress; } else if (this.defaultKeyAction instanceof SwitchLayerAction) { tab = TabName.Layer; @@ -188,6 +195,9 @@ export class PopoverComponent implements OnChanges { selectTab(tab: TabName): void { this.activeTab = tab; + if (tab === TabName.Keypress) { + this.keystrokeActionChange(this.defaultKeyAction as KeystrokeAction); + } } onOverlay() { @@ -198,6 +208,26 @@ export class PopoverComponent implements OnChanges { this.selectedTab.remapInfoChanged(this.remapInfo); } + keystrokeActionChange(keystrokeAction: KeystrokeAction): void { + this.shadowKeyAction = keystrokeAction; + const disableRemapOnAllLayer = + keystrokeAction && + this.currentLayer === 0 && + (keystrokeAction.secondaryRoleAction === SecondaryRoleAction.fn || + keystrokeAction.secondaryRoleAction === SecondaryRoleAction.mod || + keystrokeAction.secondaryRoleAction === SecondaryRoleAction.mouse); + + if (this.disableRemapOnAllLayer !== disableRemapOnAllLayer) { + this.disableRemapOnAllLayer = disableRemapOnAllLayer; + + if (disableRemapOnAllLayer) { + this.remapInfo.remapOnAllLayer = false; + } + + this.cdRef.markForCheck(); + } + } + private calculatePosition() { const offsetLeft: number = this.wrapPosition.left + 265; // 265 is a width of the side menu with a margin const popover: HTMLElement = this.popoverHost.nativeElement; diff --git a/packages/uhk-web/src/app/components/popover/tab/keypress/keypress-tab.component.ts b/packages/uhk-web/src/app/components/popover/tab/keypress/keypress-tab.component.ts index 9441f447..58e789ea 100644 --- a/packages/uhk-web/src/app/components/popover/tab/keypress/keypress-tab.component.ts +++ b/packages/uhk-web/src/app/components/popover/tab/keypress/keypress-tab.component.ts @@ -1,4 +1,13 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges } from '@angular/core'; +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnChanges, + Output, + SimpleChanges +} from '@angular/core'; import { KeyAction, KeystrokeAction, KeystrokeType, SCANCODES, SECONDARY_ROLES } from 'uhk-common'; import { Tab } from '../tab'; @@ -8,6 +17,16 @@ import { KeyModifierModel } from '../../../../models/key-modifier-model'; import { mapLeftRigthModifierToKeyActionModifier } from '../../../../util'; import { RemapInfo } from '../../../../models/remap-info'; +export const secondaryRoleFilter = (showLayerSwitchers: boolean) => { + return (data): boolean => { + if (showLayerSwitchers) { + return data; + } + + return data.text !== 'Layer switcher'; + }; +}; + @Component({ selector: 'keypress-tab', changeDetection: ChangeDetectionStrategy.OnPush, @@ -19,12 +38,15 @@ export class KeypressTabComponent extends Tab implements OnChanges { @Input() secondaryRoleEnabled: boolean; @Input() allowRemapOnAllKeymapWarning: boolean; @Input() remapInfo: RemapInfo; + @Input() showLayerSwitcherInSecondaryRoles: boolean; + + @Output() keyActionChange = new EventEmitter(); leftModifiers: KeyModifierModel[]; rightModifiers: KeyModifierModel[]; scanCodeGroups: Array; - secondaryRoleGroups: Array; + secondaryRoleGroups: Array = []; selectedScancodeOption: SelectOptionData; selectedSecondaryRoleIndex: number; @@ -41,14 +63,16 @@ export class KeypressTabComponent extends Tab implements OnChanges { text: 'None' }]; this.scanCodeGroups = this.scanCodeGroups.concat(SCANCODES); - this.secondaryRoleGroups = SECONDARY_ROLES; this.selectedScancodeOption = this.scanCodeGroups[0]; this.selectedSecondaryRoleIndex = -1; } - ngOnChanges() { + ngOnChanges(changes: SimpleChanges) { + if (changes.showLayerSwitcherInSecondaryRoles) { + this.fillSecondaryRoles(); + } this.fromKeyAction(this.defaultKeyAction); - this.keyActionChanged(); + this.keyActionChanged(false); } keyActionValid(keystrokeAction?: KeystrokeAction): boolean { @@ -124,6 +148,7 @@ export class KeypressTabComponent extends Tab implements OnChanges { onSecondaryRoleChange(id: string) { this.selectedSecondaryRoleIndex = +id; + this.keyActionChanged(); } onScancodeChange(id: string) { @@ -200,10 +225,14 @@ export class KeypressTabComponent extends Tab implements OnChanges { return [scanCode, type]; } - private keyActionChanged(): void { + private keyActionChanged(dispatch = true): void { const keystrokeAction = this.toKeyAction(); this.validAction.emit(this.keyActionValid(keystrokeAction)); this.calculateRemapOnAllLayerWarningVisibility(keystrokeAction); + + if (dispatch) { + this.keyActionChange.emit(keystrokeAction); + } } private calculateRemapOnAllLayerWarningVisibility(keystrokeAction: KeystrokeAction): void { @@ -214,4 +243,9 @@ export class KeypressTabComponent extends Tab implements OnChanges { !keystrokeAction.hasScancode() && keystrokeAction.hasOnlyOneActiveModifier(); } + + private fillSecondaryRoles(): void { + this.secondaryRoleGroups = SECONDARY_ROLES + .filter(secondaryRoleFilter(this.showLayerSwitcherInSecondaryRoles)); + } }