diff options
Diffstat (limited to 'src/electron')
-rw-r--r-- | src/electron/Settings.js | 10 | ||||
-rw-r--r-- | src/electron/ipc-api/appIndicator.js | 4 | ||||
-rw-r--r-- | src/electron/ipc-api/download.js | 4 | ||||
-rw-r--r-- | src/electron/ipc-api/localServer.js | 14 | ||||
-rw-r--r-- | src/electron/macOSPermissions.js | 67 | ||||
-rw-r--r-- | src/electron/webview-ime-focus.js | 4 |
6 files changed, 49 insertions, 54 deletions
diff --git a/src/electron/Settings.js b/src/electron/Settings.js index 2f3f8261a..3e11bb175 100644 --- a/src/electron/Settings.js +++ b/src/electron/Settings.js | |||
@@ -1,8 +1,6 @@ | |||
1 | import { observable, toJS } from 'mobx'; | 1 | import { observable, toJS } from 'mobx'; |
2 | import { pathExistsSync, outputJsonSync, readJsonSync } from 'fs-extra'; | 2 | import { pathExistsSync, outputJsonSync, readJsonSync } from 'fs-extra'; |
3 | import path from 'path'; | 3 | import { userDataPath } from '../environment'; |
4 | |||
5 | import { SETTINGS_PATH } from '../environment'; | ||
6 | 4 | ||
7 | const debug = require('debug')('Ferdi:Settings'); | 5 | const debug = require('debug')('Ferdi:Settings'); |
8 | 6 | ||
@@ -47,17 +45,17 @@ export default class Settings { | |||
47 | 45 | ||
48 | _hydrate() { | 46 | _hydrate() { |
49 | this.store = this._merge(readJsonSync(this.settingsFile)); | 47 | this.store = this._merge(readJsonSync(this.settingsFile)); |
50 | debug('Hydrate store', this.type, toJS(this.store)); | 48 | debug('Hydrate store', this.type, this.allSerialized); |
51 | } | 49 | } |
52 | 50 | ||
53 | _writeFile() { | 51 | _writeFile() { |
54 | outputJsonSync(this.settingsFile, this.store, { | 52 | outputJsonSync(this.settingsFile, this.store, { |
55 | spaces: 2, | 53 | spaces: 2, |
56 | }); | 54 | }); |
57 | debug('Write settings file', this.type, toJS(this.store)); | 55 | debug('Write settings file', this.type, this.allSerialized); |
58 | } | 56 | } |
59 | 57 | ||
60 | get settingsFile() { | 58 | get settingsFile() { |
61 | return path.join(SETTINGS_PATH, `${this.type === 'app' ? 'settings' : this.type}.json`); | 59 | return userDataPath('config', `${this.type === 'app' ? 'settings' : this.type}.json`); |
62 | } | 60 | } |
63 | } | 61 | } |
diff --git a/src/electron/ipc-api/appIndicator.js b/src/electron/ipc-api/appIndicator.js index 0691e5170..c6c261d0f 100644 --- a/src/electron/ipc-api/appIndicator.js +++ b/src/electron/ipc-api/appIndicator.js | |||
@@ -1,5 +1,5 @@ | |||
1 | import { app, ipcMain } from 'electron'; | 1 | import { app, ipcMain } from 'electron'; |
2 | import path from 'path'; | 2 | import { join } from 'path'; |
3 | import { autorun } from 'mobx'; | 3 | import { autorun } from 'mobx'; |
4 | import { isMac, isWindows, isLinux } from '../../environment'; | 4 | import { isMac, isWindows, isLinux } from '../../environment'; |
5 | 5 | ||
@@ -9,7 +9,7 @@ const FILE_EXTENSION = isWindows ? 'ico' : 'png'; | |||
9 | let isTrayIconEnabled; | 9 | let isTrayIconEnabled; |
10 | 10 | ||
11 | function getAsset(type, asset) { | 11 | function getAsset(type, asset) { |
12 | return path.join( | 12 | return join( |
13 | __dirname, '..', '..', 'assets', 'images', type, process.platform, `${asset}.${FILE_EXTENSION}`, | 13 | __dirname, '..', '..', 'assets', 'images', type, process.platform, `${asset}.${FILE_EXTENSION}`, |
14 | ); | 14 | ); |
15 | } | 15 | } |
diff --git a/src/electron/ipc-api/download.js b/src/electron/ipc-api/download.js index 7f8718924..ba261ba1e 100644 --- a/src/electron/ipc-api/download.js +++ b/src/electron/ipc-api/download.js | |||
@@ -1,7 +1,7 @@ | |||
1 | import { ipcMain, dialog, BrowserWindow } from 'electron'; | 1 | import { ipcMain, dialog, BrowserWindow } from 'electron'; |
2 | import { download } from 'electron-dl'; | 2 | import { download } from 'electron-dl'; |
3 | import mime from 'mime-types'; | 3 | import mime from 'mime-types'; |
4 | import fs from 'fs-extra'; | 4 | import { writeFileSync } from 'fs-extra'; |
5 | 5 | ||
6 | const debug = require('debug')('Ferdi:ipcApi:download'); | 6 | const debug = require('debug')('Ferdi:ipcApi:download'); |
7 | 7 | ||
@@ -37,7 +37,7 @@ export default (params) => { | |||
37 | if (saveDialog.canceled) return; | 37 | if (saveDialog.canceled) return; |
38 | 38 | ||
39 | const binaryImage = decodeBase64Image(content); | 39 | const binaryImage = decodeBase64Image(content); |
40 | fs.writeFileSync(saveDialog.filePath, binaryImage, 'binary'); | 40 | writeFileSync(saveDialog.filePath, binaryImage, 'binary'); |
41 | 41 | ||
42 | debug('File blob saved to', saveDialog.filePath); | 42 | debug('File blob saved to', saveDialog.filePath); |
43 | } catch (err) { | 43 | } catch (err) { |
diff --git a/src/electron/ipc-api/localServer.js b/src/electron/ipc-api/localServer.js index 9b800fdf6..591e70504 100644 --- a/src/electron/ipc-api/localServer.js +++ b/src/electron/ipc-api/localServer.js | |||
@@ -1,9 +1,9 @@ | |||
1 | import { ipcMain, app } from 'electron'; | 1 | import { ipcMain } from 'electron'; |
2 | import net from 'net'; | 2 | import net from 'net'; |
3 | import { LOCAL_HOSTNAME, LOCAL_PORT } from '../../config'; | ||
4 | import { userDataPath } from '../../environment'; | ||
3 | import startServer from '../../internal-server/start'; | 5 | import startServer from '../../internal-server/start'; |
4 | 6 | ||
5 | const DEFAULT_PORT = 45569; | ||
6 | |||
7 | const portInUse = function (port) { | 7 | const portInUse = function (port) { |
8 | return new Promise((resolve) => { | 8 | return new Promise((resolve) => { |
9 | const server = net.createServer((socket) => { | 9 | const server = net.createServer((socket) => { |
@@ -11,7 +11,7 @@ const portInUse = function (port) { | |||
11 | socket.pipe(socket); | 11 | socket.pipe(socket); |
12 | }); | 12 | }); |
13 | 13 | ||
14 | server.listen(port, '127.0.0.1'); | 14 | server.listen(port, LOCAL_HOSTNAME); |
15 | server.on('error', () => { | 15 | server.on('error', () => { |
16 | resolve(true); | 16 | resolve(true); |
17 | }); | 17 | }); |
@@ -28,15 +28,15 @@ export default (params) => { | |||
28 | ipcMain.on('startLocalServer', () => { | 28 | ipcMain.on('startLocalServer', () => { |
29 | if (!localServerStarted) { | 29 | if (!localServerStarted) { |
30 | // Find next unused port for server | 30 | // Find next unused port for server |
31 | let port = DEFAULT_PORT; | 31 | let port = LOCAL_PORT; |
32 | (async () => { | 32 | (async () => { |
33 | // eslint-disable-next-line no-await-in-loop | 33 | // eslint-disable-next-line no-await-in-loop |
34 | while ((await portInUse(port)) && port < DEFAULT_PORT + 10) { | 34 | while ((await portInUse(port)) && port < LOCAL_PORT + 10) { |
35 | port += 1; | 35 | port += 1; |
36 | } | 36 | } |
37 | console.log('Starting local server on port', port); | 37 | console.log('Starting local server on port', port); |
38 | 38 | ||
39 | startServer(app.getPath('userData'), port); | 39 | startServer(userDataPath(), port); |
40 | 40 | ||
41 | params.mainWindow.webContents.send('localServerPort', { | 41 | params.mainWindow.webContents.send('localServerPort', { |
42 | port, | 42 | port, |
diff --git a/src/electron/macOSPermissions.js b/src/electron/macOSPermissions.js index 940b16c6e..887af2903 100644 --- a/src/electron/macOSPermissions.js +++ b/src/electron/macOSPermissions.js | |||
@@ -1,83 +1,80 @@ | |||
1 | import { app, systemPreferences, dialog } from 'electron'; | 1 | import { systemPreferences, dialog } from 'electron'; |
2 | import fs from 'fs'; | 2 | import { pathExistsSync, mkdirSync, writeFileSync } from 'fs-extra'; |
3 | import macosVersion from 'macos-version'; | 3 | import macosVersion from 'macos-version'; |
4 | import path from 'path'; | 4 | import { dirname } from 'path'; |
5 | import { isMac } from '../environment'; | 5 | import { askForScreenCaptureAccess } from 'node-mac-permissions'; |
6 | 6 | import { userDataPath } from '../environment'; | |
7 | let askForScreenCaptureAccess; | ||
8 | if (isMac) { | ||
9 | // eslint-disable-next-line global-require | ||
10 | askForScreenCaptureAccess = require('node-mac-permissions').askForScreenCaptureAccess; | ||
11 | } | ||
12 | 7 | ||
13 | const debug = require('debug')('Ferdi:macOSPermissions'); | 8 | const debug = require('debug')('Ferdi:macOSPermissions'); |
14 | 9 | ||
15 | const permissionExists = macosVersion.isGreaterThanOrEqualTo('10.15'); | 10 | const isExplicitScreenCapturePermissionReqd = macosVersion.isGreaterThanOrEqualTo('10.15'); |
16 | const filePath = path.join(app.getPath('userData'), '.has-app-requested-screen-capture-permissions'); | 11 | debug(`Should check explicitly for screen-capture permissions: ${isExplicitScreenCapturePermissionReqd}`); |
17 | 12 | ||
18 | function hasPromptedForPermission() { | 13 | const filePath = userDataPath('.has-app-requested-screen-capture-permissions'); |
19 | if (!permissionExists) { | ||
20 | return false; | ||
21 | } | ||
22 | 14 | ||
23 | if (filePath && fs.existsSync(filePath)) { | 15 | function hasPromptedForScreenCapturePermission() { |
24 | return true; | 16 | if (!isExplicitScreenCapturePermissionReqd) { |
17 | return false; | ||
25 | } | 18 | } |
26 | 19 | ||
27 | return false; | 20 | debug('Checking if status file exists'); |
21 | return filePath && pathExistsSync(filePath); | ||
28 | } | 22 | } |
29 | 23 | ||
30 | function hasScreenCapturePermission() { | 24 | function hasScreenCapturePermissionAlreadyBeenGranted() { |
31 | if (!permissionExists) { | 25 | if (!isExplicitScreenCapturePermissionReqd) { |
32 | return true; | 26 | return true; |
33 | } | 27 | } |
34 | 28 | ||
35 | const screenCaptureStatus = systemPreferences.getMediaAccessStatus('screen'); | 29 | const screenCaptureStatus = systemPreferences.getMediaAccessStatus('screen'); |
30 | debug(`screen-capture permissions status: ${screenCaptureStatus}`); | ||
36 | return screenCaptureStatus === 'granted'; | 31 | return screenCaptureStatus === 'granted'; |
37 | } | 32 | } |
38 | 33 | ||
39 | function createStatusFile() { | 34 | function createStatusFile() { |
40 | try { | 35 | try { |
41 | fs.writeFileSync(filePath, ''); | 36 | writeFileSync(filePath, ''); |
42 | } catch (error) { | 37 | } catch (error) { |
43 | if (error.code === 'ENOENT') { | 38 | if (error.code === 'ENOENT') { |
44 | fs.mkdirSync(path.dirname(filePath)); | 39 | mkdirSync(dirname(filePath)); |
45 | fs.writeFileSync(filePath, ''); | 40 | writeFileSync(filePath, ''); |
46 | } | 41 | } |
47 | 42 | ||
48 | throw error; | 43 | throw error; |
49 | } | 44 | } |
50 | } | 45 | } |
51 | 46 | ||
52 | export default async function (mainWindow) { | 47 | export const askFormacOSPermissions = async mainWindow => { |
53 | debug('Checking camera & microphone permissions'); | 48 | debug('Checking camera & microphone permissions'); |
54 | systemPreferences.askForMediaAccess('camera'); | 49 | systemPreferences.askForMediaAccess('camera'); |
55 | systemPreferences.askForMediaAccess('microphone'); | 50 | systemPreferences.askForMediaAccess('microphone'); |
56 | 51 | ||
57 | if (!hasPromptedForPermission() && !hasScreenCapturePermission()) { | 52 | if (hasScreenCapturePermissionAlreadyBeenGranted()) { |
53 | debug('Already obtained screen-capture permissions - writing status file'); | ||
54 | createStatusFile(); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | if (!hasPromptedForScreenCapturePermission()) { | ||
58 | debug('Checking screen capture permissions'); | 59 | debug('Checking screen capture permissions'); |
59 | 60 | ||
60 | const { response } = await dialog.showMessageBox(mainWindow, { | 61 | const { response } = await dialog.showMessageBox(mainWindow, { |
61 | type: 'info', | 62 | type: 'info', |
62 | message: 'Enable Screen Sharing', | 63 | message: 'Enable Screen Sharing', |
63 | detail: 'To enable screen sharing for some services, Ferdi needs the permission to record your screen.', | 64 | detail: |
64 | buttons: [ | 65 | 'To enable screen sharing for some services, Ferdi needs the permission to record your screen.', |
65 | 'Allow screen sharing', | 66 | buttons: ['Allow screen sharing', 'No', 'Ask me later'], |
66 | 'No', | ||
67 | 'Ask me later', | ||
68 | ], | ||
69 | defaultId: 0, | 67 | defaultId: 0, |
70 | cancelId: 2, | 68 | cancelId: 2, |
71 | }); | 69 | }); |
72 | 70 | ||
73 | console.log('result', response); | ||
74 | if (response === 0) { | 71 | if (response === 0) { |
75 | debug('Asking for access'); | 72 | debug('Asking for access'); |
76 | askForScreenCaptureAccess(); | 73 | askForScreenCaptureAccess(); |
77 | createStatusFile(); | 74 | createStatusFile(); |
78 | } else if (response === 1) { | 75 | } else if (response === 1) { |
79 | debug('Don\'t ask again'); | 76 | debug("Don't ask again"); |
80 | createStatusFile(); | 77 | createStatusFile(); |
81 | } | 78 | } |
82 | } | 79 | } |
83 | } | 80 | }; |
diff --git a/src/electron/webview-ime-focus.js b/src/electron/webview-ime-focus.js index b9421eb06..e187ee0b4 100644 --- a/src/electron/webview-ime-focus.js +++ b/src/electron/webview-ime-focus.js | |||
@@ -1,5 +1,5 @@ | |||
1 | const { webContents } = require('@electron/remote'); | 1 | import { webContents } from '@electron/remote'; |
2 | const { releaseDocumentFocus } = require('./webview-ime-focus-helpers'); | 2 | import { releaseDocumentFocus } from './webview-ime-focus-helpers'; |
3 | 3 | ||
4 | function giveWebviewDocumentFocus(element) { | 4 | function giveWebviewDocumentFocus(element) { |
5 | releaseDocumentFocus(); | 5 | releaseDocumentFocus(); |