committed by
József Farkas
parent
c2103c7d50
commit
715b924be0
@@ -10,6 +10,7 @@ import { StoreLogMonitorModule, useLogMonitor } from '@ngrx/store-log-monitor';
|
||||
import { DragulaModule } from 'ng2-dragula/ng2-dragula';
|
||||
import { Select2Module } from 'ng2-select2/ng2-select2';
|
||||
|
||||
import { MissingDeviceComponent } from './components/missing-device/missing-device.component';
|
||||
import { AddOnComponent } from './shared/components/add-on';
|
||||
import { KeyboardSliderComponent } from './shared/components/keyboard/slider';
|
||||
import { KeymapAddComponent, KeymapHeaderComponent } from './shared/components/keymap';
|
||||
@@ -59,7 +60,9 @@ import {
|
||||
} from './shared/components/svg/keys';
|
||||
import { SvgModuleComponent } from './shared/components/svg/module';
|
||||
import { SvgKeyboardWrapComponent } from './shared/components/svg/wrap';
|
||||
import { MainAppComponent, appRoutingProviders, routing } from './main-app';
|
||||
import { appRoutingProviders, routing } from './app/app.routes';
|
||||
import { AppComponent } from './app/app.component';
|
||||
import { MainAppComponent } from './main-app';
|
||||
|
||||
import { CancelableDirective } from './shared/directives';
|
||||
|
||||
@@ -74,6 +77,8 @@ import { DataStorage } from './shared/store/storage';
|
||||
import { KeymapEditGuard } from './shared/components/keymap/edit';
|
||||
import { MacroNotFoundGuard } from './shared/components/macro/not-found';
|
||||
|
||||
import { UHkConnectedGuard } from './services/uhk-connected.guard';
|
||||
|
||||
// Create DataStorage dependency injection
|
||||
const storageProvider = ReflectiveInjector.resolve([DataStorage]);
|
||||
const storageInjector = ReflectiveInjector.fromResolvedProviders(storageProvider);
|
||||
@@ -87,6 +92,7 @@ const storeConfig = {
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
MainAppComponent,
|
||||
KeymapEditComponent,
|
||||
KeymapHeaderComponent,
|
||||
@@ -133,6 +139,7 @@ const storeConfig = {
|
||||
AddOnComponent,
|
||||
SettingsComponent,
|
||||
KeyboardSliderComponent,
|
||||
MissingDeviceComponent,
|
||||
CancelableDirective
|
||||
],
|
||||
imports: [
|
||||
@@ -153,6 +160,7 @@ const storeConfig = {
|
||||
EffectsModule.runAfterBootstrap(MacroEffects)
|
||||
],
|
||||
providers: [
|
||||
UHkConnectedGuard,
|
||||
MapperService,
|
||||
appRoutingProviders,
|
||||
KeymapEditGuard,
|
||||
@@ -160,6 +168,6 @@ const storeConfig = {
|
||||
CaptureService,
|
||||
UhkDeviceService
|
||||
],
|
||||
bootstrap: [MainAppComponent]
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
||||
1
electron/src/app/app.component.html
Normal file
1
electron/src/app/app.component.html
Normal file
@@ -0,0 +1 @@
|
||||
<router-outlet></router-outlet>
|
||||
6
electron/src/app/app.component.scss
Normal file
6
electron/src/app/app.component.scss
Normal file
@@ -0,0 +1,6 @@
|
||||
app {
|
||||
display: block;
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
9
electron/src/app/app.component.ts
Normal file
9
electron/src/app/app.component.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
templateUrl: 'app.component.html',
|
||||
styleUrls: ['app.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class AppComponent { }
|
||||
24
electron/src/app/app.routes.ts
Normal file
24
electron/src/app/app.routes.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { UHkConnectedGuard } from './../services/uhk-connected.guard';
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { MissingDeviceComponent } from './../components/missing-device/missing-device.component';
|
||||
import { MainAppComponent } from './../main-app/main-app.component';
|
||||
import { mainAppRoutes } from './../main-app/main-app.routes';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
path: 'detection',
|
||||
component: MissingDeviceComponent
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: MainAppComponent,
|
||||
canActivate: [UHkConnectedGuard],
|
||||
children: mainAppRoutes
|
||||
}
|
||||
];
|
||||
|
||||
export const appRoutingProviders: any[] = [];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes, { useHash: true });
|
||||
1
electron/src/app/index.ts
Normal file
1
electron/src/app/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './app.component';
|
||||
@@ -7,7 +7,7 @@ import { KeymapEditGuard } from '../../shared/components/keymap/edit';
|
||||
export const keymapRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/keymap',
|
||||
redirectTo: 'keymap',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
|
||||
1
electron/src/components/missing-device/index.ts
Normal file
1
electron/src/components/missing-device/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './missing-device.component';
|
||||
@@ -0,0 +1,7 @@
|
||||
<span class="missing-device-wrapper">
|
||||
<img class="agent-logo" src="images/agent-icon.png"/>
|
||||
<div class="messages">
|
||||
<h1> Cannot find your UHK </h1>
|
||||
<h2> Please plug it in! </h2>
|
||||
</div>
|
||||
</span>
|
||||
@@ -0,0 +1,19 @@
|
||||
.missing-device-wrapper {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.agent-logo {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> h2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/distinctUntilChanged';
|
||||
import 'rxjs/add/operator/ignoreElements';
|
||||
import 'rxjs/add/operator/takeWhile';
|
||||
|
||||
import { UhkDeviceService } from './../../services/uhk-device.service';
|
||||
|
||||
@Component({
|
||||
selector: 'missing-device',
|
||||
templateUrl: 'missing-device.component.html',
|
||||
styleUrls: ['missing-device.component.scss']
|
||||
})
|
||||
export class MissingDeviceComponent {
|
||||
|
||||
constructor(uhkDevice: UhkDeviceService, router: Router) {
|
||||
uhkDevice.isConnected()
|
||||
.distinctUntilChanged()
|
||||
.takeWhile(connected => !connected)
|
||||
.ignoreElements()
|
||||
.subscribe({
|
||||
complete: () => {
|
||||
router.navigate(['/']);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
|
||||
<main-app></main-app>
|
||||
<app></app>
|
||||
|
||||
<script src="app.uhk.js"></script> <!-- This should be moved to the head -->
|
||||
</body>
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { Component, ViewEncapsulation, HostListener } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import 'rxjs/add/operator/distinctUntilChanged';
|
||||
import 'rxjs/add/operator/ignoreElements';
|
||||
import 'rxjs/add/operator/takeWhile';
|
||||
|
||||
import { AppState } from '../shared/store';
|
||||
import { getUserConfiguration } from '../shared/store/reducers/user-configuration';
|
||||
|
||||
@@ -17,7 +22,17 @@ import { UhkDeviceService } from '../services/uhk-device.service';
|
||||
})
|
||||
export class MainAppComponent {
|
||||
|
||||
constructor(private uhkDevice: UhkDeviceService, private store: Store<AppState>) { }
|
||||
constructor(private uhkDevice: UhkDeviceService, private store: Store<AppState>, router: Router) {
|
||||
uhkDevice.isConnected()
|
||||
.distinctUntilChanged()
|
||||
.takeWhile(connected => connected)
|
||||
.ignoreElements()
|
||||
.subscribe({
|
||||
complete: () => {
|
||||
router.navigate(['/detection']);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('window:keydown.control.o', ['$event'])
|
||||
onCtrlO(event: KeyboardEvent): void {
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
import { addOnRoutes } from '../shared/components/add-on';
|
||||
import { keymapRoutes } from '../components/keymap';
|
||||
import { macroRoutes } from '../shared/components/macro';
|
||||
import { settingsRoutes } from '../shared/components/settings';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
export const mainAppRoutes: Routes = [
|
||||
...keymapRoutes,
|
||||
...macroRoutes,
|
||||
...addOnRoutes,
|
||||
...settingsRoutes
|
||||
];
|
||||
|
||||
export const appRoutingProviders: any[] = [ ];
|
||||
|
||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes, { useHash: true });
|
||||
|
||||
24
electron/src/services/uhk-connected.guard.ts
Normal file
24
electron/src/services/uhk-connected.guard.ts
Normal file
@@ -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/first';
|
||||
|
||||
import { UhkDeviceService } from './uhk-device.service';
|
||||
|
||||
@Injectable()
|
||||
export class UHkConnectedGuard implements CanActivate {
|
||||
|
||||
constructor(private uhkDevice: UhkDeviceService, private router: Router) { }
|
||||
|
||||
canActivate(): Observable<boolean> {
|
||||
return this.uhkDevice.isConnected()
|
||||
.first()
|
||||
.do(connected => {
|
||||
if (!connected) {
|
||||
return this.router.navigate(['/detection']);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, OnDestroy, NgZone } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import { Observer } from 'rxjs/Observer';
|
||||
import { ConnectableObservable } from 'rxjs/observable/ConnectableObservable';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
@@ -14,7 +15,7 @@ import 'rxjs/add/operator/concatMap';
|
||||
import 'rxjs/add/operator/mergeMap';
|
||||
import 'rxjs/add/operator/publish';
|
||||
|
||||
import { Device, Interface, InEndpoint, OutEndpoint, findByIds } from 'usb';
|
||||
import { Device, Interface, InEndpoint, OutEndpoint, findByIds, on } from 'usb';
|
||||
|
||||
import { Layer } from '../shared/config-serializer/config-items/Layer';
|
||||
import { UhkBuffer } from '../shared/config-serializer/UhkBuffer';
|
||||
@@ -34,28 +35,38 @@ interface SenderMessage {
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class UhkDeviceService {
|
||||
export class UhkDeviceService implements OnDestroy {
|
||||
|
||||
private device: Device;
|
||||
private connected: boolean;
|
||||
private connected$: BehaviorSubject<boolean>;
|
||||
|
||||
private messageIn$: Observable<Buffer>;
|
||||
private messageOut$: Subject<SenderMessage>;
|
||||
|
||||
private outSubscription: Subscription;
|
||||
|
||||
constructor() {
|
||||
constructor(zone: NgZone) {
|
||||
this.messageOut$ = new Subject<SenderMessage>();
|
||||
this.connected$ = new BehaviorSubject(false);
|
||||
this.connect();
|
||||
|
||||
// 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('detach', (device: Device) => zone.run(() => this.onDeviceDetach(device)));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.disconnect();
|
||||
this.connected$.unsubscribe();
|
||||
}
|
||||
|
||||
connect(): void {
|
||||
if (this.connected) {
|
||||
if (this.connected$.getValue()) {
|
||||
return;
|
||||
}
|
||||
this.device = findByIds(vendorId, productId);
|
||||
if (!this.device) {
|
||||
throw new Error('UhkDevice not found.');
|
||||
return;
|
||||
}
|
||||
this.device.open();
|
||||
|
||||
@@ -103,18 +114,20 @@ export class UhkDeviceService {
|
||||
}).publish();
|
||||
this.outSubscription = outSending.connect();
|
||||
|
||||
this.connected = true;
|
||||
this.connected$.next(true);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if (!this.connected) {
|
||||
if (!this.connected$.getValue()) {
|
||||
return;
|
||||
}
|
||||
this.outSubscription.unsubscribe();
|
||||
this.messageIn$ = undefined;
|
||||
this.device.interface(0).release();
|
||||
this.device.close();
|
||||
this.connected = false;
|
||||
this.connected$.next(false);
|
||||
}
|
||||
|
||||
isConnected(): Observable<boolean> {
|
||||
return this.connected$.asObservable();
|
||||
}
|
||||
|
||||
sendConfig(configBuffer: Buffer): Observable<Buffer> {
|
||||
@@ -159,4 +172,22 @@ export class UhkDeviceService {
|
||||
});
|
||||
}
|
||||
|
||||
onDeviceAttach(device: Device) {
|
||||
if (device.deviceDescriptor.idVendor !== vendorId || device.deviceDescriptor.idProduct !== productId) {
|
||||
return;
|
||||
}
|
||||
if (!this.connected$.getValue()) {
|
||||
this.connect();
|
||||
}
|
||||
}
|
||||
|
||||
onDeviceDetach(device: Device) {
|
||||
if (device.deviceDescriptor.idVendor !== vendorId || device.deviceDescriptor.idProduct !== productId) {
|
||||
return;
|
||||
}
|
||||
if (this.connected$.getValue()) {
|
||||
this.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
main-app {
|
||||
display: block;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin-left: 250px;
|
||||
|
||||
@@ -30,3 +30,8 @@
|
||||
text-shadow: 0 0 5px #444;
|
||||
}
|
||||
}
|
||||
|
||||
main-app {
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user