feat: update firmware version after update (#649)
* feat: add clipboard copy icon to the x-term-component * feat: start device poll after firmware upgrade * feat: remove the OK button from the firmware upgrade page * feat: read the firmware after firmware upgrade * fix: scrolling of the x-term-component * feat: refresh the firmware version after recovery device * fix: remove the scrollbar styling * fix: stay on device firmware upgrade screen
This commit is contained in:
committed by
László Monda
parent
6c4f580fc2
commit
a6678bd537
@@ -2,6 +2,7 @@ import { ipcMain } from 'electron';
|
|||||||
import {
|
import {
|
||||||
ConfigurationReply,
|
ConfigurationReply,
|
||||||
DeviceConnectionState,
|
DeviceConnectionState,
|
||||||
|
FirmwareUpgradeIpcResponse,
|
||||||
getHardwareConfigFromDeviceResponse,
|
getHardwareConfigFromDeviceResponse,
|
||||||
HardwareModules,
|
HardwareModules,
|
||||||
IpcEvents,
|
IpcEvents,
|
||||||
@@ -93,10 +94,7 @@ export class DeviceService {
|
|||||||
try {
|
try {
|
||||||
await this.device.waitUntilKeyboardBusy();
|
await this.device.waitUntilKeyboardBusy();
|
||||||
const result = await this.operations.loadConfigurations();
|
const result = await this.operations.loadConfigurations();
|
||||||
const modules: HardwareModules = {
|
const modules: HardwareModules = await this.getHardwareModules(false);
|
||||||
leftModuleInfo: await this.operations.getLeftModuleVersionInfo(),
|
|
||||||
rightModuleInfo: await this.operations.getRightModuleVersionInfo()
|
|
||||||
};
|
|
||||||
|
|
||||||
const hardwareConfig = getHardwareConfigFromDeviceResponse(result.hardwareConfiguration);
|
const hardwareConfig = getHardwareConfigFromDeviceResponse(result.hardwareConfiguration);
|
||||||
const uniqueId = hardwareConfig.uniqueId;
|
const uniqueId = hardwareConfig.uniqueId;
|
||||||
@@ -119,13 +117,32 @@ export class DeviceService {
|
|||||||
event.sender.send(IpcEvents.device.loadConfigurationReply, JSON.stringify(response));
|
event.sender.send(IpcEvents.device.loadConfigurationReply, JSON.stringify(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getHardwareModules(catchError: boolean): Promise<HardwareModules> {
|
||||||
|
try {
|
||||||
|
await this.device.waitUntilKeyboardBusy();
|
||||||
|
|
||||||
|
return {
|
||||||
|
leftModuleInfo: await this.operations.getLeftModuleVersionInfo(),
|
||||||
|
rightModuleInfo: await this.operations.getRightModuleVersionInfo()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (!catchError) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logService.error('[DeviceService] Read hardware modules information failed', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public close(): void {
|
public close(): void {
|
||||||
this.stopPollTimer();
|
this.stopPollTimer();
|
||||||
this.logService.info('[DeviceService] Device connection checker stopped.');
|
this.logService.info('[DeviceService] Device connection checker stopped.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateFirmware(event: Electron.Event, args?: Array<string>): Promise<void> {
|
public async updateFirmware(event: Electron.Event, args?: Array<string>): Promise<void> {
|
||||||
const response = new IpcResponse();
|
const response = new FirmwareUpgradeIpcResponse();
|
||||||
|
|
||||||
let firmwarePathData: TmpFirmware;
|
let firmwarePathData: TmpFirmware;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -142,10 +159,12 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response.success = true;
|
response.success = true;
|
||||||
|
response.modules = await this.getHardwareModules(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const err = {message: error.message, stack: error.stack};
|
const err = {message: error.message, stack: error.stack};
|
||||||
this.logService.error('[DeviceService] updateFirmware error', err);
|
this.logService.error('[DeviceService] updateFirmware error', err);
|
||||||
|
|
||||||
|
response.modules = await this.getHardwareModules(true);
|
||||||
response.error = err;
|
response.error = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,11 +173,15 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await snooze(500);
|
await snooze(500);
|
||||||
|
|
||||||
|
this.pollUhkDevice();
|
||||||
|
|
||||||
event.sender.send(IpcEvents.device.updateFirmwareReply, response);
|
event.sender.send(IpcEvents.device.updateFirmwareReply, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async recoveryDevice(event: Electron.Event): Promise<void> {
|
public async recoveryDevice(event: Electron.Event): Promise<void> {
|
||||||
const response = new IpcResponse();
|
const response = new FirmwareUpgradeIpcResponse();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.stopPollTimer();
|
this.stopPollTimer();
|
||||||
|
|
||||||
@@ -168,11 +191,13 @@ export class DeviceService {
|
|||||||
|
|
||||||
this.pollUhkDevice();
|
this.pollUhkDevice();
|
||||||
|
|
||||||
|
response.modules = await this.getHardwareModules(false);
|
||||||
response.success = true;
|
response.success = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const err = {message: error.message, stack: error.stack};
|
const err = {message: error.message, stack: error.stack};
|
||||||
this.logService.error('[DeviceService] updateFirmware error', err);
|
this.logService.error('[DeviceService] updateFirmware error', err);
|
||||||
|
|
||||||
|
response.modules = await this.getHardwareModules(true);
|
||||||
response.error = err;
|
response.error = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
|
import { HardwareModules } from './hardware-modules';
|
||||||
|
|
||||||
export class IpcResponse {
|
export class IpcResponse {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
error?: { message: string };
|
error?: { message: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FirmwareUpgradeIpcResponse extends IpcResponse {
|
||||||
|
modules?: HardwareModules;
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,15 +39,10 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-grow" #scrollMe>
|
<div class="flex-grow">
|
||||||
<xterm [logs]="xtermLog$ | async"></xterm>
|
<xterm [logs]="xtermLog$ | async"></xterm>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-footer">
|
<div class="flex-footer">
|
||||||
<button type="button"
|
|
||||||
class="btn btn-primary ok-button"
|
|
||||||
[disabled]="firmwareOkButtonDisabled$ | async"
|
|
||||||
(click)="onOkButtonClick()">OK
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, ElementRef, OnDestroy, ViewChild } from '@angular/core';
|
import { Component, OnDestroy } from '@angular/core';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
@@ -6,13 +6,12 @@ import { HardwareModules, VersionInformation } from 'uhk-common';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
AppState,
|
AppState,
|
||||||
firmwareOkButtonDisabled,
|
|
||||||
flashFirmwareButtonDisbabled,
|
flashFirmwareButtonDisbabled,
|
||||||
getAgentVersionInfo,
|
getAgentVersionInfo,
|
||||||
getHardwareModules,
|
getHardwareModules,
|
||||||
xtermLog
|
xtermLog
|
||||||
} from '../../../store';
|
} from '../../../store';
|
||||||
import { UpdateFirmwareAction, UpdateFirmwareOkButtonAction, UpdateFirmwareWithAction } from '../../../store/actions/device';
|
import { UpdateFirmwareAction, UpdateFirmwareWithAction } from '../../../store/actions/device';
|
||||||
import { XtermLog } from '../../../models/xterm-log';
|
import { XtermLog } from '../../../models/xterm-log';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -26,33 +25,20 @@ import { XtermLog } from '../../../models/xterm-log';
|
|||||||
export class DeviceFirmwareComponent implements OnDestroy {
|
export class DeviceFirmwareComponent implements OnDestroy {
|
||||||
flashFirmwareButtonDisbabled$: Observable<boolean>;
|
flashFirmwareButtonDisbabled$: Observable<boolean>;
|
||||||
xtermLog$: Observable<Array<XtermLog>>;
|
xtermLog$: Observable<Array<XtermLog>>;
|
||||||
xtermLogSubscription: Subscription;
|
|
||||||
getAgentVersionInfo$: Observable<VersionInformation>;
|
getAgentVersionInfo$: Observable<VersionInformation>;
|
||||||
firmwareOkButtonDisabled$: Observable<boolean>;
|
|
||||||
hardwareModulesSubscription: Subscription;
|
hardwareModulesSubscription: Subscription;
|
||||||
hardwareModules: HardwareModules;
|
hardwareModules: HardwareModules;
|
||||||
|
|
||||||
@ViewChild('scrollMe') divElement: ElementRef;
|
|
||||||
|
|
||||||
constructor(private store: Store<AppState>) {
|
constructor(private store: Store<AppState>) {
|
||||||
this.flashFirmwareButtonDisbabled$ = store.select(flashFirmwareButtonDisbabled);
|
this.flashFirmwareButtonDisbabled$ = store.select(flashFirmwareButtonDisbabled);
|
||||||
this.xtermLog$ = store.select(xtermLog);
|
this.xtermLog$ = store.select(xtermLog);
|
||||||
this.xtermLogSubscription = this.xtermLog$.subscribe(() => {
|
|
||||||
if (this.divElement && this.divElement.nativeElement) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.divElement.nativeElement.scrollTop = this.divElement.nativeElement.scrollHeight;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.getAgentVersionInfo$ = store.select(getAgentVersionInfo);
|
this.getAgentVersionInfo$ = store.select(getAgentVersionInfo);
|
||||||
this.firmwareOkButtonDisabled$ = store.select(firmwareOkButtonDisabled);
|
|
||||||
this.hardwareModulesSubscription = store.select(getHardwareModules).subscribe(data => {
|
this.hardwareModulesSubscription = store.select(getHardwareModules).subscribe(data => {
|
||||||
this.hardwareModules = data;
|
this.hardwareModules = data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.xtermLogSubscription.unsubscribe();
|
|
||||||
this.hardwareModulesSubscription.unsubscribe();
|
this.hardwareModulesSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,10 +46,6 @@ export class DeviceFirmwareComponent implements OnDestroy {
|
|||||||
this.store.dispatch(new UpdateFirmwareAction());
|
this.store.dispatch(new UpdateFirmwareAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
onOkButtonClick(): void {
|
|
||||||
this.store.dispatch(new UpdateFirmwareOkButtonAction());
|
|
||||||
}
|
|
||||||
|
|
||||||
changeFile(event): void {
|
changeFile(event): void {
|
||||||
const files = event.srcElement.files;
|
const files = event.srcElement.files;
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-grow" #scrollMe>
|
<div class="flex-grow">
|
||||||
<xterm [logs]="xtermLog"></xterm>
|
<xterm [logs]="xtermLog$ | async"></xterm>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-footer">
|
<div class="flex-footer">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import { XtermLog } from '../../../models/xterm-log';
|
import { XtermLog } from '../../../models/xterm-log';
|
||||||
@@ -16,38 +15,17 @@ import { RecoveryDeviceAction } from '../../../store/actions/device';
|
|||||||
'class': 'container-fluid'
|
'class': 'container-fluid'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class RecoveryModeComponent implements OnInit, OnDestroy {
|
export class RecoveryModeComponent implements OnInit {
|
||||||
xtermLogSubscription: Subscription;
|
|
||||||
flashFirmwareButtonDisbabled$: Observable<boolean>;
|
flashFirmwareButtonDisbabled$: Observable<boolean>;
|
||||||
|
|
||||||
xtermLog: Array<XtermLog>;
|
xtermLog$: Observable<Array<XtermLog>>;
|
||||||
|
|
||||||
@ViewChild('scrollMe') divElement: ElementRef;
|
constructor(private store: Store<AppState>) {
|
||||||
|
|
||||||
constructor(private store: Store<AppState>,
|
|
||||||
private cdRef: ChangeDetectorRef) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.flashFirmwareButtonDisbabled$ = this.store.select(flashFirmwareButtonDisbabled);
|
this.flashFirmwareButtonDisbabled$ = this.store.select(flashFirmwareButtonDisbabled);
|
||||||
this.xtermLogSubscription = this.store.select(xtermLog)
|
this.xtermLog$ = this.store.select(xtermLog);
|
||||||
.subscribe(data => {
|
|
||||||
this.xtermLog = data;
|
|
||||||
|
|
||||||
this.cdRef.markForCheck();
|
|
||||||
|
|
||||||
if (this.divElement && this.divElement.nativeElement) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.divElement.nativeElement.scrollTop = this.divElement.nativeElement.scrollHeight;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
|
||||||
if (this.xtermLogSubscription) {
|
|
||||||
this.xtermLogSubscription.unsubscribe();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onRecoveryDevice(): void {
|
onRecoveryDevice(): void {
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
<div class="wrapper">
|
<div class="x-term-container">
|
||||||
<ul class="list-unstyled">
|
<div class="x-term-wrapper" #scrollMe>
|
||||||
<li *ngFor="let log of logs" [ngClass]="log.cssClass"><span>{{ log.message }}</span></li>
|
<ul class="list-unstyled">
|
||||||
</ul>
|
<li *ngFor="let log of logs" [ngClass]="log.cssClass"><span>{{ log.message }}</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="copy-container-wrapper">
|
||||||
|
<div class="copy-container">
|
||||||
|
<span class="fa fa-2x fa-copy"
|
||||||
|
ngxClipboard
|
||||||
|
[cbContent]="getClipboardContent()"
|
||||||
|
title="Copy to clipboard"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
data-placement="top"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,36 @@
|
|||||||
|
$scrollbar-color: #ffffff;
|
||||||
|
$scrollbar-radius: 6px;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
background-color: yellow;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.x-term-container {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.x-term-wrapper {
|
||||||
background-color: black;
|
background-color: black;
|
||||||
|
overflow: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-container-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xterm-standard {
|
.xterm-standard {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
|
||||||
import { XtermLog } from '../../models/xterm-log';
|
import { XtermLog } from '../../models/xterm-log';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -7,6 +7,21 @@ import { XtermLog } from '../../models/xterm-log';
|
|||||||
styleUrls: ['./xterm.component.scss'],
|
styleUrls: ['./xterm.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class XtermComponent {
|
export class XtermComponent implements OnChanges {
|
||||||
@Input() logs: Array<XtermLog> = [];
|
@Input() logs: Array<XtermLog> = [];
|
||||||
|
|
||||||
|
@ViewChild('scrollMe') divElement: ElementRef;
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
if (changes.logs && this.divElement && this.divElement.nativeElement) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.divElement.nativeElement.scrollTop = this.divElement.nativeElement.scrollHeight;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getClipboardContent(): string {
|
||||||
|
return this.logs.reduce((value, line) => value + line.message + '\n', '');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { HardwareModules } from 'uhk-common';
|
||||||
|
|
||||||
|
export interface FirmwareUpgradeError {
|
||||||
|
error: any;
|
||||||
|
modules?: HardwareModules;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
import { DeviceConnectionState, HardwareModules, IpcResponse, type } from 'uhk-common';
|
import { DeviceConnectionState, FirmwareUpgradeIpcResponse, HardwareModules, IpcResponse, type } from 'uhk-common';
|
||||||
|
import { FirmwareUpgradeError } from '../../models/firmware-upgrade-error';
|
||||||
|
|
||||||
const PREFIX = '[device] ';
|
const PREFIX = '[device] ';
|
||||||
|
|
||||||
@@ -96,25 +97,23 @@ export class UpdateFirmwareWithAction implements Action {
|
|||||||
export class UpdateFirmwareReplyAction implements Action {
|
export class UpdateFirmwareReplyAction implements Action {
|
||||||
type = ActionTypes.UPDATE_FIRMWARE_REPLY;
|
type = ActionTypes.UPDATE_FIRMWARE_REPLY;
|
||||||
|
|
||||||
constructor(public payload: IpcResponse) {
|
constructor(public payload: FirmwareUpgradeIpcResponse) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UpdateFirmwareSuccessAction implements Action {
|
export class UpdateFirmwareSuccessAction implements Action {
|
||||||
type = ActionTypes.UPDATE_FIRMWARE_SUCCESS;
|
type = ActionTypes.UPDATE_FIRMWARE_SUCCESS;
|
||||||
|
constructor(public payload: HardwareModules) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UpdateFirmwareFailedAction implements Action {
|
export class UpdateFirmwareFailedAction implements Action {
|
||||||
type = ActionTypes.UPDATE_FIRMWARE_FAILED;
|
type = ActionTypes.UPDATE_FIRMWARE_FAILED;
|
||||||
|
|
||||||
constructor(public payload: any) {
|
constructor(public payload: FirmwareUpgradeError) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UpdateFirmwareOkButtonAction implements Action {
|
|
||||||
type = ActionTypes.UPDATE_FIRMWARE_OK_BUTTON;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ResetMouseSpeedSettingsAction implements Action {
|
export class ResetMouseSpeedSettingsAction implements Action {
|
||||||
type = ActionTypes.RESET_MOUSE_SPEED_SETTINGS;
|
type = ActionTypes.RESET_MOUSE_SPEED_SETTINGS;
|
||||||
}
|
}
|
||||||
@@ -162,7 +161,6 @@ export type Actions
|
|||||||
| UpdateFirmwareReplyAction
|
| UpdateFirmwareReplyAction
|
||||||
| UpdateFirmwareSuccessAction
|
| UpdateFirmwareSuccessAction
|
||||||
| UpdateFirmwareFailedAction
|
| UpdateFirmwareFailedAction
|
||||||
| UpdateFirmwareOkButtonAction
|
|
||||||
| HardwareModulesLoadedAction
|
| HardwareModulesLoadedAction
|
||||||
| RestoreUserConfigurationFromBackupAction
|
| RestoreUserConfigurationFromBackupAction
|
||||||
| HasBackupUserConfigurationAction
|
| HasBackupUserConfigurationAction
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import 'rxjs/add/operator/withLatestFrom';
|
|||||||
import 'rxjs/add/operator/switchMap';
|
import 'rxjs/add/operator/switchMap';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeviceConnectionState,
|
FirmwareUpgradeIpcResponse,
|
||||||
HardwareConfiguration,
|
HardwareConfiguration,
|
||||||
IpcResponse,
|
IpcResponse,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
@@ -34,14 +34,13 @@ import {
|
|||||||
SetPrivilegeOnLinuxReplyAction,
|
SetPrivilegeOnLinuxReplyAction,
|
||||||
UpdateFirmwareAction,
|
UpdateFirmwareAction,
|
||||||
UpdateFirmwareFailedAction,
|
UpdateFirmwareFailedAction,
|
||||||
UpdateFirmwareOkButtonAction,
|
|
||||||
UpdateFirmwareReplyAction,
|
UpdateFirmwareReplyAction,
|
||||||
UpdateFirmwareSuccessAction,
|
UpdateFirmwareSuccessAction,
|
||||||
UpdateFirmwareWithAction
|
UpdateFirmwareWithAction
|
||||||
} from '../actions/device';
|
} from '../actions/device';
|
||||||
import { DeviceRendererService } from '../../services/device-renderer.service';
|
import { DeviceRendererService } from '../../services/device-renderer.service';
|
||||||
import { SetupPermissionErrorAction, ShowNotificationAction } from '../actions/app';
|
import { SetupPermissionErrorAction, ShowNotificationAction } from '../actions/app';
|
||||||
import { AppState } from '../index';
|
import { AppState, getRouterState } from '../index';
|
||||||
import {
|
import {
|
||||||
ActionTypes as UserConfigActions,
|
ActionTypes as UserConfigActions,
|
||||||
ApplyUserConfigurationFromFileAction,
|
ApplyUserConfigurationFromFileAction,
|
||||||
@@ -56,8 +55,14 @@ export class DeviceEffects {
|
|||||||
@Effect()
|
@Effect()
|
||||||
deviceConnectionStateChange$: Observable<Action> = this.actions$
|
deviceConnectionStateChange$: Observable<Action> = this.actions$
|
||||||
.ofType<ConnectionStateChangedAction>(ActionTypes.CONNECTION_STATE_CHANGED)
|
.ofType<ConnectionStateChangedAction>(ActionTypes.CONNECTION_STATE_CHANGED)
|
||||||
.map(action => action.payload)
|
.withLatestFrom(this.store.select(getRouterState))
|
||||||
.do((state: DeviceConnectionState) => {
|
.do(([action, route]) => {
|
||||||
|
const state = action.payload;
|
||||||
|
|
||||||
|
if (route.state && route.state.url.startsWith('/device/firmware')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!state.hasPermission) {
|
if (!state.hasPermission) {
|
||||||
this.router.navigate(['/privilege']);
|
this.router.navigate(['/privilege']);
|
||||||
}
|
}
|
||||||
@@ -71,7 +76,9 @@ export class DeviceEffects {
|
|||||||
this.router.navigate(['/detection']);
|
this.router.navigate(['/detection']);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.switchMap((state: DeviceConnectionState) => {
|
.switchMap(([action, route]) => {
|
||||||
|
const state = action.payload;
|
||||||
|
|
||||||
if (state.connected && state.hasPermission) {
|
if (state.connected && state.hasPermission) {
|
||||||
return Observable.of(new LoadConfigFromDeviceAction());
|
return Observable.of(new LoadConfigFromDeviceAction());
|
||||||
}
|
}
|
||||||
@@ -203,18 +210,18 @@ export class DeviceEffects {
|
|||||||
@Effect() updateFirmwareReply$ = this.actions$
|
@Effect() updateFirmwareReply$ = this.actions$
|
||||||
.ofType<UpdateFirmwareReplyAction>(ActionTypes.UPDATE_FIRMWARE_REPLY)
|
.ofType<UpdateFirmwareReplyAction>(ActionTypes.UPDATE_FIRMWARE_REPLY)
|
||||||
.map(action => action.payload)
|
.map(action => action.payload)
|
||||||
.switchMap((response: IpcResponse) => {
|
.switchMap((response: FirmwareUpgradeIpcResponse)
|
||||||
|
: Observable<UpdateFirmwareSuccessAction | UpdateFirmwareFailedAction> => {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
return Observable.of(new UpdateFirmwareSuccessAction());
|
return Observable.of(new UpdateFirmwareSuccessAction(response.modules));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Observable.of(new UpdateFirmwareFailedAction(response.error));
|
return Observable.of(new UpdateFirmwareFailedAction({
|
||||||
|
error: response.error,
|
||||||
|
modules: response.modules
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
@Effect({dispatch: false}) updateFirmwareOkButton$ = this.actions$
|
|
||||||
.ofType<UpdateFirmwareOkButtonAction>(ActionTypes.UPDATE_FIRMWARE_OK_BUTTON)
|
|
||||||
.do(() => this.deviceRendererService.startConnectionPoller());
|
|
||||||
|
|
||||||
@Effect() restoreUserConfiguration$ = this.actions$
|
@Effect() restoreUserConfiguration$ = this.actions$
|
||||||
.ofType<ResetUserConfigurationAction>(ActionTypes.RESTORE_CONFIGURATION_FROM_BACKUP)
|
.ofType<ResetUserConfigurationAction>(ActionTypes.RESTORE_CONFIGURATION_FROM_BACKUP)
|
||||||
.map(() => new SaveConfigurationAction());
|
.map(() => new SaveConfigurationAction());
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import {
|
|||||||
|
|
||||||
import { DataStorageRepositoryService } from '../../services/datastorage-repository.service';
|
import { DataStorageRepositoryService } from '../../services/datastorage-repository.service';
|
||||||
import { DefaultUserConfigurationService } from '../../services/default-user-configuration.service';
|
import { DefaultUserConfigurationService } from '../../services/default-user-configuration.service';
|
||||||
import { AppState, getPrevUserConfiguration, getUserConfiguration } from '../index';
|
import { AppState, getPrevUserConfiguration, getRouterState, getUserConfiguration } from '../index';
|
||||||
import { KeymapAction, KeymapActions, MacroAction, MacroActions } from '../actions';
|
import { KeymapAction, KeymapActions, MacroAction, MacroActions } from '../actions';
|
||||||
import {
|
import {
|
||||||
DismissUndoNotificationAction,
|
DismissUndoNotificationAction,
|
||||||
@@ -118,8 +118,10 @@ export class UserConfigEffects {
|
|||||||
|
|
||||||
@Effect() loadConfigFromDeviceReply$ = this.actions$
|
@Effect() loadConfigFromDeviceReply$ = this.actions$
|
||||||
.ofType<LoadConfigFromDeviceReplyAction>(ActionTypes.LOAD_CONFIG_FROM_DEVICE_REPLY)
|
.ofType<LoadConfigFromDeviceReplyAction>(ActionTypes.LOAD_CONFIG_FROM_DEVICE_REPLY)
|
||||||
.map(action => action.payload)
|
.withLatestFrom(this.store.select(getRouterState))
|
||||||
.mergeMap((data: ConfigurationReply): any => {
|
.mergeMap(([action, route]): any => {
|
||||||
|
const data: ConfigurationReply = action.payload;
|
||||||
|
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
return [new ShowNotificationAction({
|
return [new ShowNotificationAction({
|
||||||
type: NotificationType.Error,
|
type: NotificationType.Error,
|
||||||
@@ -128,12 +130,16 @@ export class UserConfigEffects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = [];
|
const result = [];
|
||||||
let newPageDestination = ['/'];
|
let newPageDestination: Array<string>;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const userConfig = getUserConfigFromDeviceResponse(data.userConfiguration);
|
const userConfig = getUserConfigFromDeviceResponse(data.userConfiguration);
|
||||||
result.push(new LoadUserConfigSuccessAction(userConfig));
|
result.push(new LoadUserConfigSuccessAction(userConfig));
|
||||||
|
|
||||||
|
if (route.state && !route.state.url.startsWith('/device/firmware')) {
|
||||||
|
newPageDestination = ['/'];
|
||||||
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.logService.error('Eeprom user-config parse error:', err);
|
this.logService.error('Eeprom user-config parse error:', err);
|
||||||
const userConfig = new UserConfiguration().fromJsonObject(data.backupConfiguration);
|
const userConfig = new UserConfiguration().fromJsonObject(data.backupConfiguration);
|
||||||
@@ -158,7 +164,9 @@ export class UserConfigEffects {
|
|||||||
|
|
||||||
result.push(new HardwareModulesLoadedAction(data.modules));
|
result.push(new HardwareModulesLoadedAction(data.modules));
|
||||||
|
|
||||||
this.router.navigate(newPageDestination);
|
if (newPageDestination) {
|
||||||
|
this.router.navigate(newPageDestination);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { MetaReducer } from '@ngrx/store';
|
import { ActionReducerMap, MetaReducer } from '@ngrx/store';
|
||||||
import { RouterReducerState } from '@ngrx/router-store';
|
import { RouterReducerState, routerReducer } from '@ngrx/router-store';
|
||||||
import { storeFreeze } from 'ngrx-store-freeze';
|
import { storeFreeze } from 'ngrx-store-freeze';
|
||||||
import { Keymap, UserConfiguration } from 'uhk-common';
|
import { Keymap, UserConfiguration } from 'uhk-common';
|
||||||
|
|
||||||
@@ -14,15 +14,6 @@ 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';
|
||||||
|
|
||||||
export const reducers = {
|
|
||||||
userConfiguration: fromUserConfig.reducer,
|
|
||||||
presetKeymaps: fromPreset.reducer,
|
|
||||||
autoUpdateSettings: autoUpdateSettings.reducer,
|
|
||||||
app: fromApp.reducer,
|
|
||||||
appUpdate: fromAppUpdate.reducer,
|
|
||||||
device: fromDevice.reducer
|
|
||||||
};
|
|
||||||
|
|
||||||
// State interface for the application
|
// State interface for the application
|
||||||
export interface AppState {
|
export interface AppState {
|
||||||
userConfiguration: UserConfiguration;
|
userConfiguration: UserConfiguration;
|
||||||
@@ -34,6 +25,16 @@ export interface AppState {
|
|||||||
device: fromDevice.State;
|
device: fromDevice.State;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const reducers: ActionReducerMap<AppState> = {
|
||||||
|
userConfiguration: fromUserConfig.reducer,
|
||||||
|
presetKeymaps: fromPreset.reducer,
|
||||||
|
autoUpdateSettings: autoUpdateSettings.reducer,
|
||||||
|
app: fromApp.reducer,
|
||||||
|
router: routerReducer,
|
||||||
|
appUpdate: fromAppUpdate.reducer,
|
||||||
|
device: fromDevice.reducer
|
||||||
|
};
|
||||||
|
|
||||||
export const metaReducers: MetaReducer<AppState>[] = environment.production
|
export const metaReducers: MetaReducer<AppState>[] = environment.production
|
||||||
? []
|
? []
|
||||||
: [storeFreeze];
|
: [storeFreeze];
|
||||||
@@ -73,7 +74,6 @@ export const saveToKeyboardState = createSelector(runningInElectron, saveToKeybo
|
|||||||
});
|
});
|
||||||
export const updatingFirmware = createSelector(deviceState, fromDevice.updatingFirmware);
|
export const updatingFirmware = createSelector(deviceState, fromDevice.updatingFirmware);
|
||||||
export const xtermLog = createSelector(deviceState, fromDevice.xtermLog);
|
export const xtermLog = createSelector(deviceState, fromDevice.xtermLog);
|
||||||
export const firmwareOkButtonDisabled = createSelector(deviceState, fromDevice.firmwareOkButtonDisabled);
|
|
||||||
// tslint:disable-next-line: max-line-length
|
// tslint:disable-next-line: max-line-length
|
||||||
export const flashFirmwareButtonDisbabled = createSelector(runningInElectron, deviceState, (electron, state: fromDevice.State) => !electron || state.updatingFirmware);
|
export const flashFirmwareButtonDisbabled = createSelector(runningInElectron, deviceState, (electron, state: fromDevice.State) => !electron || state.updatingFirmware);
|
||||||
export const getHardwareModules = createSelector(deviceState, fromDevice.getHardwareModules);
|
export const getHardwareModules = createSelector(deviceState, fromDevice.getHardwareModules);
|
||||||
@@ -103,3 +103,5 @@ export const getSideMenuPageState = createSelector(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getRouterState = (state: AppState) => state.router;
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import {
|
|||||||
HardwareModulesLoadedAction,
|
HardwareModulesLoadedAction,
|
||||||
SaveConfigurationAction,
|
SaveConfigurationAction,
|
||||||
HasBackupUserConfigurationAction,
|
HasBackupUserConfigurationAction,
|
||||||
UpdateFirmwareFailedAction
|
UpdateFirmwareFailedAction,
|
||||||
|
UpdateFirmwareSuccessAction
|
||||||
} from '../actions/device';
|
} from '../actions/device';
|
||||||
import { ActionTypes as AppActions, ElectronMainLogReceivedAction } from '../actions/app';
|
import { ActionTypes as AppActions, ElectronMainLogReceivedAction } from '../actions/app';
|
||||||
import { initProgressButtonState, ProgressButtonState } from './progress-button-state';
|
import { initProgressButtonState, ProgressButtonState } from './progress-button-state';
|
||||||
@@ -19,6 +20,7 @@ export interface State {
|
|||||||
hasPermission: boolean;
|
hasPermission: boolean;
|
||||||
bootloaderActive: boolean;
|
bootloaderActive: boolean;
|
||||||
saveToKeyboard: ProgressButtonState;
|
saveToKeyboard: ProgressButtonState;
|
||||||
|
savingToKeyboard: boolean;
|
||||||
updatingFirmware: boolean;
|
updatingFirmware: boolean;
|
||||||
firmwareUpdateFinished: boolean;
|
firmwareUpdateFinished: boolean;
|
||||||
modules: HardwareModules;
|
modules: HardwareModules;
|
||||||
@@ -32,6 +34,7 @@ export const initialState: State = {
|
|||||||
hasPermission: true,
|
hasPermission: true,
|
||||||
bootloaderActive: false,
|
bootloaderActive: false,
|
||||||
saveToKeyboard: initProgressButtonState,
|
saveToKeyboard: initProgressButtonState,
|
||||||
|
savingToKeyboard: false,
|
||||||
updatingFirmware: false,
|
updatingFirmware: false,
|
||||||
firmwareUpdateFinished: false,
|
firmwareUpdateFinished: false,
|
||||||
modules: {
|
modules: {
|
||||||
@@ -48,7 +51,7 @@ export const initialState: State = {
|
|||||||
hasBackupUserConfiguration: false
|
hasBackupUserConfiguration: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export function reducer(state = initialState, action: Action) {
|
export function reducer(state = initialState, action: Action): State {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.CONNECTION_STATE_CHANGED: {
|
case ActionTypes.CONNECTION_STATE_CHANGED: {
|
||||||
const data = (<ConnectionStateChangedAction>action).payload;
|
const data = (<ConnectionStateChangedAction>action).payload;
|
||||||
@@ -132,12 +135,14 @@ export function reducer(state = initialState, action: Action) {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
updatingFirmware: false,
|
updatingFirmware: false,
|
||||||
firmwareUpdateFinished: true
|
firmwareUpdateFinished: true,
|
||||||
|
modules: (action as UpdateFirmwareSuccessAction).payload
|
||||||
};
|
};
|
||||||
|
|
||||||
case ActionTypes.UPDATE_FIRMWARE_FAILED: {
|
case ActionTypes.UPDATE_FIRMWARE_FAILED: {
|
||||||
|
const data = (action as UpdateFirmwareFailedAction).payload;
|
||||||
const logEntry = {
|
const logEntry = {
|
||||||
message: (action as UpdateFirmwareFailedAction).payload.message,
|
message: data.error.message,
|
||||||
cssClass: XtermCssClass.error
|
cssClass: XtermCssClass.error
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -145,6 +150,7 @@ export function reducer(state = initialState, action: Action) {
|
|||||||
...state,
|
...state,
|
||||||
updatingFirmware: false,
|
updatingFirmware: false,
|
||||||
firmwareUpdateFinished: true,
|
firmwareUpdateFinished: true,
|
||||||
|
modules: data.modules,
|
||||||
log: [...state.log, logEntry]
|
log: [...state.log, logEntry]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -213,7 +219,6 @@ export const isDeviceConnected = (state: State) => state.connected || state.upda
|
|||||||
export const hasDevicePermission = (state: State) => state.hasPermission;
|
export const hasDevicePermission = (state: State) => state.hasPermission;
|
||||||
export const getSaveToKeyboardState = (state: State) => state.saveToKeyboard;
|
export const getSaveToKeyboardState = (state: State) => state.saveToKeyboard;
|
||||||
export const xtermLog = (state: State) => state.log;
|
export const xtermLog = (state: State) => state.log;
|
||||||
export const firmwareOkButtonDisabled = (state: State) => !state.firmwareUpdateFinished;
|
|
||||||
export const getHardwareModules = (state: State) => state.modules;
|
export const getHardwareModules = (state: State) => state.modules;
|
||||||
export const getHasBackupUserConfiguration = (state: State) => state.hasBackupUserConfiguration;
|
export const getHasBackupUserConfiguration = (state: State) => state.hasBackupUserConfiguration;
|
||||||
export const getBackupUserConfigurationState = (state: State): RestoreConfigurationState => {
|
export const getBackupUserConfigurationState = (state: State): RestoreConfigurationState => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Action } from '@ngrx/store';
|
|||||||
export interface ProgressButtonState {
|
export interface ProgressButtonState {
|
||||||
showButton: boolean;
|
showButton: boolean;
|
||||||
text: string;
|
text: string;
|
||||||
showProgress: boolean;
|
showProgress?: boolean;
|
||||||
action?: Action;
|
action?: Action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -158,14 +158,14 @@ pre {
|
|||||||
|
|
||||||
.flex-container {
|
.flex-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-height: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex-grow {
|
.flex-grow {
|
||||||
background-color: black;
|
display: flex;
|
||||||
overflow: auto;
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user