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 {
|
||||
ConfigurationReply,
|
||||
DeviceConnectionState,
|
||||
FirmwareUpgradeIpcResponse,
|
||||
getHardwareConfigFromDeviceResponse,
|
||||
HardwareModules,
|
||||
IpcEvents,
|
||||
@@ -93,10 +94,7 @@ export class DeviceService {
|
||||
try {
|
||||
await this.device.waitUntilKeyboardBusy();
|
||||
const result = await this.operations.loadConfigurations();
|
||||
const modules: HardwareModules = {
|
||||
leftModuleInfo: await this.operations.getLeftModuleVersionInfo(),
|
||||
rightModuleInfo: await this.operations.getRightModuleVersionInfo()
|
||||
};
|
||||
const modules: HardwareModules = await this.getHardwareModules(false);
|
||||
|
||||
const hardwareConfig = getHardwareConfigFromDeviceResponse(result.hardwareConfiguration);
|
||||
const uniqueId = hardwareConfig.uniqueId;
|
||||
@@ -119,13 +117,32 @@ export class DeviceService {
|
||||
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 {
|
||||
this.stopPollTimer();
|
||||
this.logService.info('[DeviceService] Device connection checker stopped.');
|
||||
}
|
||||
|
||||
public async updateFirmware(event: Electron.Event, args?: Array<string>): Promise<void> {
|
||||
const response = new IpcResponse();
|
||||
const response = new FirmwareUpgradeIpcResponse();
|
||||
|
||||
let firmwarePathData: TmpFirmware;
|
||||
|
||||
try {
|
||||
@@ -142,10 +159,12 @@ export class DeviceService {
|
||||
}
|
||||
|
||||
response.success = true;
|
||||
response.modules = await this.getHardwareModules(false);
|
||||
} catch (error) {
|
||||
const err = {message: error.message, stack: error.stack};
|
||||
this.logService.error('[DeviceService] updateFirmware error', err);
|
||||
|
||||
response.modules = await this.getHardwareModules(true);
|
||||
response.error = err;
|
||||
}
|
||||
|
||||
@@ -154,11 +173,15 @@ export class DeviceService {
|
||||
}
|
||||
|
||||
await snooze(500);
|
||||
|
||||
this.pollUhkDevice();
|
||||
|
||||
event.sender.send(IpcEvents.device.updateFirmwareReply, response);
|
||||
}
|
||||
|
||||
public async recoveryDevice(event: Electron.Event): Promise<void> {
|
||||
const response = new IpcResponse();
|
||||
const response = new FirmwareUpgradeIpcResponse();
|
||||
|
||||
try {
|
||||
this.stopPollTimer();
|
||||
|
||||
@@ -168,11 +191,13 @@ export class DeviceService {
|
||||
|
||||
this.pollUhkDevice();
|
||||
|
||||
response.modules = await this.getHardwareModules(false);
|
||||
response.success = true;
|
||||
} catch (error) {
|
||||
const err = {message: error.message, stack: error.stack};
|
||||
this.logService.error('[DeviceService] updateFirmware error', err);
|
||||
|
||||
response.modules = await this.getHardwareModules(true);
|
||||
response.error = err;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { HardwareModules } from './hardware-modules';
|
||||
|
||||
export class IpcResponse {
|
||||
success: boolean;
|
||||
error?: { message: string };
|
||||
}
|
||||
|
||||
export class FirmwareUpgradeIpcResponse extends IpcResponse {
|
||||
modules?: HardwareModules;
|
||||
}
|
||||
|
||||
@@ -39,15 +39,10 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex-grow" #scrollMe>
|
||||
<div class="flex-grow">
|
||||
<xterm [logs]="xtermLog$ | async"></xterm>
|
||||
</div>
|
||||
<div class="flex-footer">
|
||||
<button type="button"
|
||||
class="btn btn-primary ok-button"
|
||||
[disabled]="firmwareOkButtonDisabled$ | async"
|
||||
(click)="onOkButtonClick()">OK
|
||||
</button>
|
||||
</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 { Observable } from 'rxjs/Observable';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
@@ -6,13 +6,12 @@ import { HardwareModules, VersionInformation } from 'uhk-common';
|
||||
|
||||
import {
|
||||
AppState,
|
||||
firmwareOkButtonDisabled,
|
||||
flashFirmwareButtonDisbabled,
|
||||
getAgentVersionInfo,
|
||||
getHardwareModules,
|
||||
xtermLog
|
||||
} from '../../../store';
|
||||
import { UpdateFirmwareAction, UpdateFirmwareOkButtonAction, UpdateFirmwareWithAction } from '../../../store/actions/device';
|
||||
import { UpdateFirmwareAction, UpdateFirmwareWithAction } from '../../../store/actions/device';
|
||||
import { XtermLog } from '../../../models/xterm-log';
|
||||
|
||||
@Component({
|
||||
@@ -26,33 +25,20 @@ import { XtermLog } from '../../../models/xterm-log';
|
||||
export class DeviceFirmwareComponent implements OnDestroy {
|
||||
flashFirmwareButtonDisbabled$: Observable<boolean>;
|
||||
xtermLog$: Observable<Array<XtermLog>>;
|
||||
xtermLogSubscription: Subscription;
|
||||
getAgentVersionInfo$: Observable<VersionInformation>;
|
||||
firmwareOkButtonDisabled$: Observable<boolean>;
|
||||
hardwareModulesSubscription: Subscription;
|
||||
hardwareModules: HardwareModules;
|
||||
|
||||
@ViewChild('scrollMe') divElement: ElementRef;
|
||||
|
||||
constructor(private store: Store<AppState>) {
|
||||
this.flashFirmwareButtonDisbabled$ = store.select(flashFirmwareButtonDisbabled);
|
||||
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.firmwareOkButtonDisabled$ = store.select(firmwareOkButtonDisabled);
|
||||
this.hardwareModulesSubscription = store.select(getHardwareModules).subscribe(data => {
|
||||
this.hardwareModules = data;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.xtermLogSubscription.unsubscribe();
|
||||
this.hardwareModulesSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
@@ -60,10 +46,6 @@ export class DeviceFirmwareComponent implements OnDestroy {
|
||||
this.store.dispatch(new UpdateFirmwareAction());
|
||||
}
|
||||
|
||||
onOkButtonClick(): void {
|
||||
this.store.dispatch(new UpdateFirmwareOkButtonAction());
|
||||
}
|
||||
|
||||
changeFile(event): void {
|
||||
const files = event.srcElement.files;
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex-grow" #scrollMe>
|
||||
<xterm [logs]="xtermLog"></xterm>
|
||||
<div class="flex-grow">
|
||||
<xterm [logs]="xtermLog$ | async"></xterm>
|
||||
</div>
|
||||
<div class="flex-footer">
|
||||
</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 { Subscription } from 'rxjs/Subscription';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { XtermLog } from '../../../models/xterm-log';
|
||||
@@ -16,38 +15,17 @@ import { RecoveryDeviceAction } from '../../../store/actions/device';
|
||||
'class': 'container-fluid'
|
||||
}
|
||||
})
|
||||
export class RecoveryModeComponent implements OnInit, OnDestroy {
|
||||
xtermLogSubscription: Subscription;
|
||||
export class RecoveryModeComponent implements OnInit {
|
||||
flashFirmwareButtonDisbabled$: Observable<boolean>;
|
||||
|
||||
xtermLog: Array<XtermLog>;
|
||||
xtermLog$: Observable<Array<XtermLog>>;
|
||||
|
||||
@ViewChild('scrollMe') divElement: ElementRef;
|
||||
|
||||
constructor(private store: Store<AppState>,
|
||||
private cdRef: ChangeDetectorRef) {
|
||||
constructor(private store: Store<AppState>) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.flashFirmwareButtonDisbabled$ = this.store.select(flashFirmwareButtonDisbabled);
|
||||
this.xtermLogSubscription = 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();
|
||||
}
|
||||
this.xtermLog$ = this.store.select(xtermLog);
|
||||
}
|
||||
|
||||
onRecoveryDevice(): void {
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
<div class="wrapper">
|
||||
<ul class="list-unstyled">
|
||||
<li *ngFor="let log of logs" [ngClass]="log.cssClass"><span>{{ log.message }}</span></li>
|
||||
</ul>
|
||||
<div class="x-term-container">
|
||||
<div class="x-term-wrapper" #scrollMe>
|
||||
<ul class="list-unstyled">
|
||||
<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>
|
||||
|
||||
@@ -1,9 +1,36 @@
|
||||
$scrollbar-color: #ffffff;
|
||||
$scrollbar-radius: 6px;
|
||||
|
||||
: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;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.copy-container-wrapper {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 14px;
|
||||
}
|
||||
|
||||
.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';
|
||||
|
||||
@Component({
|
||||
@@ -7,6 +7,21 @@ import { XtermLog } from '../../models/xterm-log';
|
||||
styleUrls: ['./xterm.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class XtermComponent {
|
||||
export class XtermComponent implements OnChanges {
|
||||
@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 { 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] ';
|
||||
|
||||
@@ -96,25 +97,23 @@ export class UpdateFirmwareWithAction implements Action {
|
||||
export class UpdateFirmwareReplyAction implements Action {
|
||||
type = ActionTypes.UPDATE_FIRMWARE_REPLY;
|
||||
|
||||
constructor(public payload: IpcResponse) {
|
||||
constructor(public payload: FirmwareUpgradeIpcResponse) {
|
||||
}
|
||||
}
|
||||
|
||||
export class UpdateFirmwareSuccessAction implements Action {
|
||||
type = ActionTypes.UPDATE_FIRMWARE_SUCCESS;
|
||||
constructor(public payload: HardwareModules) {
|
||||
}
|
||||
}
|
||||
|
||||
export class UpdateFirmwareFailedAction implements Action {
|
||||
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 {
|
||||
type = ActionTypes.RESET_MOUSE_SPEED_SETTINGS;
|
||||
}
|
||||
@@ -162,7 +161,6 @@ export type Actions
|
||||
| UpdateFirmwareReplyAction
|
||||
| UpdateFirmwareSuccessAction
|
||||
| UpdateFirmwareFailedAction
|
||||
| UpdateFirmwareOkButtonAction
|
||||
| HardwareModulesLoadedAction
|
||||
| RestoreUserConfigurationFromBackupAction
|
||||
| HasBackupUserConfigurationAction
|
||||
|
||||
@@ -14,7 +14,7 @@ import 'rxjs/add/operator/withLatestFrom';
|
||||
import 'rxjs/add/operator/switchMap';
|
||||
|
||||
import {
|
||||
DeviceConnectionState,
|
||||
FirmwareUpgradeIpcResponse,
|
||||
HardwareConfiguration,
|
||||
IpcResponse,
|
||||
NotificationType,
|
||||
@@ -34,14 +34,13 @@ import {
|
||||
SetPrivilegeOnLinuxReplyAction,
|
||||
UpdateFirmwareAction,
|
||||
UpdateFirmwareFailedAction,
|
||||
UpdateFirmwareOkButtonAction,
|
||||
UpdateFirmwareReplyAction,
|
||||
UpdateFirmwareSuccessAction,
|
||||
UpdateFirmwareWithAction
|
||||
} from '../actions/device';
|
||||
import { DeviceRendererService } from '../../services/device-renderer.service';
|
||||
import { SetupPermissionErrorAction, ShowNotificationAction } from '../actions/app';
|
||||
import { AppState } from '../index';
|
||||
import { AppState, getRouterState } from '../index';
|
||||
import {
|
||||
ActionTypes as UserConfigActions,
|
||||
ApplyUserConfigurationFromFileAction,
|
||||
@@ -56,8 +55,14 @@ export class DeviceEffects {
|
||||
@Effect()
|
||||
deviceConnectionStateChange$: Observable<Action> = this.actions$
|
||||
.ofType<ConnectionStateChangedAction>(ActionTypes.CONNECTION_STATE_CHANGED)
|
||||
.map(action => action.payload)
|
||||
.do((state: DeviceConnectionState) => {
|
||||
.withLatestFrom(this.store.select(getRouterState))
|
||||
.do(([action, route]) => {
|
||||
const state = action.payload;
|
||||
|
||||
if (route.state && route.state.url.startsWith('/device/firmware')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.hasPermission) {
|
||||
this.router.navigate(['/privilege']);
|
||||
}
|
||||
@@ -71,7 +76,9 @@ export class DeviceEffects {
|
||||
this.router.navigate(['/detection']);
|
||||
}
|
||||
})
|
||||
.switchMap((state: DeviceConnectionState) => {
|
||||
.switchMap(([action, route]) => {
|
||||
const state = action.payload;
|
||||
|
||||
if (state.connected && state.hasPermission) {
|
||||
return Observable.of(new LoadConfigFromDeviceAction());
|
||||
}
|
||||
@@ -203,18 +210,18 @@ export class DeviceEffects {
|
||||
@Effect() updateFirmwareReply$ = this.actions$
|
||||
.ofType<UpdateFirmwareReplyAction>(ActionTypes.UPDATE_FIRMWARE_REPLY)
|
||||
.map(action => action.payload)
|
||||
.switchMap((response: IpcResponse) => {
|
||||
.switchMap((response: FirmwareUpgradeIpcResponse)
|
||||
: Observable<UpdateFirmwareSuccessAction | UpdateFirmwareFailedAction> => {
|
||||
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$
|
||||
.ofType<ResetUserConfigurationAction>(ActionTypes.RESTORE_CONFIGURATION_FROM_BACKUP)
|
||||
.map(() => new SaveConfigurationAction());
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
|
||||
import { DataStorageRepositoryService } from '../../services/datastorage-repository.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 {
|
||||
DismissUndoNotificationAction,
|
||||
@@ -118,8 +118,10 @@ export class UserConfigEffects {
|
||||
|
||||
@Effect() loadConfigFromDeviceReply$ = this.actions$
|
||||
.ofType<LoadConfigFromDeviceReplyAction>(ActionTypes.LOAD_CONFIG_FROM_DEVICE_REPLY)
|
||||
.map(action => action.payload)
|
||||
.mergeMap((data: ConfigurationReply): any => {
|
||||
.withLatestFrom(this.store.select(getRouterState))
|
||||
.mergeMap(([action, route]): any => {
|
||||
const data: ConfigurationReply = action.payload;
|
||||
|
||||
if (!data.success) {
|
||||
return [new ShowNotificationAction({
|
||||
type: NotificationType.Error,
|
||||
@@ -128,12 +130,16 @@ export class UserConfigEffects {
|
||||
}
|
||||
|
||||
const result = [];
|
||||
let newPageDestination = ['/'];
|
||||
let newPageDestination: Array<string>;
|
||||
|
||||
try {
|
||||
const userConfig = getUserConfigFromDeviceResponse(data.userConfiguration);
|
||||
result.push(new LoadUserConfigSuccessAction(userConfig));
|
||||
|
||||
if (route.state && !route.state.url.startsWith('/device/firmware')) {
|
||||
newPageDestination = ['/'];
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
this.logService.error('Eeprom user-config parse error:', err);
|
||||
const userConfig = new UserConfiguration().fromJsonObject(data.backupConfiguration);
|
||||
@@ -158,7 +164,9 @@ export class UserConfigEffects {
|
||||
|
||||
result.push(new HardwareModulesLoadedAction(data.modules));
|
||||
|
||||
this.router.navigate(newPageDestination);
|
||||
if (newPageDestination) {
|
||||
this.router.navigate(newPageDestination);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import { MetaReducer } from '@ngrx/store';
|
||||
import { RouterReducerState } from '@ngrx/router-store';
|
||||
import { ActionReducerMap, MetaReducer } from '@ngrx/store';
|
||||
import { RouterReducerState, routerReducer } from '@ngrx/router-store';
|
||||
import { storeFreeze } from 'ngrx-store-freeze';
|
||||
import { Keymap, UserConfiguration } from 'uhk-common';
|
||||
|
||||
@@ -14,15 +14,6 @@ import { initProgressButtonState } from './reducers/progress-button-state';
|
||||
import { environment } from '../../environments/environment';
|
||||
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
|
||||
export interface AppState {
|
||||
userConfiguration: UserConfiguration;
|
||||
@@ -34,6 +25,16 @@ export interface AppState {
|
||||
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
|
||||
? []
|
||||
: [storeFreeze];
|
||||
@@ -73,7 +74,6 @@ export const saveToKeyboardState = createSelector(runningInElectron, saveToKeybo
|
||||
});
|
||||
export const updatingFirmware = createSelector(deviceState, fromDevice.updatingFirmware);
|
||||
export const xtermLog = createSelector(deviceState, fromDevice.xtermLog);
|
||||
export const firmwareOkButtonDisabled = createSelector(deviceState, fromDevice.firmwareOkButtonDisabled);
|
||||
// tslint:disable-next-line: max-line-length
|
||||
export const flashFirmwareButtonDisbabled = createSelector(runningInElectron, deviceState, (electron, state: fromDevice.State) => !electron || state.updatingFirmware);
|
||||
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,
|
||||
SaveConfigurationAction,
|
||||
HasBackupUserConfigurationAction,
|
||||
UpdateFirmwareFailedAction
|
||||
UpdateFirmwareFailedAction,
|
||||
UpdateFirmwareSuccessAction
|
||||
} from '../actions/device';
|
||||
import { ActionTypes as AppActions, ElectronMainLogReceivedAction } from '../actions/app';
|
||||
import { initProgressButtonState, ProgressButtonState } from './progress-button-state';
|
||||
@@ -19,6 +20,7 @@ export interface State {
|
||||
hasPermission: boolean;
|
||||
bootloaderActive: boolean;
|
||||
saveToKeyboard: ProgressButtonState;
|
||||
savingToKeyboard: boolean;
|
||||
updatingFirmware: boolean;
|
||||
firmwareUpdateFinished: boolean;
|
||||
modules: HardwareModules;
|
||||
@@ -32,6 +34,7 @@ export const initialState: State = {
|
||||
hasPermission: true,
|
||||
bootloaderActive: false,
|
||||
saveToKeyboard: initProgressButtonState,
|
||||
savingToKeyboard: false,
|
||||
updatingFirmware: false,
|
||||
firmwareUpdateFinished: false,
|
||||
modules: {
|
||||
@@ -48,7 +51,7 @@ export const initialState: State = {
|
||||
hasBackupUserConfiguration: false
|
||||
};
|
||||
|
||||
export function reducer(state = initialState, action: Action) {
|
||||
export function reducer(state = initialState, action: Action): State {
|
||||
switch (action.type) {
|
||||
case ActionTypes.CONNECTION_STATE_CHANGED: {
|
||||
const data = (<ConnectionStateChangedAction>action).payload;
|
||||
@@ -132,12 +135,14 @@ export function reducer(state = initialState, action: Action) {
|
||||
return {
|
||||
...state,
|
||||
updatingFirmware: false,
|
||||
firmwareUpdateFinished: true
|
||||
firmwareUpdateFinished: true,
|
||||
modules: (action as UpdateFirmwareSuccessAction).payload
|
||||
};
|
||||
|
||||
case ActionTypes.UPDATE_FIRMWARE_FAILED: {
|
||||
const data = (action as UpdateFirmwareFailedAction).payload;
|
||||
const logEntry = {
|
||||
message: (action as UpdateFirmwareFailedAction).payload.message,
|
||||
message: data.error.message,
|
||||
cssClass: XtermCssClass.error
|
||||
};
|
||||
|
||||
@@ -145,6 +150,7 @@ export function reducer(state = initialState, action: Action) {
|
||||
...state,
|
||||
updatingFirmware: false,
|
||||
firmwareUpdateFinished: true,
|
||||
modules: data.modules,
|
||||
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 getSaveToKeyboardState = (state: State) => state.saveToKeyboard;
|
||||
export const xtermLog = (state: State) => state.log;
|
||||
export const firmwareOkButtonDisabled = (state: State) => !state.firmwareUpdateFinished;
|
||||
export const getHardwareModules = (state: State) => state.modules;
|
||||
export const getHasBackupUserConfiguration = (state: State) => state.hasBackupUserConfiguration;
|
||||
export const getBackupUserConfigurationState = (state: State): RestoreConfigurationState => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Action } from '@ngrx/store';
|
||||
export interface ProgressButtonState {
|
||||
showButton: boolean;
|
||||
text: string;
|
||||
showProgress: boolean;
|
||||
showProgress?: boolean;
|
||||
action?: Action;
|
||||
}
|
||||
|
||||
|
||||
@@ -158,14 +158,14 @@ pre {
|
||||
|
||||
.flex-container {
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flex-grow {
|
||||
background-color: black;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user