Skip to content

Commit 8f1c6c4

Browse files
committed
trying to fix some bugs
1 parent 1044589 commit 8f1c6c4

File tree

6 files changed

+174
-86
lines changed

6 files changed

+174
-86
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ node_modules
22
dist
33
dist_electron
44
.idea
5-
.DS_Store
5+
.DS_Store
6+
*.log

src/ConfigEngine.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import * as storage from 'electron-json-storage';
2+
import { BaseObserver } from './BaseObserver';
3+
import { Logger } from 'winston';
24

35
export interface Config {
46
devices: {
@@ -7,16 +9,28 @@ export interface Config {
79
};
810
};
911
startupDelay: number;
12+
logFile: boolean;
1013
}
1114

12-
export class ConfigEngine {
15+
export interface ConfigEngineListener {
16+
configChanged: (changedConfig: Partial<Config>) => any;
17+
}
18+
19+
export interface ConfigEngineOptions {
20+
logger: Logger;
21+
}
22+
23+
export class ConfigEngine extends BaseObserver<ConfigEngineListener> {
1324
static VERSION = 2;
1425
static KEY = 'dynamouse';
1526

1627
config: Config;
28+
protected logger: Logger;
1729

18-
constructor() {
19-
this.config = { devices: {}, startupDelay: 0 };
30+
constructor(protected options: ConfigEngineOptions) {
31+
super();
32+
this.logger = options.logger.child({ namespace: 'CONFIG' });
33+
this.config = { devices: {}, startupDelay: 0, logFile: false };
2034
}
2135

2236
init() {
@@ -30,15 +44,21 @@ export class ConfigEngine {
3044
return `${ConfigEngine.KEY}-${ConfigEngine.VERSION}`;
3145
}
3246

33-
update(config: Partial<Config>) {
47+
async update(config: Partial<Config>) {
3448
this.config = {
3549
...this.config,
3650
...config
3751
};
38-
storage.set(this.saveKey, this.config, (err) => {
39-
if (err) {
40-
console.error('failed to store settings', err);
41-
}
52+
await new Promise<void>((resolve, reject) => {
53+
storage.set(this.saveKey, this.config, (err) => {
54+
if (err) {
55+
this.logger.error('failed to store settings', err);
56+
return reject(err);
57+
}
58+
resolve();
59+
});
4260
});
61+
this.logger.debug(`Config updated`, this.config);
62+
this.iterateListeners((cb) => cb.configChanged?.(config));
4363
}
4464
}

src/PointerEngine.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ export class PointerDevice extends BaseObserver<PointerDeviceListener> {
3131
const data_cb = () => {
3232
this.iterateListeners((cb) => cb.moved?.());
3333
};
34-
const error_cb = () => {
34+
const error_cb = (err) => {
35+
this.logger.error(err);
3536
// do nothing for now
3637
};
3738
this.resource.on('error', error_cb);
@@ -104,10 +105,8 @@ export class PointerEngine extends BaseObserver<PointerEngineListener> {
104105

105106
refreshDeviceList() {
106107
this.logger.info('Refreshing device list');
107-
let pointerDevices = _.chain(devices())
108-
.filter((d) => d.usage === 2)
109-
.uniqBy((u) => u.serialNumber)
110-
.value();
108+
let pointerDevices = _.filter(devices(), (d) => d.usage === 2 && d.usagePage === 1);
109+
let unique = _.uniqBy(pointerDevices, (u) => u.serialNumber);
111110

112111
const snMapper = (a: PointerDevice | Device) => {
113112
if (a instanceof PointerDevice) {
@@ -117,12 +116,12 @@ export class PointerEngine extends BaseObserver<PointerEngineListener> {
117116
};
118117

119118
// devices to remove
120-
_.differenceBy(this.getDevices(), pointerDevices, snMapper).forEach((d) => {
119+
_.differenceBy(this.getDevices(), unique, snMapper).forEach((d) => {
121120
d.detach();
122121
});
123122

124123
// devices to add
125-
_.differenceBy(pointerDevices, this.getDevices(), snMapper).forEach((d) => {
124+
_.differenceBy(unique, this.getDevices(), snMapper).forEach((d) => {
126125
const device = new PointerDevice({
127126
device: d,
128127
logger: this.logger
@@ -141,12 +140,12 @@ export class PointerEngine extends BaseObserver<PointerEngineListener> {
141140

142141
init() {
143142
usb.on('attach', () => {
144-
this.logger.info('Device attached');
143+
this.logger.debug('Device attached');
145144
this.refreshDeviceList();
146145
});
147146

148147
usb.on('detach', () => {
149-
this.logger.info('Device detached');
148+
this.logger.debug('Device detached');
150149
this.refreshDeviceList();
151150
});
152151
this.refreshDeviceList();

src/RobotEngine.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { DisplayEngine } from './DisplayEngine';
55
import { BaseObserver } from './BaseObserver';
66
import { screen } from 'electron';
77
import { moveMouse } from '@jitsi/robotjs';
8+
import { Logger } from 'winston';
89

910
export interface AssignmentListener {
1011
willActivate: () => any;
@@ -98,18 +99,23 @@ export class Assignment extends BaseObserver<AssignmentListener> {
9899
export interface RobotEngineOptions {
99100
pointerEngine: PointerEngine;
100101
displayEngine: DisplayEngine;
102+
logger: Logger;
101103
}
102104

103105
export class RobotEngine {
104106
assignments: Assignment[];
105107
lock: boolean;
106108

109+
protected logger: Logger;
110+
107111
constructor(protected options: RobotEngineOptions) {
108112
this.assignments = [];
109113
this.lock = false;
114+
this.logger = options.logger.child({ namespace: 'ROBOT' });
110115
}
111116

112117
async setupAssignments(config: Config) {
118+
this.logger.debug('Re-initializing');
113119
await Promise.all(this.assignments.map((a) => a.dispose()));
114120
this.assignments = [];
115121
for (let key in config.devices) {
@@ -127,6 +133,7 @@ export class RobotEngine {
127133
if (this.lock) {
128134
return;
129135
}
136+
this.logger.debug(`Activating: ${device.product}`);
130137
this.lock = true;
131138
const activated = this.assignments.find((a) => a.activated);
132139
await activated?.deactivate();

src/main.ts

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { app, nativeImage, Tray } from 'electron';
22
import * as path from 'path';
33
import { DisplayEngine } from './DisplayEngine';
4-
import { PointerDevice, PointerEngine } from './PointerEngine';
4+
import { PointerEngine } from './PointerEngine';
55
import { ConfigEngine } from './ConfigEngine';
66
import { RobotEngine } from './RobotEngine';
77
import AutoLaunch from 'auto-launch';
88
import { createLogger, transports } from 'winston';
99
import { buildLoadingMenu, buildMenu } from './menu';
1010
import { waitForAllPermissions } from './permissions';
11-
import {} from 'async';
1211

1312
require('source-map-support').install();
1413

@@ -19,12 +18,14 @@ const autolauncher = new AutoLaunch({
1918
const icon_mac = nativeImage.createFromPath(path.join(__dirname, '../media/icon-mac.png'));
2019

2120
const logger = createLogger();
22-
logger.add(new transports.Console());
21+
22+
logger.add(new transports.Console({ level: 'debug' }));
2323

2424
const displayEngine = new DisplayEngine();
25-
const pointerEngine = new PointerEngine({ logger: logger });
26-
const configEngine = new ConfigEngine();
25+
const pointerEngine = new PointerEngine({ logger });
26+
const configEngine = new ConfigEngine({ logger });
2727
const robotEngine = new RobotEngine({
28+
logger,
2829
displayEngine,
2930
pointerEngine
3031
});
@@ -48,42 +49,43 @@ app.on('ready', async () => {
4849
return robotEngine.setupAssignments(configEngine.config);
4950
};
5051

52+
const dispose = async () => {
53+
logger.debug('Disposing app');
54+
await pointerEngine.dispose();
55+
};
56+
5157
const buildMenuWrapped = () => {
5258
buildMenu({
5359
tray,
54-
assignDisplayToDevice,
60+
quit: async () => {
61+
await dispose();
62+
app.exit(0);
63+
},
5564
displayEngine,
5665
pointerEngine,
5766
configEngine,
58-
autolauncher
59-
});
60-
};
61-
62-
const assignDisplayToDevice = (display_id: string, device: PointerDevice) => {
63-
configEngine.update({
64-
devices: {
65-
...configEngine.config.devices,
66-
[device.product]: { display: display_id }
67+
autolauncher,
68+
rebuildMenu: () => {
69+
buildMenuWrapped();
6770
}
6871
});
69-
buildMenuWrapped();
70-
setupMovement();
7172
};
7273

73-
configEngine.init();
74-
75-
// add a startup delay
76-
const delay = (configEngine.config.startupDelay || 0) * 1_000;
77-
78-
if (delay > 0) {
79-
buildLoadingMenu({ tray, message: `...waiting ${delay}ms (startup delay)` });
80-
}
81-
82-
// might want startup delay
83-
setTimeout(() => {
74+
const init = () => {
8475
pointerEngine.init();
8576
displayEngine.init();
8677

78+
configEngine.registerListener({
79+
configChanged: ({ devices }) => {
80+
buildMenuWrapped();
81+
82+
// if devices changed, then also setupMovementAgain
83+
if (devices) {
84+
setupMovement();
85+
}
86+
}
87+
});
88+
8789
pointerEngine.registerListener({
8890
devicesChanged: () => {
8991
buildMenuWrapped();
@@ -93,5 +95,22 @@ app.on('ready', async () => {
9395

9496
buildMenuWrapped();
9597
setupMovement();
96-
}, delay);
98+
};
99+
100+
configEngine.init();
101+
102+
// useful for debugging
103+
if (configEngine.config.logFile) {
104+
logger.add(new transports.File({ filename: 'combined.log', level: 'debug' }));
105+
}
106+
107+
// add a startup delay
108+
const delay = (configEngine.config.startupDelay || 0) * 1_000;
109+
if (delay > 0) {
110+
buildLoadingMenu({ tray, message: `...waiting ${delay}ms (startup delay)` });
111+
setTimeout(init, delay);
112+
} else {
113+
// doing this outside of a setTimeout may help with node event loops for some cases :shrug:
114+
init();
115+
}
97116
});

0 commit comments

Comments
 (0)