Skip to content

Commit

Permalink
Merge pull request #5 from projectstorm/try_fix_bugs
Browse files Browse the repository at this point in the history
Trying to fix some bugs
  • Loading branch information
dylanvorster authored Mar 3, 2024
2 parents 1044589 + 4f27728 commit 7869caa
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 86 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ node_modules
dist
dist_electron
.idea
.DS_Store
.DS_Store
*.log
36 changes: 28 additions & 8 deletions src/ConfigEngine.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as storage from 'electron-json-storage';
import { BaseObserver } from './BaseObserver';
import { Logger } from 'winston';

export interface Config {
devices: {
Expand All @@ -7,16 +9,28 @@ export interface Config {
};
};
startupDelay: number;
logFile: boolean;
}

export class ConfigEngine {
export interface ConfigEngineListener {
configChanged: (changedConfig: Partial<Config>) => any;
}

export interface ConfigEngineOptions {
logger: Logger;
}

export class ConfigEngine extends BaseObserver<ConfigEngineListener> {
static VERSION = 2;
static KEY = 'dynamouse';

config: Config;
protected logger: Logger;

constructor() {
this.config = { devices: {}, startupDelay: 0 };
constructor(protected options: ConfigEngineOptions) {
super();
this.logger = options.logger.child({ namespace: 'CONFIG' });
this.config = { devices: {}, startupDelay: 0, logFile: false };
}

init() {
Expand All @@ -30,15 +44,21 @@ export class ConfigEngine {
return `${ConfigEngine.KEY}-${ConfigEngine.VERSION}`;
}

update(config: Partial<Config>) {
async update(config: Partial<Config>) {
this.config = {
...this.config,
...config
};
storage.set(this.saveKey, this.config, (err) => {
if (err) {
console.error('failed to store settings', err);
}
await new Promise<void>((resolve, reject) => {
storage.set(this.saveKey, this.config, (err) => {
if (err) {
this.logger.error('failed to store settings', err);
return reject(err);
}
resolve();
});
});
this.logger.debug(`Config updated`, this.config);
this.iterateListeners((cb) => cb.configChanged?.(config));
}
}
17 changes: 8 additions & 9 deletions src/PointerEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export class PointerDevice extends BaseObserver<PointerDeviceListener> {
const data_cb = () => {
this.iterateListeners((cb) => cb.moved?.());
};
const error_cb = () => {
const error_cb = (err) => {
this.logger.error(err);
// do nothing for now
};
this.resource.on('error', error_cb);
Expand Down Expand Up @@ -104,10 +105,8 @@ export class PointerEngine extends BaseObserver<PointerEngineListener> {

refreshDeviceList() {
this.logger.info('Refreshing device list');
let pointerDevices = _.chain(devices())
.filter((d) => d.usage === 2)
.uniqBy((u) => u.serialNumber)
.value();
let pointerDevices = _.filter(devices(), (d) => d.usage === 2 && d.usagePage === 1);
let unique = _.uniqBy(pointerDevices, (u) => u.serialNumber);

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

// devices to remove
_.differenceBy(this.getDevices(), pointerDevices, snMapper).forEach((d) => {
_.differenceBy(this.getDevices(), unique, snMapper).forEach((d) => {
d.detach();
});

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

init() {
usb.on('attach', () => {
this.logger.info('Device attached');
this.logger.debug('Device attached');
this.refreshDeviceList();
});

usb.on('detach', () => {
this.logger.info('Device detached');
this.logger.debug('Device detached');
this.refreshDeviceList();
});
this.refreshDeviceList();
Expand Down
7 changes: 7 additions & 0 deletions src/RobotEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { DisplayEngine } from './DisplayEngine';
import { BaseObserver } from './BaseObserver';
import { screen } from 'electron';
import { moveMouse } from '@jitsi/robotjs';
import { Logger } from 'winston';

export interface AssignmentListener {
willActivate: () => any;
Expand Down Expand Up @@ -98,18 +99,23 @@ export class Assignment extends BaseObserver<AssignmentListener> {
export interface RobotEngineOptions {
pointerEngine: PointerEngine;
displayEngine: DisplayEngine;
logger: Logger;
}

export class RobotEngine {
assignments: Assignment[];
lock: boolean;

protected logger: Logger;

constructor(protected options: RobotEngineOptions) {
this.assignments = [];
this.lock = false;
this.logger = options.logger.child({ namespace: 'ROBOT' });
}

async setupAssignments(config: Config) {
this.logger.debug('Re-initializing');
await Promise.all(this.assignments.map((a) => a.dispose()));
this.assignments = [];
for (let key in config.devices) {
Expand All @@ -127,6 +133,7 @@ export class RobotEngine {
if (this.lock) {
return;
}
this.logger.debug(`Activating: ${device.product}`);
this.lock = true;
const activated = this.assignments.find((a) => a.activated);
await activated?.deactivate();
Expand Down
77 changes: 48 additions & 29 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { app, nativeImage, Tray } from 'electron';
import * as path from 'path';
import { DisplayEngine } from './DisplayEngine';
import { PointerDevice, PointerEngine } from './PointerEngine';
import { PointerEngine } from './PointerEngine';
import { ConfigEngine } from './ConfigEngine';
import { RobotEngine } from './RobotEngine';
import AutoLaunch from 'auto-launch';
import { createLogger, transports } from 'winston';
import { buildLoadingMenu, buildMenu } from './menu';
import { waitForAllPermissions } from './permissions';
import {} from 'async';

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

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

const logger = createLogger();
logger.add(new transports.Console());

logger.add(new transports.Console({ level: 'debug' }));

const displayEngine = new DisplayEngine();
const pointerEngine = new PointerEngine({ logger: logger });
const configEngine = new ConfigEngine();
const pointerEngine = new PointerEngine({ logger });
const configEngine = new ConfigEngine({ logger });
const robotEngine = new RobotEngine({
logger,
displayEngine,
pointerEngine
});
Expand All @@ -48,42 +49,43 @@ app.on('ready', async () => {
return robotEngine.setupAssignments(configEngine.config);
};

const dispose = async () => {
logger.debug('Disposing app');
await pointerEngine.dispose();
};

const buildMenuWrapped = () => {
buildMenu({
tray,
assignDisplayToDevice,
quit: async () => {
await dispose();
app.exit(0);
},
displayEngine,
pointerEngine,
configEngine,
autolauncher
});
};

const assignDisplayToDevice = (display_id: string, device: PointerDevice) => {
configEngine.update({
devices: {
...configEngine.config.devices,
[device.product]: { display: display_id }
autolauncher,
rebuildMenu: () => {
buildMenuWrapped();
}
});
buildMenuWrapped();
setupMovement();
};

configEngine.init();

// add a startup delay
const delay = (configEngine.config.startupDelay || 0) * 1_000;

if (delay > 0) {
buildLoadingMenu({ tray, message: `...waiting ${delay}ms (startup delay)` });
}

// might want startup delay
setTimeout(() => {
const init = () => {
pointerEngine.init();
displayEngine.init();

configEngine.registerListener({
configChanged: ({ devices }) => {
buildMenuWrapped();

// if devices changed, then also setupMovementAgain
if (devices) {
setupMovement();
}
}
});

pointerEngine.registerListener({
devicesChanged: () => {
buildMenuWrapped();
Expand All @@ -93,5 +95,22 @@ app.on('ready', async () => {

buildMenuWrapped();
setupMovement();
}, delay);
};

configEngine.init();

// useful for debugging
if (configEngine.config.logFile) {
logger.add(new transports.File({ filename: 'combined.log', dirname: app.getPath('logs'), level: 'debug' }));
}

// add a startup delay
const delay = (configEngine.config.startupDelay || 0) * 1_000;
if (delay > 0) {
buildLoadingMenu({ tray, message: `...waiting ${delay}ms (startup delay)` });
setTimeout(init, delay);
} else {
// doing this outside of a setTimeout may help with node event loops for some cases :shrug:
init();
}
});
Loading

0 comments on commit 7869caa

Please sign in to comment.