feat: display OS-specific modifiers (#764)
* chore: git ignore "out-tsc/" folder in uhk-web package * feat: add OperationSystem calculation to the app reducer * feat: create os specific key modifier * feat: Os specific texts * revert: KeyModifierValues and getKeyModifiers selector * refactor: remove unnecessary return * refactor: rename OperationSystem => OperatingSystem
This commit is contained in:
committed by
László Monda
parent
aba0b09109
commit
3e4d439852
1
packages/uhk-web/.gitignore
vendored
Normal file
1
packages/uhk-web/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
out-tsc/
|
||||||
@@ -43,4 +43,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -29,8 +29,18 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
|||||||
|
|
||||||
constructor(private mapper: MapperService) {
|
constructor(private mapper: MapperService) {
|
||||||
super();
|
super();
|
||||||
this.leftModifiers = ['LShift', 'LCtrl', 'LSuper', 'LAlt'];
|
this.leftModifiers = [
|
||||||
this.rightModifiers = ['RShift', 'RCtrl', 'RSuper', 'RAlt'];
|
'LShift',
|
||||||
|
'LCtrl',
|
||||||
|
mapper.getOsSpecificText('LSuper'),
|
||||||
|
mapper.getOsSpecificText('LAlt')
|
||||||
|
];
|
||||||
|
this.rightModifiers = [
|
||||||
|
'RShift',
|
||||||
|
'RCtrl',
|
||||||
|
mapper.getOsSpecificText('RSuper'),
|
||||||
|
mapper.getOsSpecificText('RAlt')
|
||||||
|
];
|
||||||
this.scanCodeGroups = [{
|
this.scanCodeGroups = [{
|
||||||
id: '0',
|
id: '0',
|
||||||
text: 'None'
|
text: 'None'
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { MapperService } from '../../../../services/mapper.service';
|
|||||||
import { AppState } from '../../../../store';
|
import { AppState } from '../../../../store';
|
||||||
import { getMacros } from '../../../../store/reducers/user-configuration';
|
import { getMacros } from '../../../../store/reducers/user-configuration';
|
||||||
import { SvgKeyCaptureEvent, SvgKeyClickEvent } from '../../../../models/svg-key-events';
|
import { SvgKeyCaptureEvent, SvgKeyClickEvent } from '../../../../models/svg-key-events';
|
||||||
|
import { OperatingSystem } from '../../../../models/operating-system';
|
||||||
|
|
||||||
enum LabelTypes {
|
enum LabelTypes {
|
||||||
KeystrokeKey,
|
KeystrokeKey,
|
||||||
@@ -293,29 +294,32 @@ export class SvgKeyboardKeyComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (keyAction.hasOnlyOneActiveModifier() && !keyAction.hasScancode()) {
|
} else if (keyAction.hasOnlyOneActiveModifier() && !keyAction.hasScancode()) {
|
||||||
newLabelSource = [];
|
|
||||||
switch (keyAction.modifierMask) {
|
switch (keyAction.modifierMask) {
|
||||||
case KeyModifiers.leftCtrl:
|
case KeyModifiers.leftCtrl:
|
||||||
case KeyModifiers.rightCtrl:
|
case KeyModifiers.rightCtrl:
|
||||||
newLabelSource.push('Ctrl');
|
this.labelSource = ['Ctrl'];
|
||||||
break;
|
break;
|
||||||
case KeyModifiers.leftShift:
|
case KeyModifiers.leftShift:
|
||||||
case KeyModifiers.rightShift:
|
case KeyModifiers.rightShift:
|
||||||
newLabelSource.push('Shift');
|
this.labelSource = ['Shift'];
|
||||||
break;
|
break;
|
||||||
case KeyModifiers.leftAlt:
|
case KeyModifiers.leftAlt:
|
||||||
case KeyModifiers.rightAlt:
|
case KeyModifiers.rightAlt:
|
||||||
newLabelSource.push('Alt');
|
this.labelSource = [this.mapper.getOsSpecificText('Alt')];
|
||||||
break;
|
break;
|
||||||
case KeyModifiers.leftGui:
|
case KeyModifiers.leftGui:
|
||||||
case KeyModifiers.rightGui:
|
case KeyModifiers.rightGui:
|
||||||
newLabelSource.push('Super');
|
if (this.mapper.getOperatingSystem() === OperatingSystem.Windows) {
|
||||||
|
this.labelSource = this.mapper.getIcon('command');
|
||||||
|
this.labelType = LabelTypes.SingleIcon;
|
||||||
|
} else {
|
||||||
|
this.labelSource = [this.mapper.getOsSpecificText('Super')];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
newLabelSource.push('Undefined');
|
this.labelSource = ['Undefined'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.labelSource = newLabelSource;
|
|
||||||
} else {
|
} else {
|
||||||
this.labelType = LabelTypes.KeystrokeKey;
|
this.labelType = LabelTypes.KeystrokeKey;
|
||||||
this.labelSource = this.keyAction;
|
this.labelSource = this.keyAction;
|
||||||
|
|||||||
@@ -28,10 +28,12 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<svg viewBox="0 0 100 100" [attr.width]="option.width" [attr.height]="option.height" [attr.x]="option.x" [attr.y]="option.y"
|
<svg viewBox="0 0 100 100" [attr.width]="option.width" [attr.height]="option.height" [attr.x]="option.x" [attr.y]="option.y"
|
||||||
preserveAspectRatio="none" [class.disabled]="option.disabled">
|
preserveAspectRatio="none" [class.disabled]="option.disabled">
|
||||||
<svg:use [attr.xlink:href]="modifierIconNames.option" />
|
<svg:use *ngIf="modifierIconNames.option" [attr.xlink:href]="modifierIconNames.option" />
|
||||||
|
<svg:text *ngIf="!modifierIconNames.option" [attr.text-anchor]="'middle'" [attr.x]="50" [attr.y]="50">A</svg:text>
|
||||||
</svg>
|
</svg>
|
||||||
<svg viewBox="0 0 100 100" [attr.width]="command.width" [attr.height]="command.height" [attr.x]="command.x" [attr.y]="command.y"
|
<svg viewBox="0 0 100 100" [attr.width]="command.width" [attr.height]="command.height" [attr.x]="command.x" [attr.y]="command.y"
|
||||||
preserveAspectRatio="none" [class.disabled]="command.disabled">
|
preserveAspectRatio="none" [class.disabled]="command.disabled">
|
||||||
<svg:use [attr.xlink:href]="modifierIconNames.command" />
|
<svg:use *ngIf="modifierIconNames.command" [attr.xlink:href]="modifierIconNames.command" />
|
||||||
|
<svg:text *ngIf="!modifierIconNames.command" [attr.text-anchor]="'middle'" [attr.x]="50" [attr.y]="50">S</svg:text>
|
||||||
</svg>
|
</svg>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.3 KiB |
5
packages/uhk-web/src/app/models/operating-system.ts
Normal file
5
packages/uhk-web/src/app/models/operating-system.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export enum OperatingSystem {
|
||||||
|
Linux,
|
||||||
|
Mac,
|
||||||
|
Windows
|
||||||
|
}
|
||||||
@@ -1,22 +1,37 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
import { KeystrokeType } from 'uhk-common';
|
import { KeystrokeType } from 'uhk-common';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
|
||||||
|
import { AppState, getOperatingSystem } from '../store';
|
||||||
|
import { OperatingSystem } from '../models/operating-system';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MapperService {
|
export class MapperService {
|
||||||
|
|
||||||
private basicScanCodeTextMap: Map<number, string[]>;
|
private basicScanCodeTextMap: Map<number, string[]>;
|
||||||
private mediaScanCodeTextMap: Map<number, string[]>;
|
private mediaScanCodeTextMap: Map<number, string[]>;
|
||||||
private sytemScanCodeTextMap: Map<number, string[]>;
|
private systemScanCodeTextMap: Map<number, string[]>;
|
||||||
|
|
||||||
private basicScancodeIcons: Map<number, string>;
|
private basicScancodeIcons: Map<number, string>;
|
||||||
private mediaScancodeIcons: Map<number, string>;
|
private mediaScancodeIcons: Map<number, string>;
|
||||||
private systemScancodeIcons: Map<number, string>;
|
private systemScancodeIcons: Map<number, string>;
|
||||||
private nameToFileName: Map<string, string>;
|
private nameToFileName: Map<string, string>;
|
||||||
|
private osSpecificTexts: Map<string, string>;
|
||||||
|
|
||||||
constructor() {
|
private operatingSystem: OperatingSystem;
|
||||||
this.initScanCodeTextMap();
|
private osSubscription: Subscription;
|
||||||
this.initScancodeIcons();
|
|
||||||
this.initNameToFileNames();
|
constructor(private store: Store<AppState>) {
|
||||||
|
this.osSubscription = store
|
||||||
|
.select(getOperatingSystem)
|
||||||
|
.subscribe(os => {
|
||||||
|
this.operatingSystem = os;
|
||||||
|
this.initOsSpecificText();
|
||||||
|
this.initScanCodeTextMap();
|
||||||
|
this.initScancodeIcons();
|
||||||
|
this.initNameToFileNames();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public scanCodeToText(scanCode: number, type: KeystrokeType = KeystrokeType.basic): string[] {
|
public scanCodeToText(scanCode: number, type: KeystrokeType = KeystrokeType.basic): string[] {
|
||||||
@@ -27,7 +42,7 @@ export class MapperService {
|
|||||||
map = this.mediaScanCodeTextMap;
|
map = this.mediaScanCodeTextMap;
|
||||||
break;
|
break;
|
||||||
case KeystrokeType.system:
|
case KeystrokeType.system:
|
||||||
map = this.sytemScanCodeTextMap;
|
map = this.systemScanCodeTextMap;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
map = this.basicScanCodeTextMap;
|
map = this.basicScanCodeTextMap;
|
||||||
@@ -79,7 +94,10 @@ export class MapperService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getIcon(iconName: string): string {
|
public getIcon(iconName: string): string {
|
||||||
return 'assets/compiled_sprite.svg#' + this.nameToFileName.get(iconName);
|
const mappedIconName = this.nameToFileName.get(iconName);
|
||||||
|
if (mappedIconName) {
|
||||||
|
return 'assets/compiled_sprite.svg#' + mappedIconName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public modifierMapper(x: number) {
|
public modifierMapper(x: number) {
|
||||||
@@ -90,6 +108,33 @@ export class MapperService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getOperatingSystem(): OperatingSystem {
|
||||||
|
return this.operatingSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOsSpecificText(key: string): string {
|
||||||
|
const text = this.osSpecificTexts.get(key);
|
||||||
|
|
||||||
|
return text ? text : key;
|
||||||
|
}
|
||||||
|
|
||||||
|
private initOsSpecificText(): void {
|
||||||
|
this.osSpecificTexts = new Map<string, string>();
|
||||||
|
|
||||||
|
if (this.operatingSystem === OperatingSystem.Mac) {
|
||||||
|
this.osSpecificTexts.set('Enter', 'Return');
|
||||||
|
this.osSpecificTexts.set('Alt', 'Option');
|
||||||
|
this.osSpecificTexts.set('Super', 'Cmd');
|
||||||
|
this.osSpecificTexts.set('LSuper', 'LCmd');
|
||||||
|
this.osSpecificTexts.set('RSuper', 'RCmd');
|
||||||
|
this.osSpecificTexts.set('LAlt', 'LOption');
|
||||||
|
this.osSpecificTexts.set('RAlt', 'ROption');
|
||||||
|
} else if (this.operatingSystem === OperatingSystem.Windows) {
|
||||||
|
this.osSpecificTexts.set('LSuper', 'LWindows');
|
||||||
|
this.osSpecificTexts.set('RSuper', 'RWindows');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: read the mapping from JSON
|
// TODO: read the mapping from JSON
|
||||||
private initScanCodeTextMap(): void {
|
private initScanCodeTextMap(): void {
|
||||||
this.basicScanCodeTextMap = new Map<number, string[]>();
|
this.basicScanCodeTextMap = new Map<number, string[]>();
|
||||||
@@ -129,7 +174,7 @@ export class MapperService {
|
|||||||
this.basicScanCodeTextMap.set(37, ['8', '*']);
|
this.basicScanCodeTextMap.set(37, ['8', '*']);
|
||||||
this.basicScanCodeTextMap.set(38, ['9', '(']);
|
this.basicScanCodeTextMap.set(38, ['9', '(']);
|
||||||
this.basicScanCodeTextMap.set(39, ['0', ')']);
|
this.basicScanCodeTextMap.set(39, ['0', ')']);
|
||||||
this.basicScanCodeTextMap.set(40, ['Enter']);
|
this.basicScanCodeTextMap.set(40, [this.getOsSpecificText('Enter')]);
|
||||||
this.basicScanCodeTextMap.set(41, ['Esc']);
|
this.basicScanCodeTextMap.set(41, ['Esc']);
|
||||||
this.basicScanCodeTextMap.set(42, ['Backspace']);
|
this.basicScanCodeTextMap.set(42, ['Backspace']);
|
||||||
this.basicScanCodeTextMap.set(43, ['Tab']);
|
this.basicScanCodeTextMap.set(43, ['Tab']);
|
||||||
@@ -177,7 +222,7 @@ export class MapperService {
|
|||||||
this.basicScanCodeTextMap.set(85, ['*']);
|
this.basicScanCodeTextMap.set(85, ['*']);
|
||||||
this.basicScanCodeTextMap.set(86, ['-']);
|
this.basicScanCodeTextMap.set(86, ['-']);
|
||||||
this.basicScanCodeTextMap.set(87, ['+']);
|
this.basicScanCodeTextMap.set(87, ['+']);
|
||||||
this.basicScanCodeTextMap.set(88, ['Enter']);
|
this.basicScanCodeTextMap.set(88, [this.getOsSpecificText('Enter')]);
|
||||||
this.basicScanCodeTextMap.set(89, ['end', '1']);
|
this.basicScanCodeTextMap.set(89, ['end', '1']);
|
||||||
this.basicScanCodeTextMap.set(90, ['2']);
|
this.basicScanCodeTextMap.set(90, ['2']);
|
||||||
this.basicScanCodeTextMap.set(91, ['pgdn', '3']);
|
this.basicScanCodeTextMap.set(91, ['pgdn', '3']);
|
||||||
@@ -224,10 +269,10 @@ export class MapperService {
|
|||||||
this.mediaScanCodeTextMap.set(394, ['Launch Email Client']);
|
this.mediaScanCodeTextMap.set(394, ['Launch Email Client']);
|
||||||
this.mediaScanCodeTextMap.set(402, ['Launch Calculator']);
|
this.mediaScanCodeTextMap.set(402, ['Launch Calculator']);
|
||||||
|
|
||||||
this.sytemScanCodeTextMap = new Map<number, string[]>();
|
this.systemScanCodeTextMap = new Map<number, string[]>();
|
||||||
this.sytemScanCodeTextMap.set(129, ['Power Down']);
|
this.systemScanCodeTextMap.set(129, ['Power Down']);
|
||||||
this.sytemScanCodeTextMap.set(130, ['Sleep']);
|
this.systemScanCodeTextMap.set(130, ['Sleep']);
|
||||||
this.sytemScanCodeTextMap.set(131, ['Wake Up']);
|
this.systemScanCodeTextMap.set(131, ['Wake Up']);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initScancodeIcons(): void {
|
private initScancodeIcons(): void {
|
||||||
@@ -266,8 +311,12 @@ export class MapperService {
|
|||||||
this.nameToFileName.set('switch-keymap', 'icon-kbd__mod--switch-keymap');
|
this.nameToFileName.set('switch-keymap', 'icon-kbd__mod--switch-keymap');
|
||||||
this.nameToFileName.set('macro', 'icon-icon__macro');
|
this.nameToFileName.set('macro', 'icon-icon__macro');
|
||||||
this.nameToFileName.set('shift', 'icon-kbd__default--modifier-shift');
|
this.nameToFileName.set('shift', 'icon-kbd__default--modifier-shift');
|
||||||
this.nameToFileName.set('option', 'icon-kbd__default--modifier-option');
|
if (this.operatingSystem === OperatingSystem.Mac) {
|
||||||
this.nameToFileName.set('command', 'icon-kbd__default--modifier-command');
|
this.nameToFileName.set('option', 'icon-kbd__default--modifier-option');
|
||||||
|
this.nameToFileName.set('command', 'icon-kbd__default--modifier-command');
|
||||||
|
} else if (this.operatingSystem === OperatingSystem.Windows) {
|
||||||
|
this.nameToFileName.set('command', 'icon-kbd__default--modifier-windows');
|
||||||
|
}
|
||||||
this.nameToFileName.set('mouse', 'icon-kbd__mouse');
|
this.nameToFileName.set('mouse', 'icon-kbd__mouse');
|
||||||
this.nameToFileName.set('left-arrow', 'icon-kbd__mod--arrow-left');
|
this.nameToFileName.set('left-arrow', 'icon-kbd__mod--arrow-left');
|
||||||
this.nameToFileName.set('right-arrow', 'icon-kbd__mod--arrow-right');
|
this.nameToFileName.set('right-arrow', 'icon-kbd__mod--arrow-right');
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import * as fromAppUpdate from './reducers/app-update.reducer';
|
|||||||
import * as autoUpdateSettings from './reducers/auto-update-settings';
|
import * as autoUpdateSettings from './reducers/auto-update-settings';
|
||||||
import * as fromApp from './reducers/app.reducer';
|
import * as fromApp from './reducers/app.reducer';
|
||||||
import * as fromDevice from './reducers/device';
|
import * as fromDevice from './reducers/device';
|
||||||
|
import * as fromSelectors from './reducers/selectors';
|
||||||
import { initProgressButtonState } from './reducers/progress-button-state';
|
import { initProgressButtonState } from './reducers/progress-button-state';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { RouterStateUrl } from './router-util';
|
import { RouterStateUrl } from './router-util';
|
||||||
@@ -52,6 +53,7 @@ export const getKeyboardLayout = createSelector(appState, fromApp.getKeyboardLay
|
|||||||
export const deviceConfigurationLoaded = createSelector(appState, fromApp.deviceConfigurationLoaded);
|
export const deviceConfigurationLoaded = createSelector(appState, fromApp.deviceConfigurationLoaded);
|
||||||
export const getAgentVersionInfo = createSelector(appState, fromApp.getAgentVersionInfo);
|
export const getAgentVersionInfo = createSelector(appState, fromApp.getAgentVersionInfo);
|
||||||
export const getPrivilegePageState = createSelector(appState, fromApp.getPrivilagePageState);
|
export const getPrivilegePageState = createSelector(appState, fromApp.getPrivilagePageState);
|
||||||
|
export const getOperatingSystem = createSelector(appState, fromSelectors.getOperatingSystem);
|
||||||
export const runningOnNotSupportedWindows = createSelector(appState, fromApp.runningOnNotSupportedWindows);
|
export const runningOnNotSupportedWindows = createSelector(appState, fromApp.runningOnNotSupportedWindows);
|
||||||
export const firmwareUpgradeAllowed = createSelector(runningOnNotSupportedWindows, notSupportedOs => !notSupportedOs);
|
export const firmwareUpgradeAllowed = createSelector(runningOnNotSupportedWindows, notSupportedOs => !notSupportedOs);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { OperatingSystem } from '../../models/operating-system';
|
||||||
|
import { State } from './app.reducer';
|
||||||
|
|
||||||
|
export const getOperatingSystem = (state: State): OperatingSystem => {
|
||||||
|
if (state.runningInElectron) {
|
||||||
|
switch (state.platform) {
|
||||||
|
case 'darwin':
|
||||||
|
return OperatingSystem.Mac;
|
||||||
|
|
||||||
|
case 'win32':
|
||||||
|
return OperatingSystem.Windows;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return OperatingSystem.Linux;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const platform = navigator.platform.toLowerCase();
|
||||||
|
|
||||||
|
if (platform.indexOf('mac') > -1) {
|
||||||
|
return OperatingSystem.Mac;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform.indexOf('win') > -1) {
|
||||||
|
return OperatingSystem.Windows;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OperatingSystem.Linux;
|
||||||
|
};
|
||||||
1
packages/uhk-web/src/app/store/reducers/selectors.ts
Normal file
1
packages/uhk-web/src/app/store/reducers/selectors.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './get-operating-system.selector';
|
||||||
Reference in New Issue
Block a user