Skip to content

Commit 4ff0bf5

Browse files
authored
feat: advanced-settings/change keyboard layout (#1958)
1 parent d11db5b commit 4ff0bf5

File tree

12 files changed

+217
-30
lines changed

12 files changed

+217
-30
lines changed

packages/uhk-agent/src/services/device.service.ts

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ipcMain } from 'electron';
22
import { cloneDeep, isEqual } from 'lodash';
33
import {
4+
ChangeKeyboardLayoutIpcResponse,
45
CommandLineArgs,
56
ConfigurationReply,
67
DeviceConnectionState,
@@ -13,25 +14,28 @@ import {
1314
IpcEvents,
1415
IpcResponse,
1516
isDeviceProtocolSupportGitInfo,
17+
KeyboardLayout,
1618
LEFT_HALF_MODULE,
1719
LeftSlotModules,
1820
LogService,
1921
mapObjectToUserConfigBinaryBuffer,
2022
ModuleInfo,
2123
ModuleSlotToId,
22-
SaveUserConfigurationData,
23-
UpdateFirmwareData,
24-
UploadFileData,
25-
UHK_MODULES,
26-
RightSlotModules,
2724
RIGHT_HALF_FIRMWARE_UPGRADE_MODULE_NAME,
25+
RightSlotModules,
26+
SaveUserConfigurationData,
2827
shouldUpgradeAgent,
2928
shouldUpgradeFirmware,
3029
simulateInvalidUserConfigError,
30+
UHK_MODULES,
31+
UpdateFirmwareData,
32+
UploadFileData,
3133
VersionInformation
3234
} from 'uhk-common';
3335
import {
3436
checkFirmwareAndDeviceCompatibility,
37+
ConfigBufferId,
38+
convertBufferToIntArray,
3539
getCurrentUhkDeviceProduct,
3640
getCurrentUhkDeviceProductByBootloaderId,
3741
getDeviceFirmwarePath,
@@ -93,6 +97,15 @@ export class DeviceService {
9397
this.logService.misc('[DeviceService] Cannot query udev info:', error);
9498
});
9599

100+
ipcMain.on(IpcEvents.device.changeKeyboardLayout, (...args: any[]) => {
101+
this.queueManager.add({
102+
method: this.changeKeyboardLayout,
103+
bind: this,
104+
params: args,
105+
asynchronous: true
106+
});
107+
});
108+
96109
ipcMain.on(IpcEvents.device.toggleI2cDebugging, this.toggleI2cDebugging.bind(this));
97110

98111
ipcMain.on(IpcEvents.device.saveUserConfiguration, (...args: any[]) => {
@@ -521,6 +534,34 @@ export class DeviceService {
521534
});
522535
}
523536

537+
private async changeKeyboardLayout(event: Electron.IpcMainEvent, [layout, deviceId]): Promise<void> {
538+
const layoutName = layout === KeyboardLayout.ISO ? 'iso': 'ansi';
539+
540+
this.logService.misc(`[DeviceService] Change keyboard layout to ${layoutName}`);
541+
const response = new ChangeKeyboardLayoutIpcResponse();
542+
543+
try {
544+
await this.stopPollUhkDevice();
545+
546+
await this.operations.saveHardwareConfiguration(layout === KeyboardLayout.ISO, deviceId);
547+
548+
const hardwareInfo = await this.operations.loadConfiguration(ConfigBufferId.hardwareConfig);
549+
response.hardwareConfig = JSON.stringify(convertBufferToIntArray(hardwareInfo));
550+
response.success = true;
551+
552+
this.logService.misc('[DeviceService] Keyboard layout changed to', layoutName);
553+
} catch (error) {
554+
this.logService.error('[DeviceService] Change keyboard layout error', error);
555+
556+
response.success = false;
557+
response.error = { message: error.message };
558+
} finally {
559+
this.startPollUhkDevice();
560+
}
561+
562+
event.sender.send(IpcEvents.device.changeKeyboardLayoutReply, response);
563+
}
564+
524565
/**
525566
* HID API not support device attached and detached event.
526567
* This method check the keyboard is attached to the computer or not.

packages/uhk-common/src/models/ipc-response.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ export class IpcResponse {
55
error?: { message: string };
66
}
77

8+
export class ChangeKeyboardLayoutIpcResponse extends IpcResponse {
9+
hardwareConfig: string;
10+
}
11+
812
export enum FirmwareUpgradeFailReason {
913
UserConfigVersionNotSupported = 'UserConfigVersionNotSupported'
1014
}

packages/uhk-common/src/util/ipcEvents.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export class AutoUpdate {
2121
}
2222

2323
export class Device {
24+
public static readonly changeKeyboardLayout = 'device-change-keyboard-layout';
25+
public static readonly changeKeyboardLayoutReply = 'device-change-keyboard-layout-reply';
2426
public static readonly setPrivilegeOnLinux = 'set-privilege-on-linux';
2527
public static readonly setPrivilegeOnLinuxReply = 'set-privilege-on-linux-reply';
2628
public static readonly deviceConnectionStateChanged = 'device-connection-state-changed';

packages/uhk-web/src/app/components/device/advanced-settings/advanced-settings.page.component.html

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,40 @@ <h1 class="pane-title">
66
<span>Advanced settings</span>
77
</h1>
88

9-
<div class="col-12">
10-
<div class="checkbox d-inline-block mb-0 mt-0">
11-
<label>
12-
<input type="checkbox"
13-
[checked]="state.i2cDebuggingEnabled"
14-
(click)="onToggleI2cDebug()"
15-
> I2cRecovery debugging
16-
</label>
9+
<div>
10+
<div class="form-check">
11+
Layout:
12+
<div class="form-check d-inline-block">
13+
<input class="form-check-input" type="radio" id="ansiLayout" name="device-layout"
14+
[checked]="keyboardLayout === keyboardLayoutEnum.ANSI"
15+
[disabled]="isKeyboardLayoutChanging$ | async"
16+
(click)="onChangeKeyboardLayout(keyboardLayoutEnum.ANSI)"
17+
>
18+
<label class="form-check-label" for="ansiLayout">
19+
ANSI
20+
</label>
21+
</div>
22+
<div class="form-check d-inline-block">
23+
<input class="form-check-input" type="radio" id="isoLayout" name="device-layout"
24+
[checked]="keyboardLayout === keyboardLayoutEnum.ISO"
25+
[disabled]="isKeyboardLayoutChanging$ | async"
26+
(click)="onChangeKeyboardLayout(keyboardLayoutEnum.ISO)"
27+
>
28+
<label class="form-check-label" for="isoLayout">
29+
ISO
30+
</label>
31+
</div>
32+
</div>
33+
34+
<div class="form-check mt-3">
35+
<div class="checkbox d-inline-block mb-0 mt-0">
36+
<label>
37+
<input type="checkbox"
38+
[checked]="state.i2cDebuggingEnabled"
39+
(click)="onToggleI2cDebug()"
40+
> I2cRecovery debugging
41+
</label>
42+
</div>
1743
</div>
1844
</div>
1945
</div>

packages/uhk-web/src/app/components/device/advanced-settings/advanced-settings.page.component.ts

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import { ChangeDetectionStrategy } from '@angular/core';
55
import { Component } from '@angular/core';
66
import { faCog } from '@fortawesome/free-solid-svg-icons';
77
import { Store } from '@ngrx/store';
8-
import { Subscription } from 'rxjs';
8+
import { Observable, Subscription } from 'rxjs';
9+
import { KeyboardLayout } from 'uhk-common';
910

1011
import { ToggleI2cDebuggingAction } from '../../../store/actions/advance-settings.action';
11-
import { advanceSettingsState, AppState } from '../../../store';
12-
import { State } from '../../../store/reducers/advanced-settings.reducer';
12+
import { advanceSettingsState, AppState, getKeyboardLayout, isKeyboardLayoutChanging } from '../../../store';
13+
import { ChangeKeyboardLayoutAction } from '../../../store/actions/device';
14+
import { initialState, State } from '../../../store/reducers/advanced-settings.reducer';
1315

1416
@Component({
1517
selector: 'advanced-settings',
@@ -22,27 +24,53 @@ import { State } from '../../../store/reducers/advanced-settings.reducer';
2224
export class AdvancedSettingsPageComponent implements OnInit, OnDestroy {
2325
faCog = faCog;
2426

27+
isKeyboardLayoutChanging$: Observable<boolean>;
28+
keyboardLayout: KeyboardLayout;
29+
keyboardLayoutEnum = KeyboardLayout;
30+
2531
state: State;
2632

27-
private subscription: Subscription;
33+
private stateSubscription: Subscription;
34+
private keyboardLayoutSubscription: Subscription;
35+
2836
constructor(private store: Store<AppState>,
2937
private cdRef: ChangeDetectorRef) {
38+
this.state = initialState();
39+
this.isKeyboardLayoutChanging$ = this.store.select(isKeyboardLayoutChanging);
3040
}
3141

3242
ngOnDestroy(): void {
33-
if (this.subscription) {
34-
this.subscription.unsubscribe();
43+
if(this.keyboardLayoutSubscription) {
44+
this.keyboardLayoutSubscription.unsubscribe();
45+
}
46+
47+
if (this.stateSubscription) {
48+
this.stateSubscription.unsubscribe();
3549
}
3650
}
3751

3852
ngOnInit(): void {
39-
this.subscription = this.store.select(advanceSettingsState)
53+
this.keyboardLayoutSubscription = this.store.select(getKeyboardLayout)
54+
.subscribe(layout => {
55+
this.keyboardLayout = layout;
56+
this.cdRef.detectChanges();
57+
});
58+
59+
this.stateSubscription = this.store.select(advanceSettingsState)
4060
.subscribe(state => {
4161
this.state = state;
4262
this.cdRef.detectChanges();
4363
});
4464
}
4565

66+
onChangeKeyboardLayout(layout: KeyboardLayout): void {
67+
if (this.keyboardLayout === layout) {
68+
return;
69+
}
70+
71+
this.store.dispatch(new ChangeKeyboardLayoutAction(layout));
72+
}
73+
4674
onToggleI2cDebug(): void {
4775
this.store.dispatch(new ToggleI2cDebuggingAction());
4876
}

packages/uhk-web/src/app/services/device-renderer.service.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@ import { Injectable, NgZone } from '@angular/core';
22
import { Action, Store } from '@ngrx/store';
33

44
import {
5+
ChangeKeyboardLayoutIpcResponse,
56
DeviceConnectionState,
67
FirmwareJson,
78
FirmwareUpgradeIpcResponse,
89
IpcEvents,
910
IpcResponse,
11+
KeyboardLayout,
1012
LogService,
1113
SaveUserConfigurationData,
1214
UpdateFirmwareData,
1315
UploadFileData,
1416
UserConfiguration,
1517
VersionInformation
1618
} from 'uhk-common';
19+
1720
import { AppState } from '../store';
1821
import { IpcCommonRenderer } from './ipc-common-renderer';
1922
import {
23+
ChangeKeyboardLayoutReplyAction,
2024
ConnectionStateChangedAction,
2125
CurrentlyUpdatingModuleAction,
2226
ReadConfigSizesReplyAction,
@@ -41,6 +45,10 @@ export class DeviceRendererService {
4145
this.logService.misc('[DeviceRendererService] init success ');
4246
}
4347

48+
changeKeyboardLayout(layout: KeyboardLayout, deviceId: number): void {
49+
this.ipcRenderer.send(IpcEvents.device.changeKeyboardLayout, layout, deviceId);
50+
}
51+
4452
setPrivilegeOnLinux(): void {
4553
this.ipcRenderer.send(IpcEvents.device.setPrivilegeOnLinux);
4654
}
@@ -90,6 +98,10 @@ export class DeviceRendererService {
9098
}
9199

92100
private registerEvents(): void {
101+
this.ipcRenderer.on(IpcEvents.device.changeKeyboardLayoutReply, (event: string, response: ChangeKeyboardLayoutIpcResponse) => {
102+
this.dispachStoreAction(new ChangeKeyboardLayoutReplyAction(response));
103+
});
104+
93105
this.ipcRenderer.on(IpcEvents.device.deviceConnectionStateChanged, (event: string, arg: DeviceConnectionState) => {
94106
this.dispachStoreAction(new ConnectionStateChangedAction(arg));
95107
});

packages/uhk-web/src/app/store/actions/device.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import { Action } from '@ngrx/store';
22
import {
33
BackupUserConfiguration,
4+
ChangeKeyboardLayoutIpcResponse,
45
ConfigSizesInfo,
56
DeviceConnectionState,
67
FirmwareJson,
78
FirmwareUpgradeFailReason,
89
FirmwareUpgradeIpcResponse,
910
HardwareModules,
10-
IpcResponse
11+
IpcResponse,
12+
KeyboardLayout
1113
} from 'uhk-common';
1214
import { FirmwareUpgradeError } from '../../models/firmware-upgrade-error';
1315
import { UpdateFirmwareWithPayload } from '../../models';
1416
import { UpdateFirmwareSuccessPayload } from '../../models/update-firmware-success-payload';
1517

1618
export enum ActionTypes {
19+
ChangeKeyboardLayout = '[device] change keyboard layout',
20+
ChangeKeyboardLayoutReply = '[device] change keyboard layout reply',
1721
SetPrivilegeOnLinux = '[device] set privilege on linux',
1822
SetPrivilegeOnLinuxReply = '[device] set privilege on linux reply',
1923
ConnectionStateChanged = '[device] connection state changed',
@@ -50,6 +54,19 @@ export enum ActionTypes {
5054
SkipFirmwareUpgrade = '[device] Skip firmware upgrade'
5155
}
5256

57+
export class ChangeKeyboardLayoutAction implements Action {
58+
type = ActionTypes.ChangeKeyboardLayout;
59+
60+
constructor(public layout: KeyboardLayout) {}
61+
}
62+
63+
export class ChangeKeyboardLayoutReplyAction implements Action {
64+
type = ActionTypes.ChangeKeyboardLayoutReply;
65+
66+
constructor(public payload: ChangeKeyboardLayoutIpcResponse) {}
67+
}
68+
69+
5370
export class SetPrivilegeOnLinuxAction implements Action {
5471
type = ActionTypes.SetPrivilegeOnLinux;
5572
}
@@ -243,7 +260,9 @@ export class SkipFirmwareUpgradeAction implements Action {
243260
}
244261

245262
export type Actions
246-
= SetPrivilegeOnLinuxAction
263+
= ChangeKeyboardLayoutAction
264+
| ChangeKeyboardLayoutReplyAction
265+
| SetPrivilegeOnLinuxAction
247266
| SetPrivilegeOnLinuxReplyAction
248267
| ConnectionStateChangedAction
249268
| ShowSaveToKeyboardButtonAction

0 commit comments

Comments
 (0)