Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(boot): added file association #1617

Merged
merged 5 commits into from
Jun 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion builder.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ module.exports = {
afterSign: 'scripts/notarize.js',
win: {
icon: 'electron/assets/lumi.png',
target: ['appx', 'nsis']
target: ['appx', 'nsis'],
fileAssociations: {
ext: 'h5p',
name: 'H5P'
}
},
appx: {
identityName: process.env.APPX_IDENTITY_NAME,
Expand All @@ -37,6 +41,9 @@ module.exports = {
displayName: process.env.APPX_DISPLAY_NAME,
publisherDisplayName: process.env.APPX_PUBLISHER_DISPLAY_NAME
},
nsis: {
deleteAppDataOnUninstall: true
},
linux: {
category: 'Utility',
target: ['AppImage', 'snap', 'deb', 'pacman']
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"build:mac:dev": "CSC_IDENTITY_AUTO_DISCOVERY=false npm run build:mac",
"build:sentry": "RELEASE=true npm run build:client",
"build:server": "npx tsc --project tsconfig.json",
"build:win": "npm run build && cp -r electron/assets/appx build && npx --no-install electron-builder --config builder.config.js --win --publish never && rm -rf build/appx",
"build:win": "npm run build && cp -r electron/assets/appx build && npx --no-install electron-builder --config builder.config.js --windows nsis --publish never && rm -rf build/appx",
"ci": "npm run lint && npm run format:check && npm run build && npm run test",
"clean": "rm -rf build/",
"format": "npx prettier --write \"{server,client,test}/**/*.{ts,tsx}\"",
Expand Down
64 changes: 64 additions & 0 deletions server/src/helpers/DelayedEmitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import SocketIO from 'socket.io';
import log from 'electron-log';

/**
* Wraps around SocketIO.Server and queues events until the websocket connection
* to the client is established. Events sent after the connection is established
* are sent directly without delay.
*/
export default class DelayedEmitter {
constructor(private websocketServer?: SocketIO.Server) {
log.debug(`DelayedEmitter: Initialized"`);
if (this.websocketServer) {
this.websocketServer.on('connection', this.onConnection);
}
}

private eventQueue: {
/**
* The arguments of the event.
*/
args: any[];
/**
* The name of the event.
*/
name: string;
}[] = [];
private isConnected: boolean = false;

/**
* Queues the event or emits it directly, depending on whether the websocket
* is already connected.
* @param name the name of the event
* @param args the custom arguments to pass alongside the event name
*/
public emit = (name: string, ...args: any[]): void => {
if (this.isConnected) {
log.debug(`DelayedEmitter: Immediately emitting event "${name}"`);
this.websocketServer.emit(name, ...args);
} else {
log.debug(`DelayedEmitter: Queueing event "${name}"`);
this.eventQueue.push({ name, args });
}
};

public setWebsocket = (websocket: SocketIO.Server): void => {
log.debug(`DelayedEmitter: Set websocket`);
this.websocketServer = websocket;
this.websocketServer.on('connection', this.onConnection);
};

private emitQueue = (): void => {
log.debug('DelayedEmitter: Emitting queued events');
for (const event of this.eventQueue) {
this.websocketServer.emit(event.name, ...event.args);
}
this.eventQueue = [];
};

private onConnection = () => {
log.debug('DelayedEmitter: Websocket connected');
this.isConnected = true;
this.emitQueue();
};
}
40 changes: 32 additions & 8 deletions server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ import i18next from 'i18next';

import settingsCache from './settingsCache';
import electronState from './electronState';
import DelayedEmitter from './helpers/DelayedEmitter';

const app = electron.app;
let websocket: SocketIO.Server;
/**
* The DelayedEmitter queues websocket events until the websocket is connected.
* We need it as the browser window and the client must be initialized before
* we can send events, but the events are raised by the startup routine before
* the initialization is over.
*/
const delayedWebsocketEmitter: DelayedEmitter = new DelayedEmitter();
let mainWindow: electron.BrowserWindow;
let port: number;
let currentPath: string = '/';
Expand Down Expand Up @@ -118,16 +126,13 @@ app.on('window-all-closed', () => {
}
});

app.on('open-file', (event, openedFilePath) => {
let filePath = openedFilePath;
if (process.argv.length >= 2) {
// or electron.remote.process.argv
filePath = process.argv[1];
}
// Handle open file events for MacOS
app.on('open-file', (event: electron.Event, openedFilePath: string) => {
log.debug('Electron open-file event caught');

websocket.emit('action', {
delayedWebsocketEmitter.emit('action', {
payload: {
paths: [filePath]
paths: [openedFilePath]
},
type: 'OPEN_H5P'
});
Expand Down Expand Up @@ -183,12 +188,31 @@ app.on('ready', async () => {
websocket = websocketFactory(server);
log.info('websocket created');

delayedWebsocketEmitter.setWebsocket(websocket);

updater(app, websocket, serverConfig);
log.info('updater started');

createMainWindow(websocket);
log.info('window created');

const argv = process.argv;
if (process.platform === 'win32' && argv.length >= 2) {
// Check if there are H5Ps specified in the command line args and
// load them (Windows only).
argv.splice(0, 1);
const openFilePaths = argv.filter((arg) => arg.endsWith('.h5p'));
if (openFilePaths.length > 0) {
log.debug(`Opening file(s): ${openFilePaths.join(' ')}`);
delayedWebsocketEmitter.emit('action', {
payload: {
paths: openFilePaths
},
type: 'OPEN_H5P'
});
}
}

try {
if (settingsCache.getSettings().usageStatistics) {
const data = {
Expand Down