aboutsummaryrefslogtreecommitdiffstats
path: root/src/electron/ipc-api
diff options
context:
space:
mode:
Diffstat (limited to 'src/electron/ipc-api')
-rw-r--r--src/electron/ipc-api/appIndicator.ts (renamed from src/electron/ipc-api/appIndicator.js)44
-rw-r--r--src/electron/ipc-api/autoUpdate.ts (renamed from src/electron/ipc-api/autoUpdate.js)26
-rw-r--r--src/electron/ipc-api/cld.ts (renamed from src/electron/ipc-api/cld.js)11
-rw-r--r--src/electron/ipc-api/dnd.ts (renamed from src/electron/ipc-api/dnd.js)4
-rw-r--r--src/electron/ipc-api/download.js51
-rw-r--r--src/electron/ipc-api/download.ts59
-rw-r--r--src/electron/ipc-api/focusState.ts (renamed from src/electron/ipc-api/focusState.js)4
-rw-r--r--src/electron/ipc-api/index.ts (renamed from src/electron/ipc-api/index.js)11
-rw-r--r--src/electron/ipc-api/localServer.ts (renamed from src/electron/ipc-api/localServer.js)17
-rw-r--r--src/electron/ipc-api/sessionStorage.ts35
-rw-r--r--src/electron/ipc-api/settings.js14
-rw-r--r--src/electron/ipc-api/settings.ts14
12 files changed, 175 insertions, 115 deletions
diff --git a/src/electron/ipc-api/appIndicator.js b/src/electron/ipc-api/appIndicator.ts
index c6c261d0f..a51ed8161 100644
--- a/src/electron/ipc-api/appIndicator.js
+++ b/src/electron/ipc-api/appIndicator.ts
@@ -6,15 +6,22 @@ import { isMac, isWindows, isLinux } from '../../environment';
6const INDICATOR_TASKBAR = 'taskbar'; 6const INDICATOR_TASKBAR = 'taskbar';
7const FILE_EXTENSION = isWindows ? 'ico' : 'png'; 7const FILE_EXTENSION = isWindows ? 'ico' : 'png';
8 8
9let isTrayIconEnabled; 9let isTrayIconEnabled: boolean;
10 10
11function getAsset(type, asset) { 11function getAsset(type: 'tray' | 'taskbar', asset: string) {
12 return join( 12 return join(
13 __dirname, '..', '..', 'assets', 'images', type, process.platform, `${asset}.${FILE_EXTENSION}`, 13 __dirname,
14 '..',
15 '..',
16 'assets',
17 'images',
18 type,
19 process.platform,
20 `${asset}.${FILE_EXTENSION}`,
14 ); 21 );
15} 22}
16 23
17export default (params) => { 24export default params => {
18 autorun(() => { 25 autorun(() => {
19 isTrayIconEnabled = params.settings.app.get('enableSystemTray'); 26 isTrayIconEnabled = params.settings.app.get('enableSystemTray');
20 27
@@ -25,36 +32,37 @@ export default (params) => {
25 } 32 }
26 }); 33 });
27 34
28 ipcMain.on('updateAppIndicator', (event, args) => { 35 ipcMain.on('updateAppIndicator', (_event, args) => {
29 // Flash TaskBar for windows, bounce Dock on Mac 36 // Flash TaskBar for windows, bounce Dock on Mac
30 if (!app.mainWindow.isFocused()) { 37 if (!(app as any).mainWindow.isFocused() && params.settings.app.get('notifyTaskBarOnMessage')) {
31 if (params.settings.app.get('notifyTaskBarOnMessage')) {
32 if (isWindows) { 38 if (isWindows) {
33 app.mainWindow.flashFrame(true); 39 (app as any).mainWindow.flashFrame(true);
34 app.mainWindow.once('focus', () => app.mainWindow.flashFrame(false)); 40 (app as any).mainWindow.once('focus', () =>
41 (app as any).mainWindow.flashFrame(false),
42 );
35 } else if (isMac) { 43 } else if (isMac) {
36 app.dock.bounce('informational'); 44 app.dock.bounce('informational');
37 } 45 }
38 } 46 }
39 }
40 47
41 // Update badge 48 // Update badge
42 if (isMac 49 if (isMac && typeof args.indicator === 'string') {
43 && typeof (args.indicator) === 'string') {
44 app.dock.setBadge(args.indicator); 50 app.dock.setBadge(args.indicator);
45 } 51 }
46 52
47 if ((isMac || isLinux) 53 if ((isMac || isLinux) && typeof args.indicator === 'number') {
48 && typeof (args.indicator) === 'number'
49 ) {
50 app.badgeCount = args.indicator; 54 app.badgeCount = args.indicator;
51 } 55 }
52 56
53 if (isWindows) { 57 if (isWindows) {
54 if (typeof args.indicator === 'number' 58 if (typeof args.indicator === 'number' && args.indicator !== 0) {
55 && args.indicator !== 0) {
56 params.mainWindow.setOverlayIcon( 59 params.mainWindow.setOverlayIcon(
57 getAsset('taskbar', `${INDICATOR_TASKBAR}-${(args.indicator >= 10 ? 10 : args.indicator)}`), 60 getAsset(
61 'taskbar',
62 `${INDICATOR_TASKBAR}-${
63 args.indicator >= 10 ? 10 : args.indicator
64 }`,
65 ),
58 '', 66 '',
59 ); 67 );
60 } else if (typeof args.indicator === 'string') { 68 } else if (typeof args.indicator === 'string') {
diff --git a/src/electron/ipc-api/autoUpdate.js b/src/electron/ipc-api/autoUpdate.ts
index 255595b9e..e6b805edc 100644
--- a/src/electron/ipc-api/autoUpdate.js
+++ b/src/electron/ipc-api/autoUpdate.ts
@@ -1,11 +1,10 @@
1import { app, ipcMain } from 'electron'; 1import { app, ipcMain, BrowserWindow } from 'electron';
2import { autoUpdater } from 'electron-updater'; 2import { autoUpdater } from 'electron-updater';
3import { GITHUB_NIGHTLIES_REPO_NAME, GITHUB_ORG_NAME } from '../../config';
4import { isMac, isWindows } from '../../environment'; 3import { isMac, isWindows } from '../../environment';
5 4
6const debug = require('debug')('Ferdi:ipcApi:autoUpdate'); 5const debug = require('debug')('Ferdi:ipcApi:autoUpdate');
7 6
8export default (params) => { 7export default (params: { mainWindow: BrowserWindow; settings: any }) => {
9 const enableUpdate = Boolean(params.settings.app.get('automaticUpdates')); 8 const enableUpdate = Boolean(params.settings.app.get('automaticUpdates'));
10 9
11 if (!enableUpdate) { 10 if (!enableUpdate) {
@@ -16,17 +15,16 @@ export default (params) => {
16 if (enableUpdate) { 15 if (enableUpdate) {
17 try { 16 try {
18 autoUpdater.autoInstallOnAppQuit = false; 17 autoUpdater.autoInstallOnAppQuit = false;
19 autoUpdater.allowPrerelease = Boolean(params.settings.app.get('beta')); 18 autoUpdater.allowPrerelease = Boolean(
19 params.settings.app.get('beta'),
20 );
20 autoUpdater.channel = autoUpdater.allowPrerelease ? 'beta' : 'latest'; 21 autoUpdater.channel = autoUpdater.allowPrerelease ? 'beta' : 'latest';
21 22
22 if (params.settings.app.get('nightly')) { 23 if (params.settings.app.get('nightly')) {
23 autoUpdater.allowPrerelease = Boolean(params.settings.app.get('nightly')); 24 autoUpdater.allowPrerelease = Boolean(
25 params.settings.app.get('nightly'),
26 );
24 autoUpdater.channel = 'alpha'; 27 autoUpdater.channel = 'alpha';
25 autoUpdater.setFeedURL({
26 provider: 'github',
27 owner: GITHUB_ORG_NAME,
28 repo: GITHUB_NIGHTLIES_REPO_NAME,
29 });
30 } 28 }
31 29
32 if (args.action === 'check') { 30 if (args.action === 'check') {
@@ -40,8 +38,8 @@ export default (params) => {
40 app.quit(); 38 app.quit();
41 }, 20); 39 }, 20);
42 } 40 }
43 } catch (e) { 41 } catch (error) {
44 console.error(e); 42 console.error(error);
45 event.sender.send('autoUpdate', { error: true }); 43 event.sender.send('autoUpdate', { error: true });
46 } 44 }
47 } 45 }
@@ -52,7 +50,7 @@ export default (params) => {
52 params.mainWindow.webContents.send('autoUpdate', { available: false }); 50 params.mainWindow.webContents.send('autoUpdate', { available: false });
53 }); 51 });
54 52
55 autoUpdater.on('update-available', (event) => { 53 autoUpdater.on('update-available', event => {
56 debug('update-available'); 54 debug('update-available');
57 55
58 if (enableUpdate) { 56 if (enableUpdate) {
@@ -63,7 +61,7 @@ export default (params) => {
63 } 61 }
64 }); 62 });
65 63
66 autoUpdater.on('download-progress', (progressObj) => { 64 autoUpdater.on('download-progress', progressObj => {
67 let logMessage = `Download speed: ${progressObj.bytesPerSecond}`; 65 let logMessage = `Download speed: ${progressObj.bytesPerSecond}`;
68 logMessage = `${logMessage} - Downloaded ${progressObj.percent}%`; 66 logMessage = `${logMessage} - Downloaded ${progressObj.percent}%`;
69 logMessage = `${logMessage} (${progressObj.transferred}/${progressObj.total})`; 67 logMessage = `${logMessage} (${progressObj.transferred}/${progressObj.total})`;
diff --git a/src/electron/ipc-api/cld.js b/src/electron/ipc-api/cld.ts
index 73e320ad9..4221f9b22 100644
--- a/src/electron/ipc-api/cld.js
+++ b/src/electron/ipc-api/cld.ts
@@ -4,17 +4,20 @@ import cld from 'cld';
4const debug = require('debug')('Ferdi:ipcApi:cld'); 4const debug = require('debug')('Ferdi:ipcApi:cld');
5 5
6export default async () => { 6export default async () => {
7 ipcMain.handle('detect-language', async (event, { sample }) => { 7 ipcMain.handle('detect-language', async (_event, { sample }) => {
8 try { 8 try {
9 const result = await cld.detect(sample); 9 const result = await cld.detect(sample);
10 debug('Checking language', 'probability', result.languages); 10 debug('Checking language', 'probability', result.languages);
11 if (result.reliable) { 11 if (result.reliable) {
12 debug('Language detected reliably, setting spellchecker language to', result.languages[0].code); 12 debug(
13 'Language detected reliably, setting spellchecker language to',
14 result.languages[0].code,
15 );
13 16
14 return result.languages[0].code; 17 return result.languages[0].code;
15 } 18 }
16 } catch (e) { 19 } catch (error) {
17 console.error(e); 20 console.error(error);
18 } 21 }
19 }); 22 });
20}; 23};
diff --git a/src/electron/ipc-api/dnd.js b/src/electron/ipc-api/dnd.ts
index 6fb8999a3..afaef9a66 100644
--- a/src/electron/ipc-api/dnd.js
+++ b/src/electron/ipc-api/dnd.ts
@@ -15,8 +15,8 @@ export default async () => {
15 const isDND = getDoNotDisturb(); 15 const isDND = getDoNotDisturb();
16 debug('Fetching DND state, set to', isDND); 16 debug('Fetching DND state, set to', isDND);
17 return isDND; 17 return isDND;
18 } catch (e) { 18 } catch (error) {
19 console.error(e); 19 console.error(error);
20 return false; 20 return false;
21 } 21 }
22 }); 22 });
diff --git a/src/electron/ipc-api/download.js b/src/electron/ipc-api/download.js
deleted file mode 100644
index ba261ba1e..000000000
--- a/src/electron/ipc-api/download.js
+++ /dev/null
@@ -1,51 +0,0 @@
1import { ipcMain, dialog, BrowserWindow } from 'electron';
2import { download } from 'electron-dl';
3import mime from 'mime-types';
4import { writeFileSync } from 'fs-extra';
5
6const debug = require('debug')('Ferdi:ipcApi:download');
7
8function decodeBase64Image(dataString) {
9 const matches = dataString.match(/^data:([A-Za-z-+/]+);base64,(.+)$/);
10
11 if (matches.length !== 3) {
12 return new Error('Invalid input string');
13 }
14
15 return Buffer.from(matches[2], 'base64');
16}
17
18export default (params) => {
19 ipcMain.on('download-file', async (event, { url, content, fileOptions = {} }) => {
20 const win = BrowserWindow.getFocusedWindow();
21
22 try {
23 if (!content) {
24 const dl = await download(win, url, {
25 saveAs: true,
26 });
27 debug('File saved to', dl.savePath);
28 } else {
29 const extension = mime.extension(fileOptions.mime);
30 const filename = `${fileOptions.name}.${extension}`;
31
32 try {
33 const saveDialog = await dialog.showSaveDialog(params.mainWindow, {
34 defaultPath: filename,
35 });
36
37 if (saveDialog.canceled) return;
38
39 const binaryImage = decodeBase64Image(content);
40 writeFileSync(saveDialog.filePath, binaryImage, 'binary');
41
42 debug('File blob saved to', saveDialog.filePath);
43 } catch (err) {
44 console.log(err);
45 }
46 }
47 } catch (e) {
48 console.error(e);
49 }
50 });
51};
diff --git a/src/electron/ipc-api/download.ts b/src/electron/ipc-api/download.ts
new file mode 100644
index 000000000..af15b157e
--- /dev/null
+++ b/src/electron/ipc-api/download.ts
@@ -0,0 +1,59 @@
1import { ipcMain, dialog, BrowserWindow } from 'electron';
2import { download } from 'electron-dl';
3import mime from 'mime-types';
4import { writeFileSync } from 'fs-extra';
5import { PathLike } from 'fs';
6
7const debug = require('debug')('Ferdi:ipcApi:download');
8
9function decodeBase64Image(dataString: string) {
10 const matches = dataString.match(/^data:([+/A-Za-z-]+);base64,(.+)$/);
11
12 if (matches?.length !== 3) {
13 return new Error('Invalid input string');
14 }
15
16 return Buffer.from(matches[2], 'base64');
17}
18
19export default (params: { mainWindow: BrowserWindow }) => {
20 ipcMain.on(
21 'download-file',
22 async (_event, { url, content, fileOptions = {} }) => {
23 const win = BrowserWindow.getFocusedWindow();
24
25 try {
26 if (!content) {
27 const dl = await download(win!, url, {
28 saveAs: true,
29 });
30 debug('File saved to', dl.savePath);
31 } else {
32 const extension = mime.extension(fileOptions.mime);
33 const filename = `${fileOptions.name}.${extension}`;
34
35 try {
36 const saveDialog = await dialog.showSaveDialog(params.mainWindow, {
37 defaultPath: filename,
38 });
39
40 if (saveDialog.canceled) return;
41
42 const binaryImage = decodeBase64Image(content);
43 writeFileSync(
44 saveDialog.filePath as PathLike,
45 binaryImage as unknown as string,
46 'binary',
47 );
48
49 debug('File blob saved to', saveDialog.filePath);
50 } catch (error) {
51 console.log(error);
52 }
53 }
54 } catch (error) {
55 console.error(error);
56 }
57 },
58 );
59};
diff --git a/src/electron/ipc-api/focusState.js b/src/electron/ipc-api/focusState.ts
index 0b4a0d8f3..01aa1a971 100644
--- a/src/electron/ipc-api/focusState.js
+++ b/src/electron/ipc-api/focusState.ts
@@ -1,4 +1,6 @@
1export default (params) => { 1import { BrowserWindow } from 'electron';
2
3export default (params: { mainWindow: BrowserWindow }) => {
2 params.mainWindow.on('focus', () => { 4 params.mainWindow.on('focus', () => {
3 params.mainWindow.webContents.send('isWindowFocused', true); 5 params.mainWindow.webContents.send('isWindowFocused', true);
4 }); 6 });
diff --git a/src/electron/ipc-api/index.js b/src/electron/ipc-api/index.ts
index 5da1edc39..f03f61517 100644
--- a/src/electron/ipc-api/index.js
+++ b/src/electron/ipc-api/index.ts
@@ -1,5 +1,7 @@
1import { BrowserWindow, Tray } from 'electron';
1import autoUpdate from './autoUpdate'; 2import autoUpdate from './autoUpdate';
2import settings from './settings'; 3import settings from './settings';
4import sessionStorage from './sessionStorage';
3import appIndicator from './appIndicator'; 5import appIndicator from './appIndicator';
4import download from './download'; 6import download from './download';
5import localServer from './localServer'; 7import localServer from './localServer';
@@ -7,13 +9,18 @@ import cld from './cld';
7import dnd from './dnd'; 9import dnd from './dnd';
8import focusState from './focusState'; 10import focusState from './focusState';
9 11
10export default (params) => { 12export default (params: {
13 mainWindow: BrowserWindow;
14 settings: any;
15 tray: Tray;
16}) => {
11 settings(params); 17 settings(params);
18 sessionStorage();
12 autoUpdate(params); 19 autoUpdate(params);
13 appIndicator(params); 20 appIndicator(params);
14 download(params); 21 download(params);
15 localServer(params); 22 localServer(params);
16 cld(params); 23 cld();
17 dnd(); 24 dnd();
18 focusState(params); 25 focusState(params);
19}; 26};
diff --git a/src/electron/ipc-api/localServer.js b/src/electron/ipc-api/localServer.ts
index 591e70504..7ee642101 100644
--- a/src/electron/ipc-api/localServer.js
+++ b/src/electron/ipc-api/localServer.ts
@@ -1,12 +1,12 @@
1import { ipcMain } from 'electron'; 1import { ipcMain, BrowserWindow } from 'electron';
2import net from 'net'; 2import net from 'net';
3import { LOCAL_HOSTNAME, LOCAL_PORT } from '../../config'; 3import { LOCAL_HOSTNAME, LOCAL_PORT } from '../../config';
4import { userDataPath } from '../../environment'; 4import { userDataPath } from '../../environment-remote';
5import startServer from '../../internal-server/start'; 5import { server } from '../../internal-server/start';
6 6
7const portInUse = function (port) { 7const portInUse = (port: number): Promise<boolean> =>
8 return new Promise((resolve) => { 8 new Promise(resolve => {
9 const server = net.createServer((socket) => { 9 const server = net.createServer(socket => {
10 socket.write('Echo server\r\n'); 10 socket.write('Echo server\r\n');
11 socket.pipe(socket); 11 socket.pipe(socket);
12 }); 12 });
@@ -20,11 +20,10 @@ const portInUse = function (port) {
20 resolve(false); 20 resolve(false);
21 }); 21 });
22 }); 22 });
23};
24 23
25let localServerStarted = false; 24let localServerStarted = false;
26 25
27export default (params) => { 26export default (params: { mainWindow: BrowserWindow }) => {
28 ipcMain.on('startLocalServer', () => { 27 ipcMain.on('startLocalServer', () => {
29 if (!localServerStarted) { 28 if (!localServerStarted) {
30 // Find next unused port for server 29 // Find next unused port for server
@@ -36,7 +35,7 @@ export default (params) => {
36 } 35 }
37 console.log('Starting local server on port', port); 36 console.log('Starting local server on port', port);
38 37
39 startServer(userDataPath(), port); 38 server(userDataPath(), port);
40 39
41 params.mainWindow.webContents.send('localServerPort', { 40 params.mainWindow.webContents.send('localServerPort', {
42 port, 41 port,
diff --git a/src/electron/ipc-api/sessionStorage.ts b/src/electron/ipc-api/sessionStorage.ts
new file mode 100644
index 000000000..3eda568a1
--- /dev/null
+++ b/src/electron/ipc-api/sessionStorage.ts
@@ -0,0 +1,35 @@
1import { ipcMain, Session, session } from 'electron';
2
3import { TODOS_PARTITION_ID } from '../../config';
4
5const debug = require('debug')('Ferdi:ipcApi:sessionStorage');
6
7function deduceSession(serviceId: string | undefined | null): Session {
8 if (serviceId) {
9 return session.fromPartition(serviceId === TODOS_PARTITION_ID ? TODOS_PARTITION_ID : `persist:service-${serviceId}`);
10 }
11 return session.defaultSession;
12}
13
14export default async () => {
15 ipcMain.on('clear-storage-data', (_event, { serviceId, targetsToClear }) => {
16 try {
17 const serviceSession = deduceSession(serviceId);
18 serviceSession.flushStorageData();
19 if (targetsToClear) {
20 debug('Clearing targets:', targetsToClear);
21 serviceSession.clearStorageData(targetsToClear);
22 } else {
23 debug('Clearing all targets');
24 serviceSession.clearStorageData();
25 }
26 } catch (error) {
27 debug(error);
28 }
29 });
30
31 ipcMain.handle('clear-cache', (_event, { serviceId }) => {
32 const serviceSession = deduceSession(serviceId);
33 return serviceSession.clearCache();
34 });
35};
diff --git a/src/electron/ipc-api/settings.js b/src/electron/ipc-api/settings.js
deleted file mode 100644
index 15182739c..000000000
--- a/src/electron/ipc-api/settings.js
+++ /dev/null
@@ -1,14 +0,0 @@
1import { ipcMain } from 'electron';
2
3export default (params) => {
4 ipcMain.on('getAppSettings', (event, type) => {
5 params.mainWindow.webContents.send('appSettings', {
6 type,
7 data: params.settings[type].allSerialized,
8 });
9 });
10
11 ipcMain.on('updateAppSettings', (event, args) => {
12 params.settings[args.type].set(args.data);
13 });
14};
diff --git a/src/electron/ipc-api/settings.ts b/src/electron/ipc-api/settings.ts
new file mode 100644
index 000000000..72de6866d
--- /dev/null
+++ b/src/electron/ipc-api/settings.ts
@@ -0,0 +1,14 @@
1import { ipcMain, BrowserWindow, Settings } from 'electron';
2
3export default (params: { mainWindow: BrowserWindow; settings: Settings }) => {
4 ipcMain.on('getAppSettings', (_event, type) => {
5 params.mainWindow.webContents.send('appSettings', {
6 type,
7 data: params.settings[type].allSerialized,
8 });
9 });
10
11 ipcMain.on('updateAppSettings', (_event, args) => {
12 params.settings[args.type].set(args.data);
13 });
14};