Redirection accross components based on UHK state
This commit is contained in:
@@ -79,7 +79,10 @@ import { DataStorage } from './shared/store/storage';
|
|||||||
import { KeymapEditGuard } from './shared/components/keymap/edit';
|
import { KeymapEditGuard } from './shared/components/keymap/edit';
|
||||||
import { MacroNotFoundGuard } from './shared/components/macro/not-found';
|
import { MacroNotFoundGuard } from './shared/components/macro/not-found';
|
||||||
|
|
||||||
import { UHkConnectedGuard } from './services/uhk-connected.guard';
|
import { UhkDeviceConnectedGuard } from './services/uhk-device-connected.guard';
|
||||||
|
import { UhkDeviceDisconnectedGuard } from './services/uhk-device-disconnected.guard';
|
||||||
|
import { UhkDeviceInitializedGuard } from './services/uhk-device-initialized.guard';
|
||||||
|
import { UhkDeviceUninitializedGuard } from './services/uhk-device-uninitialized.guard';
|
||||||
|
|
||||||
// Create DataStorage dependency injection
|
// Create DataStorage dependency injection
|
||||||
const storageProvider = ReflectiveInjector.resolve([DataStorage]);
|
const storageProvider = ReflectiveInjector.resolve([DataStorage]);
|
||||||
@@ -164,7 +167,10 @@ const storeConfig = {
|
|||||||
EffectsModule.runAfterBootstrap(MacroEffects)
|
EffectsModule.runAfterBootstrap(MacroEffects)
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
UHkConnectedGuard,
|
UhkDeviceConnectedGuard,
|
||||||
|
UhkDeviceDisconnectedGuard,
|
||||||
|
UhkDeviceInitializedGuard,
|
||||||
|
UhkDeviceUninitializedGuard,
|
||||||
MapperService,
|
MapperService,
|
||||||
appRoutingProviders,
|
appRoutingProviders,
|
||||||
KeymapEditGuard,
|
KeymapEditGuard,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { UHkConnectedGuard } from './../services/uhk-connected.guard';
|
|
||||||
import { ModuleWithProviders } from '@angular/core';
|
import { ModuleWithProviders } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
@@ -7,19 +6,26 @@ import { PrivilegeCheckerComponent } from './../components/privilege-checker';
|
|||||||
import { MainAppComponent } from './../main-app/main-app.component';
|
import { MainAppComponent } from './../main-app/main-app.component';
|
||||||
import { mainAppRoutes } from './../main-app/main-app.routes';
|
import { mainAppRoutes } from './../main-app/main-app.routes';
|
||||||
|
|
||||||
|
import { UhkDeviceConnectedGuard } from './../services/uhk-device-connected.guard';
|
||||||
|
import { UhkDeviceDisconnectedGuard } from './../services/uhk-device-disconnected.guard';
|
||||||
|
import { UhkDeviceInitializedGuard } from './../services/uhk-device-initialized.guard';
|
||||||
|
import { UhkDeviceUninitializedGuard } from './../services/uhk-device-uninitialized.guard';
|
||||||
|
|
||||||
const appRoutes: Routes = [
|
const appRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'detection',
|
path: 'detection',
|
||||||
component: MissingDeviceComponent
|
component: MissingDeviceComponent,
|
||||||
|
canActivate: [UhkDeviceDisconnectedGuard]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'privilege',
|
path: 'privilege',
|
||||||
component: PrivilegeCheckerComponent
|
component: PrivilegeCheckerComponent,
|
||||||
|
canActivate: [UhkDeviceConnectedGuard, UhkDeviceUninitializedGuard]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: MainAppComponent,
|
component: MainAppComponent,
|
||||||
canActivate: [UHkConnectedGuard],
|
canActivate: [UhkDeviceInitializedGuard],
|
||||||
children: mainAppRoutes
|
children: mainAppRoutes
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class MissingDeviceComponent {
|
|||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.subscribe({
|
.subscribe({
|
||||||
complete: () => {
|
complete: () => {
|
||||||
router.navigate(['/privilige']);
|
router.navigate(['/privilege']);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ import { Router } from '@angular/router';
|
|||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import 'rxjs/add/observable/of';
|
import 'rxjs/add/observable/of';
|
||||||
|
import 'rxjs/add/observable/throw';
|
||||||
|
import 'rxjs/add/operator/distinctUntilChanged';
|
||||||
|
import 'rxjs/add/operator/ignoreElements';
|
||||||
|
import 'rxjs/add/operator/takeWhile';
|
||||||
|
|
||||||
|
import { UhkDeviceService } from './../../services/uhk-device.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'privilege-checker',
|
selector: 'privilege-checker',
|
||||||
@@ -11,13 +17,17 @@ import 'rxjs/add/observable/of';
|
|||||||
})
|
})
|
||||||
export class PrivilegeCheckerComponent {
|
export class PrivilegeCheckerComponent {
|
||||||
|
|
||||||
constructor(router: Router) {
|
constructor(private router: Router, private uhkDevice: UhkDeviceService) {
|
||||||
this.checkPermissions()
|
uhkDevice.isConnected()
|
||||||
.subscribe(hasPermisson => {
|
.distinctUntilChanged()
|
||||||
if (hasPermisson) {
|
.takeWhile(connected => connected)
|
||||||
router.navigate(['/privilige']);
|
.ignoreElements()
|
||||||
|
.subscribe({
|
||||||
|
complete: () => {
|
||||||
|
router.navigate(['/detection']);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPermissions(): Observable<boolean> {
|
checkPermissions(): Observable<boolean> {
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import { UhkDeviceService } from '../services/uhk-device.service';
|
|||||||
export class MainAppComponent {
|
export class MainAppComponent {
|
||||||
|
|
||||||
constructor(private uhkDevice: UhkDeviceService, private store: Store<AppState>, router: Router) {
|
constructor(private uhkDevice: UhkDeviceService, private store: Store<AppState>, router: Router) {
|
||||||
uhkDevice.isConnected()
|
uhkDevice.isInitialized()
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.takeWhile(connected => connected)
|
.takeWhile(initialized => initialized)
|
||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.subscribe({
|
.subscribe({
|
||||||
complete: () => {
|
complete: () => {
|
||||||
|
|||||||
+2
-4
@@ -3,21 +3,19 @@ import { Injectable } from '@angular/core';
|
|||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import 'rxjs/add/operator/do';
|
import 'rxjs/add/operator/do';
|
||||||
import 'rxjs/add/operator/first';
|
|
||||||
|
|
||||||
import { UhkDeviceService } from './uhk-device.service';
|
import { UhkDeviceService } from './uhk-device.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UHkConnectedGuard implements CanActivate {
|
export class UhkDeviceConnectedGuard implements CanActivate {
|
||||||
|
|
||||||
constructor(private uhkDevice: UhkDeviceService, private router: Router) { }
|
constructor(private uhkDevice: UhkDeviceService, private router: Router) { }
|
||||||
|
|
||||||
canActivate(): Observable<boolean> {
|
canActivate(): Observable<boolean> {
|
||||||
return this.uhkDevice.isConnected()
|
return this.uhkDevice.isConnected()
|
||||||
.first()
|
|
||||||
.do(connected => {
|
.do(connected => {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
return this.router.navigate(['/detection']);
|
this.router.navigate(['/detection']);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { CanActivate, Router } from '@angular/router';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import 'rxjs/add/operator/do';
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
|
import { UhkDeviceService } from './uhk-device.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UhkDeviceDisconnectedGuard implements CanActivate {
|
||||||
|
|
||||||
|
constructor(private uhkDevice: UhkDeviceService, private router: Router) { }
|
||||||
|
|
||||||
|
canActivate(): Observable<boolean> {
|
||||||
|
return this.uhkDevice.isConnected()
|
||||||
|
.do(connected => {
|
||||||
|
if (connected) {
|
||||||
|
this.router.navigate(['/privilege']);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(connected => !connected);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { CanActivate, Router } from '@angular/router';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import 'rxjs/add/operator/do';
|
||||||
|
|
||||||
|
import { UhkDeviceService } from './uhk-device.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UhkDeviceInitializedGuard implements CanActivate {
|
||||||
|
|
||||||
|
constructor(private uhkDevice: UhkDeviceService, private router: Router) { }
|
||||||
|
|
||||||
|
canActivate(): Observable<boolean> {
|
||||||
|
return this.uhkDevice.isInitialized()
|
||||||
|
.do(initialized => {
|
||||||
|
if (!initialized) {
|
||||||
|
this.router.navigate(['/detection']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { CanActivate, Router } from '@angular/router';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import 'rxjs/add/operator/do';
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
|
import { UhkDeviceService } from './uhk-device.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UhkDeviceUninitializedGuard implements CanActivate {
|
||||||
|
|
||||||
|
constructor(private uhkDevice: UhkDeviceService, private router: Router) { }
|
||||||
|
|
||||||
|
canActivate(): Observable<boolean> {
|
||||||
|
return this.uhkDevice.isInitialized()
|
||||||
|
.do(initialized => {
|
||||||
|
if (initialized) {
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(initialized => !initialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Injectable, OnDestroy, NgZone } from '@angular/core';
|
import { Injectable, OnDestroy, NgZone } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
import { Observer } from 'rxjs/Observer';
|
import { Observer } from 'rxjs/Observer';
|
||||||
@@ -9,11 +10,14 @@ import { Subscription } from 'rxjs/Subscription';
|
|||||||
|
|
||||||
import 'rxjs/add/observable/empty';
|
import 'rxjs/add/observable/empty';
|
||||||
import 'rxjs/add/observable/from';
|
import 'rxjs/add/observable/from';
|
||||||
|
import 'rxjs/add/observable/of';
|
||||||
import 'rxjs/add/operator/catch';
|
import 'rxjs/add/operator/catch';
|
||||||
import 'rxjs/add/operator/concat';
|
import 'rxjs/add/operator/concat';
|
||||||
|
import 'rxjs/add/operator/combineLatest';
|
||||||
import 'rxjs/add/operator/concatMap';
|
import 'rxjs/add/operator/concatMap';
|
||||||
import 'rxjs/add/operator/mergeMap';
|
import 'rxjs/add/operator/mergeMap';
|
||||||
import 'rxjs/add/operator/publish';
|
import 'rxjs/add/operator/publish';
|
||||||
|
import 'rxjs/add/operator/switchMap';
|
||||||
|
|
||||||
import { Device, Interface, InEndpoint, OutEndpoint, findByIds, on } from 'usb';
|
import { Device, Interface, InEndpoint, OutEndpoint, findByIds, on } from 'usb';
|
||||||
|
|
||||||
@@ -38,7 +42,9 @@ interface SenderMessage {
|
|||||||
export class UhkDeviceService implements OnDestroy {
|
export class UhkDeviceService implements OnDestroy {
|
||||||
|
|
||||||
private device: Device;
|
private device: Device;
|
||||||
|
private deviceOpened$: BehaviorSubject<boolean>;
|
||||||
private connected$: BehaviorSubject<boolean>;
|
private connected$: BehaviorSubject<boolean>;
|
||||||
|
private initizalized$: BehaviorSubject<boolean>;
|
||||||
|
|
||||||
private messageIn$: Observable<Buffer>;
|
private messageIn$: Observable<Buffer>;
|
||||||
private messageOut$: Subject<SenderMessage>;
|
private messageOut$: Subject<SenderMessage>;
|
||||||
@@ -47,8 +53,12 @@ export class UhkDeviceService implements OnDestroy {
|
|||||||
|
|
||||||
constructor(zone: NgZone) {
|
constructor(zone: NgZone) {
|
||||||
this.messageOut$ = new Subject<SenderMessage>();
|
this.messageOut$ = new Subject<SenderMessage>();
|
||||||
|
this.initizalized$ = new BehaviorSubject(false);
|
||||||
this.connected$ = new BehaviorSubject(false);
|
this.connected$ = new BehaviorSubject(false);
|
||||||
this.connect();
|
this.deviceOpened$ = new BehaviorSubject(false);
|
||||||
|
this.outSubscription = Subscription.EMPTY;
|
||||||
|
|
||||||
|
this.initialize();
|
||||||
|
|
||||||
// The change detection doesn't work properly if the callbacks are called outside Angular Zone
|
// The change detection doesn't work properly if the callbacks are called outside Angular Zone
|
||||||
on('attach', (device: Device) => zone.run(() => this.onDeviceAttach(device)));
|
on('attach', (device: Device) => zone.run(() => this.onDeviceAttach(device)));
|
||||||
@@ -57,18 +67,27 @@ export class UhkDeviceService implements OnDestroy {
|
|||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
|
this.initizalized$.unsubscribe();
|
||||||
this.connected$.unsubscribe();
|
this.connected$.unsubscribe();
|
||||||
|
this.deviceOpened$.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(): void {
|
initialize(): void {
|
||||||
if (this.connected$.getValue()) {
|
if (this.initizalized$.getValue()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.device = findByIds(vendorId, productId);
|
this.device = findByIds(vendorId, productId);
|
||||||
|
this.connected$.next(!!this.device);
|
||||||
if (!this.device) {
|
if (!this.device) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.device.open();
|
try {
|
||||||
|
this.device.open();
|
||||||
|
this.deviceOpened$.next(true);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const usbInterface: Interface = this.device.interface(0);
|
const usbInterface: Interface = this.device.interface(0);
|
||||||
// https://github.com/tessel/node-usb/issues/147
|
// https://github.com/tessel/node-usb/issues/147
|
||||||
@@ -114,22 +133,50 @@ export class UhkDeviceService implements OnDestroy {
|
|||||||
}).publish();
|
}).publish();
|
||||||
this.outSubscription = outSending.connect();
|
this.outSubscription = outSending.connect();
|
||||||
|
|
||||||
this.connected$.next(true);
|
this.initizalized$.next(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
if (!this.connected$.getValue()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.outSubscription.unsubscribe();
|
this.outSubscription.unsubscribe();
|
||||||
this.messageIn$ = undefined;
|
this.messageIn$ = undefined;
|
||||||
|
this.initizalized$.next(false);
|
||||||
|
this.deviceOpened$.next(false);
|
||||||
this.connected$.next(false);
|
this.connected$.next(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isInitialized(): Observable<boolean> {
|
||||||
|
return this.initizalized$.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
isConnected(): Observable<boolean> {
|
isConnected(): Observable<boolean> {
|
||||||
return this.connected$.asObservable();
|
return this.connected$.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasPermissions(): Observable<boolean> {
|
||||||
|
return this.isConnected()
|
||||||
|
.combineLatest(this.deviceOpened$)
|
||||||
|
.map((latest: boolean[]) => {
|
||||||
|
const connected = latest[0];
|
||||||
|
const opened = latest[1];
|
||||||
|
if (!connected) {
|
||||||
|
return false;
|
||||||
|
} else if (opened) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.device.open();
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.device.close();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isOpened(): Observable<boolean> {
|
||||||
|
return this.deviceOpened$.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
sendConfig(configBuffer: Buffer): Observable<Buffer> {
|
sendConfig(configBuffer: Buffer): Observable<Buffer> {
|
||||||
return Observable.create((subscriber: Subscriber<Buffer>) => {
|
return Observable.create((subscriber: Subscriber<Buffer>) => {
|
||||||
console.log('Sending...', configBuffer);
|
console.log('Sending...', configBuffer);
|
||||||
@@ -176,18 +223,14 @@ export class UhkDeviceService implements OnDestroy {
|
|||||||
if (device.deviceDescriptor.idVendor !== vendorId || device.deviceDescriptor.idProduct !== productId) {
|
if (device.deviceDescriptor.idVendor !== vendorId || device.deviceDescriptor.idProduct !== productId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.connected$.getValue()) {
|
this.initialize();
|
||||||
this.connect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onDeviceDetach(device: Device) {
|
onDeviceDetach(device: Device) {
|
||||||
if (device.deviceDescriptor.idVendor !== vendorId || device.deviceDescriptor.idProduct !== productId) {
|
if (device.deviceDescriptor.idVendor !== vendorId || device.deviceDescriptor.idProduct !== productId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.connected$.getValue()) {
|
this.disconnect();
|
||||||
this.disconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user