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:
Róbert Kiss
2017-10-14 01:22:44 +02:00
committed by László Monda
parent 01b07a3ab7
commit 737897b40e
14 changed files with 125 additions and 11 deletions

View File

@@ -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",

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -9,4 +9,5 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
export class UhkMessageComponent {
@Input() title: string;
@Input() subtitle: string;
@Input() rotateLogo = false;
}

View File

@@ -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() {
}
}

View 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);
}
}

View File

@@ -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']);
}
});
}
}

View File

@@ -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,

View File

@@ -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),

View File

@@ -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);

View File

@@ -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 {
@@ -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;