feat(agent): Add loading screen (#444)
* feat(uhk-message): Add spin animation * feat(agent): Add loading page * fix device connected / disconnected events
This commit is contained in:
committed by
László Monda
parent
01b07a3ab7
commit
737897b40e
@@ -26,7 +26,7 @@
|
||||
|
||||
"unit-case": "lower",
|
||||
"unit-no-unknown": true,
|
||||
"unit-whitelist": ["px", "%", "deg", "ms", "em", "rem", "vh", "vv"],
|
||||
"unit-whitelist": ["px", "%", "deg", "ms", "em", "rem", "vh", "vv", "s"],
|
||||
|
||||
"value-list-comma-space-after": "always-single-line",
|
||||
"value-list-comma-space-before": "never",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
(doNotUpdateApp)="doNotUpdateApp()">
|
||||
</app-update-available>
|
||||
|
||||
<side-menu *ngIf="deviceConnected$ | async"></side-menu>
|
||||
<side-menu *ngIf="deviceConfigurationLoaded$ | async"></side-menu>
|
||||
<div id="main-content" class="main-content">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { DoNotUpdateAppAction, UpdateAppAction } from './store/actions/app-updat
|
||||
import {
|
||||
AppState,
|
||||
getShowAppUpdateAvailable,
|
||||
deviceConnected,
|
||||
deviceConfigurationLoaded,
|
||||
runningInElectron,
|
||||
saveToKeyboardState
|
||||
} from './store';
|
||||
@@ -37,13 +37,13 @@ import { SaveUserConfigInBinaryFileAction, SaveUserConfigInJsonFileAction } from
|
||||
})
|
||||
export class MainAppComponent {
|
||||
showUpdateAvailable$: Observable<boolean>;
|
||||
deviceConnected$: Observable<boolean>;
|
||||
deviceConfigurationLoaded$: Observable<boolean>;
|
||||
runningInElectron$: Observable<boolean>;
|
||||
saveToKeyboardState$: Observable<ProgressButtonState>;
|
||||
|
||||
constructor(private store: Store<AppState>) {
|
||||
this.showUpdateAvailable$ = store.select(getShowAppUpdateAvailable);
|
||||
this.deviceConnected$ = store.select(deviceConnected);
|
||||
this.deviceConfigurationLoaded$ = store.select(deviceConfigurationLoaded);
|
||||
this.runningInElectron$ = store.select(runningInElectron);
|
||||
this.saveToKeyboardState$ = store.select(saveToKeyboardState);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ import { UhkDeviceUninitializedGuard } from './services/uhk-device-uninitialized
|
||||
import { UhkDeviceInitializedGuard } from './services/uhk-device-initialized.guard';
|
||||
import { MainPage } from './pages/main-page/main.page';
|
||||
import { settingsRoutes } from './components/settings/settings.routes';
|
||||
import { LoadingDevicePageComponent } from './pages/loading-page/loading-device.page';
|
||||
import { UhkDeviceLoadingGuard } from './services/uhk-device-loading.guard';
|
||||
import { UhkDeviceLoadedGuard } from './services/uhk-device-loaded.guard';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
@@ -25,10 +28,15 @@ const appRoutes: Routes = [
|
||||
component: PrivilegeCheckerComponent,
|
||||
canActivate: [UhkDeviceInitializedGuard]
|
||||
},
|
||||
{
|
||||
path: 'loading',
|
||||
component: LoadingDevicePageComponent,
|
||||
canActivate: [UhkDeviceLoadedGuard]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: MainPage,
|
||||
canActivate: [UhkDeviceDisconnectedGuard],
|
||||
canActivate: [UhkDeviceDisconnectedGuard, UhkDeviceLoadingGuard],
|
||||
children: [
|
||||
...deviceRoutes,
|
||||
...keymapRoutes,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<span class="uhk-message-wrapper">
|
||||
<img class="agent-logo" src="assets/images/agent-icon.png"/>
|
||||
<img class="agent-logo spin-logo"
|
||||
[ngClass]="{'spin-logo': rotateLogo}"
|
||||
src="assets/images/agent-icon.png"/>
|
||||
<div class="messages">
|
||||
<h1> {{ title }} </h1>
|
||||
<h2> {{ subtitle }} </h2>
|
||||
|
||||
@@ -17,3 +17,23 @@
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.spin-logo {
|
||||
-webkit-animation: spin 2s ease-in-out infinite;
|
||||
-moz-animation: spin 2s ease-in-out infinite;
|
||||
animation: spin 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,4 +9,5 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
|
||||
export class UhkMessageComponent {
|
||||
@Input() title: string;
|
||||
@Input() subtitle: string;
|
||||
@Input() rotateLogo = false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'loading-device',
|
||||
template: `
|
||||
<uhk-message title="Loading Agent..."
|
||||
subtitle="Hang tight!"
|
||||
[rotateLogo]="true"></uhk-message>
|
||||
`
|
||||
})
|
||||
export class LoadingDevicePageComponent {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
25
packages/uhk-web/src/app/services/uhk-device-loaded.guard.ts
Normal file
25
packages/uhk-web/src/app/services/uhk-device-loaded.guard.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { CanActivate, Router } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/do';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
import { AppState, deviceConfigurationLoaded } from '../store';
|
||||
|
||||
@Injectable()
|
||||
export class UhkDeviceLoadedGuard implements CanActivate {
|
||||
|
||||
constructor(private store: Store<AppState>, private router: Router) { }
|
||||
|
||||
canActivate(): Observable<boolean> {
|
||||
return this.store.select(deviceConfigurationLoaded)
|
||||
.do(loaded => {
|
||||
if (loaded) {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
})
|
||||
.map(loaded => !loaded);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { CanActivate, Router } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/do';
|
||||
|
||||
import { AppState, deviceConfigurationLoaded } from '../store';
|
||||
|
||||
@Injectable()
|
||||
export class UhkDeviceLoadingGuard implements CanActivate {
|
||||
|
||||
constructor(private store: Store<AppState>, private router: Router) { }
|
||||
|
||||
canActivate(): Observable<boolean> {
|
||||
return this.store.select(deviceConfigurationLoaded)
|
||||
.do(loaded => {
|
||||
if (!loaded) {
|
||||
this.router.navigate(['/loading']);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -85,11 +85,13 @@ import { UhkDeviceConnectedGuard } from './services/uhk-device-connected.guard';
|
||||
import { UhkDeviceDisconnectedGuard } from './services/uhk-device-disconnected.guard';
|
||||
import { UhkDeviceUninitializedGuard } from './services/uhk-device-uninitialized.guard';
|
||||
import { MainPage } from './pages/main-page/main.page';
|
||||
import { DeviceEffects } from './store/effects/device';
|
||||
import { DeviceRendererService } from './services/device-renderer.service';
|
||||
import { UhkDeviceInitializedGuard } from './services/uhk-device-initialized.guard';
|
||||
import { ProgressButtonComponent } from './components/progress-button/progress-button.component';
|
||||
import { MainAppComponent } from './app.component';
|
||||
import { LoadingDevicePageComponent } from './pages/loading-page/loading-device.page';
|
||||
import { UhkDeviceLoadingGuard } from './services/uhk-device-loading.guard';
|
||||
import { UhkDeviceLoadedGuard } from './services/uhk-device-loaded.guard';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -151,7 +153,8 @@ import { MainAppComponent } from './app.component';
|
||||
MissingDeviceComponent,
|
||||
PrivilegeCheckerComponent,
|
||||
MainPage,
|
||||
ProgressButtonComponent
|
||||
ProgressButtonComponent,
|
||||
LoadingDevicePageComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@@ -180,7 +183,9 @@ import { MainAppComponent } from './app.component';
|
||||
UhkDeviceConnectedGuard,
|
||||
UhkDeviceDisconnectedGuard,
|
||||
UhkDeviceInitializedGuard,
|
||||
UhkDeviceUninitializedGuard
|
||||
UhkDeviceUninitializedGuard,
|
||||
UhkDeviceLoadingGuard,
|
||||
UhkDeviceLoadedGuard
|
||||
],
|
||||
exports: [
|
||||
UhkMessageComponent,
|
||||
|
||||
@@ -135,6 +135,7 @@ export class UserConfigEffects {
|
||||
try {
|
||||
const userConfig = UserConfigEffects.getUserConfigFromDeviceResponse(data.userConfiguration);
|
||||
const hardwareConfig = UserConfigEffects.getHardwareConfigFromDeviceResponse(data.hardwareConfiguration);
|
||||
this.router.navigate(['/']);
|
||||
|
||||
return [
|
||||
new LoadUserConfigSuccessAction(userConfig),
|
||||
|
||||
@@ -47,6 +47,7 @@ export const getPrevUserConfiguration = createSelector(appState, fromApp.getPrev
|
||||
export const runningInElectron = createSelector(appState, fromApp.runningInElectron);
|
||||
export const getHardwareConfiguration = createSelector(appState, fromApp.getHardwareConfiguration);
|
||||
export const getKeyboardLayout = createSelector(appState, fromApp.getKeyboardLayout);
|
||||
export const deviceConfigurationLoaded = createSelector(appState, fromApp.deviceConfigurationLoaded);
|
||||
|
||||
export const appUpdateState = (state: AppState) => state.appUpdate;
|
||||
export const getShowAppUpdateAvailable = createSelector(appUpdateState, fromAppUpdate.getShowAppUpdateAvailable);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Action } from '@ngrx/store';
|
||||
import { HardwareConfiguration, runInElectron, Notification, NotificationType, UserConfiguration } from 'uhk-common';
|
||||
import { ActionTypes, ShowNotificationAction } from '../actions/app';
|
||||
import { ActionTypes as UserConfigActionTypes } from '../actions/user-config';
|
||||
import { ActionTypes as DeviceActionTypes } from '../actions/device';
|
||||
import { KeyboardLayout } from '../../keyboard/keyboard-layout.enum';
|
||||
|
||||
export interface State {
|
||||
@@ -57,7 +58,7 @@ export function reducer(state = initialState, action: Action & { payload: any })
|
||||
// When deleted a keymap or macro the app automaticaly navigate to other keymap, or macro, so
|
||||
// so we have to count the navigations and when reach the 2nd then remove the dialog.
|
||||
case ROUTER_NAVIGATION: {
|
||||
const newState = { ...state };
|
||||
const newState = {...state};
|
||||
newState.navigationCountAfterNotification++;
|
||||
|
||||
if (newState.navigationCountAfterNotification > 1) {
|
||||
@@ -98,6 +99,17 @@ export function reducer(state = initialState, action: Action & { payload: any })
|
||||
hardwareConfig: action.payload
|
||||
};
|
||||
|
||||
case DeviceActionTypes.CONNECTION_STATE_CHANGED:
|
||||
|
||||
if (action.payload === true) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
hardwareConfig: null
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@@ -115,3 +127,4 @@ export const getKeyboardLayout = (state: State): KeyboardLayout => {
|
||||
|
||||
return KeyboardLayout.ANSI;
|
||||
};
|
||||
export const deviceConfigurationLoaded = (state: State) => !state.runningInElectron ? true : !!state.hardwareConfig;
|
||||
|
||||
Reference in New Issue
Block a user