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 { DragulaModule } from 'ng2-dragula/ng2-dragula';
|
||||||
import { Select2Module } from 'ng2-select2/ng2-select2';
|
import { Select2Module } from 'ng2-select2/ng2-select2';
|
||||||
|
|
||||||
|
import { MissingDeviceComponent } from './components/missing-device/missing-device.component';
|
||||||
import { AddOnComponent } from './shared/components/add-on';
|
import { AddOnComponent } from './shared/components/add-on';
|
||||||
import { KeyboardSliderComponent } from './shared/components/keyboard/slider';
|
import { KeyboardSliderComponent } from './shared/components/keyboard/slider';
|
||||||
import { KeymapAddComponent, KeymapHeaderComponent } from './shared/components/keymap';
|
import { KeymapAddComponent, KeymapHeaderComponent } from './shared/components/keymap';
|
||||||
@@ -59,7 +60,9 @@ import {
|
|||||||
} from './shared/components/svg/keys';
|
} from './shared/components/svg/keys';
|
||||||
import { SvgModuleComponent } from './shared/components/svg/module';
|
import { SvgModuleComponent } from './shared/components/svg/module';
|
||||||
import { SvgKeyboardWrapComponent } from './shared/components/svg/wrap';
|
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';
|
import { CancelableDirective } from './shared/directives';
|
||||||
|
|
||||||
@@ -74,6 +77,8 @@ 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';
|
||||||
|
|
||||||
// Create DataStorage dependency injection
|
// Create DataStorage dependency injection
|
||||||
const storageProvider = ReflectiveInjector.resolve([DataStorage]);
|
const storageProvider = ReflectiveInjector.resolve([DataStorage]);
|
||||||
const storageInjector = ReflectiveInjector.fromResolvedProviders(storageProvider);
|
const storageInjector = ReflectiveInjector.fromResolvedProviders(storageProvider);
|
||||||
@@ -87,6 +92,7 @@ const storeConfig = {
|
|||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
MainAppComponent,
|
MainAppComponent,
|
||||||
KeymapEditComponent,
|
KeymapEditComponent,
|
||||||
KeymapHeaderComponent,
|
KeymapHeaderComponent,
|
||||||
@@ -133,6 +139,7 @@ const storeConfig = {
|
|||||||
AddOnComponent,
|
AddOnComponent,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
KeyboardSliderComponent,
|
KeyboardSliderComponent,
|
||||||
|
MissingDeviceComponent,
|
||||||
CancelableDirective
|
CancelableDirective
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
@@ -153,6 +160,7 @@ const storeConfig = {
|
|||||||
EffectsModule.runAfterBootstrap(MacroEffects)
|
EffectsModule.runAfterBootstrap(MacroEffects)
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
UHkConnectedGuard,
|
||||||
MapperService,
|
MapperService,
|
||||||
appRoutingProviders,
|
appRoutingProviders,
|
||||||
KeymapEditGuard,
|
KeymapEditGuard,
|
||||||
@@ -160,6 +168,6 @@ const storeConfig = {
|
|||||||
CaptureService,
|
CaptureService,
|
||||||
UhkDeviceService
|
UhkDeviceService
|
||||||
],
|
],
|
||||||
bootstrap: [MainAppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
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 = [
|
export const keymapRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
redirectTo: '/keymap',
|
redirectTo: 'keymap',
|
||||||
pathMatch: 'full'
|
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>
|
</script>
|
||||||
<!-- End Google Tag Manager -->
|
<!-- End Google Tag Manager -->
|
||||||
|
|
||||||
<main-app></main-app>
|
<app></app>
|
||||||
|
|
||||||
<script src="app.uhk.js"></script> <!-- This should be moved to the head -->
|
<script src="app.uhk.js"></script> <!-- This should be moved to the head -->
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { Component, ViewEncapsulation, HostListener } from '@angular/core';
|
import { Component, ViewEncapsulation, HostListener } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { Store } from '@ngrx/store';
|
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 { AppState } from '../shared/store';
|
||||||
import { getUserConfiguration } from '../shared/store/reducers/user-configuration';
|
import { getUserConfiguration } from '../shared/store/reducers/user-configuration';
|
||||||
|
|
||||||
@@ -17,7 +22,17 @@ import { UhkDeviceService } from '../services/uhk-device.service';
|
|||||||
})
|
})
|
||||||
export class MainAppComponent {
|
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'])
|
@HostListener('window:keydown.control.o', ['$event'])
|
||||||
onCtrlO(event: KeyboardEvent): void {
|
onCtrlO(event: KeyboardEvent): void {
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
import { ModuleWithProviders } from '@angular/core';
|
import { Routes } from '@angular/router';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
|
||||||
|
|
||||||
import { addOnRoutes } from '../shared/components/add-on';
|
import { addOnRoutes } from '../shared/components/add-on';
|
||||||
import { keymapRoutes } from '../components/keymap';
|
import { keymapRoutes } from '../components/keymap';
|
||||||
import { macroRoutes } from '../shared/components/macro';
|
import { macroRoutes } from '../shared/components/macro';
|
||||||
import { settingsRoutes } from '../shared/components/settings';
|
import { settingsRoutes } from '../shared/components/settings';
|
||||||
|
|
||||||
const appRoutes: Routes = [
|
export const mainAppRoutes: Routes = [
|
||||||
...keymapRoutes,
|
...keymapRoutes,
|
||||||
...macroRoutes,
|
...macroRoutes,
|
||||||
...addOnRoutes,
|
...addOnRoutes,
|
||||||
...settingsRoutes
|
...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 { Observable } from 'rxjs/Observable';
|
||||||
|
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
import { Observer } from 'rxjs/Observer';
|
import { Observer } from 'rxjs/Observer';
|
||||||
import { ConnectableObservable } from 'rxjs/observable/ConnectableObservable';
|
import { ConnectableObservable } from 'rxjs/observable/ConnectableObservable';
|
||||||
import { Subject } from 'rxjs/Subject';
|
import { Subject } from 'rxjs/Subject';
|
||||||
@@ -14,7 +15,7 @@ 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 { 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 { Layer } from '../shared/config-serializer/config-items/Layer';
|
||||||
import { UhkBuffer } from '../shared/config-serializer/UhkBuffer';
|
import { UhkBuffer } from '../shared/config-serializer/UhkBuffer';
|
||||||
@@ -34,28 +35,38 @@ interface SenderMessage {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UhkDeviceService {
|
export class UhkDeviceService implements OnDestroy {
|
||||||
|
|
||||||
private device: Device;
|
private device: Device;
|
||||||
private connected: boolean;
|
private connected$: BehaviorSubject<boolean>;
|
||||||
|
|
||||||
private messageIn$: Observable<Buffer>;
|
private messageIn$: Observable<Buffer>;
|
||||||
private messageOut$: Subject<SenderMessage>;
|
private messageOut$: Subject<SenderMessage>;
|
||||||
|
|
||||||
private outSubscription: Subscription;
|
private outSubscription: Subscription;
|
||||||
|
|
||||||
constructor() {
|
constructor(zone: NgZone) {
|
||||||
this.messageOut$ = new Subject<SenderMessage>();
|
this.messageOut$ = new Subject<SenderMessage>();
|
||||||
|
this.connected$ = new BehaviorSubject(false);
|
||||||
this.connect();
|
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 {
|
connect(): void {
|
||||||
if (this.connected) {
|
if (this.connected$.getValue()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.device = findByIds(vendorId, productId);
|
this.device = findByIds(vendorId, productId);
|
||||||
if (!this.device) {
|
if (!this.device) {
|
||||||
throw new Error('UhkDevice not found.');
|
return;
|
||||||
}
|
}
|
||||||
this.device.open();
|
this.device.open();
|
||||||
|
|
||||||
@@ -103,18 +114,20 @@ export class UhkDeviceService {
|
|||||||
}).publish();
|
}).publish();
|
||||||
this.outSubscription = outSending.connect();
|
this.outSubscription = outSending.connect();
|
||||||
|
|
||||||
this.connected = true;
|
this.connected$.next(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
if (!this.connected) {
|
if (!this.connected$.getValue()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.outSubscription.unsubscribe();
|
this.outSubscription.unsubscribe();
|
||||||
this.messageIn$ = undefined;
|
this.messageIn$ = undefined;
|
||||||
this.device.interface(0).release();
|
this.connected$.next(false);
|
||||||
this.device.close();
|
}
|
||||||
this.connected = false;
|
|
||||||
|
isConnected(): Observable<boolean> {
|
||||||
|
return this.connected$.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
sendConfig(configBuffer: Buffer): Observable<Buffer> {
|
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,13 +1,11 @@
|
|||||||
main-app {
|
main-app {
|
||||||
display: block;
|
display: block;
|
||||||
min-height: 100vh;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
|
|||||||
@@ -30,3 +30,8 @@
|
|||||||
text-shadow: 0 0 5px #444;
|
text-shadow: 0 0 5px #444;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main-app {
|
||||||
|
min-height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user