Skip to content

Commit

Permalink
fix(boot): file associations always work (#1624)
Browse files Browse the repository at this point in the history
* fix(boot): files load after consent

* fix(legal): consent dialog changes not immediately saved

* fix(boot): file association open always opens new window in macOS
  • Loading branch information
sr258 authored Jun 17, 2021
1 parent 510e5eb commit e66c2a4
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 21 deletions.
17 changes: 15 additions & 2 deletions client/src/state/Settings/SettingsActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,28 @@ export function updateSettings(settings: ISettingsState): any {
};
}

export function changeSetting(payload: Partial<ISettingsState>): any {
/**
*
* @param payload
* @param save If true, the setting change will also be persisted, if false the
* change will only be performed in the Redux state, but not persisted to the
* disk.
* @returns
*/
export function changeSetting(
payload: Partial<ISettingsState>,
save: boolean = false
): any {
return async (dispatch: any) => {
try {
dispatch({
payload,
type: SETTINGS_CHANGE
});

dispatch(updateSettings(store.getState().settings));
if (save) {
dispatch(updateSettings(store.getState().settings));
}
} catch (error) {
Sentry.captureException(error);
}
Expand Down
43 changes: 28 additions & 15 deletions client/src/views/components/SetupDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,13 @@ export default function CustomizedDialogs() {
edge="end"
onChange={() =>
dispatch(
actions.settings.changeSetting({
privacyPolicyConsent:
!settings.privacyPolicyConsent
})
actions.settings.changeSetting(
{
privacyPolicyConsent:
!settings.privacyPolicyConsent
},
false
)
)
}
checked={settings.privacyPolicyConsent}
Expand All @@ -175,9 +178,13 @@ export default function CustomizedDialogs() {
edge="end"
onChange={() =>
dispatch(
actions.settings.changeSetting({
bugTracking: !settings.bugTracking
})
actions.settings.changeSetting(
{
bugTracking:
!settings.bugTracking
},
false
)
)
}
checked={settings.bugTracking}
Expand All @@ -202,10 +209,13 @@ export default function CustomizedDialogs() {
edge="end"
onChange={() =>
dispatch(
actions.settings.changeSetting({
usageStatistics:
!settings.usageStatistics
})
actions.settings.changeSetting(
{
usageStatistics:
!settings.usageStatistics
},
false
)
)
}
checked={settings.usageStatistics}
Expand All @@ -231,10 +241,13 @@ export default function CustomizedDialogs() {
edge="end"
onChange={() =>
dispatch(
actions.settings.changeSetting({
autoUpdates:
!settings.autoUpdates
})
actions.settings.changeSetting(
{
autoUpdates:
!settings.autoUpdates
},
false
)
)
}
checked={settings.autoUpdates}
Expand Down
44 changes: 42 additions & 2 deletions server/src/helpers/DelayedEmitter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import SocketIO from 'socket.io';
import log from 'electron-log';

import settingsCache from '../settingsCache';

/**
* Wraps around SocketIO.Server and queues events until the websocket connection
* to the client is established. Events sent after the connection is established
Expand All @@ -12,6 +14,11 @@ export default class DelayedEmitter {
if (this.websocketServer) {
this.websocketServer.on('connection', this.onConnection);
}
if (settingsCache.getSettings().privacyPolicyConsent) {
this.hasConsented = true;
} else {
settingsCache.subscribe(this.onSettingsChanged);
}
}

private eventQueue: {
Expand All @@ -24,6 +31,15 @@ export default class DelayedEmitter {
*/
name: string;
}[] = [];

/**
* Keeps track if the user has consented to the privacy policy.
*/
private hasConsented: boolean = false;

/**
* Keeps track if the Websocket is connected to the client.
*/
private isConnected: boolean = false;

/**
Expand All @@ -33,7 +49,7 @@ export default class DelayedEmitter {
* @param args the custom arguments to pass alongside the event name
*/
public emit = (name: string, ...args: any[]): void => {
if (this.isConnected) {
if (this.isConnected && this.hasConsented) {
log.debug(`DelayedEmitter: Immediately emitting event "${name}"`);
this.websocketServer.emit(name, ...args);
} else {
Expand All @@ -42,6 +58,17 @@ export default class DelayedEmitter {
}
};

/**
* Sets the connection state to false again and listens for a new connection.
*/
public resetWebsocketConnection = () => {
log.debug(
`DelayedEmitter: Resetting websocket connected state and waiting for new connection event`
);
this.isConnected = false;
this.websocketServer.on('connection', this.onConnection);
};

public setWebsocket = (websocket: SocketIO.Server): void => {
log.debug(`DelayedEmitter: Set websocket`);
this.websocketServer = websocket;
Expand All @@ -59,6 +86,19 @@ export default class DelayedEmitter {
private onConnection = () => {
log.debug('DelayedEmitter: Websocket connected');
this.isConnected = true;
this.emitQueue();
if (this.hasConsented) {
this.emitQueue();
}
};

private onSettingsChanged = (): void => {
if (settingsCache.getSettings().privacyPolicyConsent) {
log.debug('DelayedEmitter: User has consented to privacy policy');
this.hasConsented = true;
settingsCache.unsubscribe(this.onSettingsChanged);
if (this.isConnected) {
this.emitQueue();
}
}
};
}
13 changes: 11 additions & 2 deletions server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ export function createMainWindow(websocketArg: SocketIO.Server): void {

window.on('closed', () => {
mainWindow = null;
// If a new main window is recreated later (macOS), we need to
// listen to the websocket's connection event again.
delayedWebsocketEmitter.resetWebsocketConnection();
});

window.webContents.on('devtools-opened', () => {
Expand All @@ -113,8 +116,6 @@ export function createMainWindow(websocketArg: SocketIO.Server): void {
});

mainWindow = window;

// return window;
}
}

Expand All @@ -130,6 +131,14 @@ app.on('window-all-closed', () => {
app.on('open-file', (event: electron.Event, openedFilePath: string) => {
log.debug('Electron open-file event caught');

/**
* If we are in macOS and the process is still active but there is no
* window, we need to create one.
*/
if (mainWindow === null) {
createMainWindow(websocket);
}

delayedWebsocketEmitter.emit('action', {
payload: {
paths: [openedFilePath]
Expand Down
14 changes: 14 additions & 0 deletions server/src/settingsCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,26 @@ class SettingsStorage {
}
public settings: ISettingsState;

private subscribers: (() => void)[] = [];

getSettings(): ISettingsState {
return this.settings;
}

setSettings(s: ISettingsState): void {
this.settings = s;
this.subscribers.forEach((subscriber) => subscriber());
}

subscribe(handler: () => void): void {
this.subscribers.push(handler);
}

unsubscribe(handler: () => void): void {
const index = this.subscribers.indexOf(handler);
if (index >= 0) {
this.subscribers.splice(index, 1);
}
}
}

Expand Down

0 comments on commit e66c2a4

Please sign in to comment.