Update to Electron 16

Re-implement tray envelope icon for unread messages.

Fix minimize on close bug.
This commit is contained in:
Keith Maika 2022-01-21 22:01:40 -05:00
parent 4ce02148e2
commit 4b6cf4b86a
No known key found for this signature in database
GPG Key ID: F71740E8722C75F1
16 changed files with 136 additions and 91 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ node_modules
.DS_* .DS_*
package-lock.json package-lock.json
dist/ dist/
.idea/

View File

@ -1,5 +1,4 @@
const { addCredentials } = require('../credentials.js'); const credentials = await import('../credentials.js');
const { getCredentials, removeCredentials } = require('../credentials.js');
converse.plugins.add('converse-desktop-credentials', { converse.plugins.add('converse-desktop-credentials', {
@ -9,7 +8,7 @@ converse.plugins.add('converse-desktop-credentials', {
api.listen.on('afterResourceBinding', () => { api.listen.on('afterResourceBinding', () => {
if (_converse.connection.pass) { if (_converse.connection.pass) {
addCredentials( credentials.addCredentials(
converse.connectionManager, converse.connectionManager,
_converse.bare_jid, _converse.bare_jid,
_converse.connection.pass _converse.connection.pass
@ -18,7 +17,7 @@ converse.plugins.add('converse-desktop-credentials', {
}); });
api.listen.on('logout', () => { api.listen.on('logout', () => {
getCredentials().then((result) => removeCredentials(result.login)) credentials.getCredentials().then((result) => credentials.removeCredentials(result.login))
}); });
} }
}); });

View File

@ -0,0 +1,24 @@
/* global api */
converse.plugins.add('converse-desktop-trayicon', {
initialize() {
const {_converse} = this;
let envelopeIsShowing = false;
function hideEnvelope() {
if (envelopeIsShowing) {
api.trayService.hideEnvelope();
envelopeIsShowing = false;
}
}
window.addEventListener('focus', hideEnvelope);
_converse.api.listen.on('chatBoxInitialized', hideEnvelope);
_converse.api.listen.on('chatBoxFocused', hideEnvelope);
_converse.api.listen.on('messageNotification', () => {
api.trayService.showEnvelope();
envelopeIsShowing = true;
});
}
});

View File

@ -1,48 +1,32 @@
/* global require, module */ /* global api */
const settings = require('electron-settings'); async function addCredentials(connectionManager, login, password) {
const keytar = require('keytar')
function addCredentials (connectionManager, login, password) {
const xmppService = login.split('@').pop() const xmppService = login.split('@').pop()
settings.setSync('connectionManager', connectionManager) await api.settings.set('connectionManager', connectionManager)
settings.setSync('login', login) await api.settings.set('login', login)
keytar.setPassword(xmppService, login, password) await api.keytar.setPassword(xmppService, login, password)
} }
function getCredentials () { async function getCredentials() {
const credentials = {} const credentials = {}
credentials.login = settings.getSync('login') credentials.login = await api.settings.get('login')
return new Promise((resolve) => { if (credentials.login) {
if (credentials.login) { credentials.connectionManager = await api.settings.get('connectionManager') || null
credentials.connectionManager = settings.getSync('connectionManager') credentials.xmppService = credentials.login.split('@').pop()
credentials.xmppService = credentials.login.split('@').pop() credentials.password = await api.keytar.getPassword(credentials.xmppService, credentials.login)
let password = keytar.getPassword(credentials.xmppService, credentials.login) }
password.then((result) => {
credentials.password = result return credentials;
resolve(credentials)
})
} else {
resolve({});
}
});
} }
function removeCredentials (login) { async function removeCredentials(login) {
const xmppService = login.split('@').pop() const xmppService = login.split('@').pop();
const passwordDelete = keytar.deletePassword(xmppService, login) await api.keytar.deletePassword(xmppService, login);
return new Promise((resolve, reject) => { await api.settings.unset('login');
passwordDelete.then(() => { await api.settings.unset('connectionManager');
settings.unsetSync('login')
settings.unsetSync('connectionManager')
resolve()
}, (error) => {
reject(error)
})
})
} }
module.exports = { export {
addCredentials, addCredentials,
getCredentials, getCredentials,
removeCredentials removeCredentials

View File

@ -17,24 +17,9 @@
<div id="conversejs-bg"></div> <div id="conversejs-bg"></div>
</div> </div>
</div> </div>
<!--
@see comment https://github.com/signalapp/libsignal-protocol-javascript/issues/6#issuecomment-247208665
-->
<script>
window.nodeRequire = require
delete window.require
</script>
<!-- Place libsignal at libs dir as it's no more distributed with converse.js --> <!-- Place libsignal at libs dir as it's no more distributed with converse.js -->
<script src="./3rdparty/libsignal-protocol.js"></script> <script src="./3rdparty/libsignal-protocol.js"></script>
<script> <script src="./node_modules/converse.js/dist/converse.js"></script>
window.require = window.nodeRequire <script type="module" src="./setup.js"></script>
delete window.nodeRequire
</script>
<script>
// You can also require other files to run in this process
require('./node_modules/converse.js/dist/converse.js')
require('./setup.js')
</script>
</body> </body>
</html> </html>

13
main.js
View File

@ -1,5 +1,6 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, shell } = require('electron') const { app, BrowserWindow, ipcMain, shell } = require('electron')
const path = require('path');
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
@ -26,9 +27,7 @@ function createWindow () {
const mainWindowOptions = { const mainWindowOptions = {
zoomToPageWidth: true, zoomToPageWidth: true,
webPreferences: { webPreferences: {
nodeIntegration: true, preload: path.join(__dirname, 'preload.js')
contextIsolation: false,
enableRemoteModule: true
}, },
icon: './resources/images/logo.png', icon: './resources/images/logo.png',
} }
@ -88,6 +87,14 @@ function createWindow () {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
ipcMain.handle('settings', (e, method, ...args) => {
return settingsService[method].apply(settingsService, args);
});
ipcMain.handle('trayService', (e, method, ...args) => {
return trayService[method].apply(trayService, args);
});
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished

View File

@ -1,16 +1,18 @@
/** /**
* Module for Menu functions. * Module for Menu functions.
*/ */
const {app, Menu, BrowserWindow} = require('electron') const {app, Menu, MenuItem, BrowserWindow} = require('electron')
const settingsService = require(__dirname + '/../modules/settings-service') const settingsService = require(__dirname + '/../modules/settings-service')
const menuService = {} const menuService = {}
menuService.createMenu = () => { menuService.createMenu = () => {
const application = { let converse;
label: 'Converse Desktop', const application = new Menu();
submenu: [ application.append(new MenuItem({
label: 'Converse Desktop'
, submenu: converse = Menu.buildFromTemplate([
{ {
label: 'Reconnect', label: 'Reconnect',
accelerator: 'CmdOrCtrl+R', accelerator: 'CmdOrCtrl+R',
@ -23,10 +25,10 @@ menuService.createMenu = () => {
{ {
label: 'Minimize on close', label: 'Minimize on close',
type: 'checkbox', type: 'checkbox',
id: 'minimize-on-close',
checked: settingsService.get('minimizeOnClose'), checked: settingsService.get('minimizeOnClose'),
click: () => { click: () => {
this.checked = !this.checked; settingsService.set('minimizeOnClose', converse.getMenuItemById('minimize-on-close').checked);
settingsService.set('minimizeOnClose', this.checked);
} }
}, },
{ {
@ -40,12 +42,11 @@ menuService.createMenu = () => {
app.quit() app.quit()
}, },
}, },
], ])
} }));
application.append(new MenuItem({
const edit = { label: 'Edit'
label: 'Edit', , submenu: Menu.buildFromTemplate([
submenu: [
{ {
label: 'Undo', label: 'Undo',
accelerator: 'CmdOrCtrl+Z', accelerator: 'CmdOrCtrl+Z',
@ -77,12 +78,11 @@ menuService.createMenu = () => {
accelerator: 'CmdOrCtrl+A', accelerator: 'CmdOrCtrl+A',
role: 'selectAll', role: 'selectAll',
}, },
], ])
} }));
application.append(new MenuItem({
const help = { label: 'Help'
label: 'Help', , submenu: Menu.buildFromTemplate([
submenu: [
{ {
label: 'Debug info', label: 'Debug info',
accelerator: 'F12', accelerator: 'F12',
@ -91,12 +91,10 @@ menuService.createMenu = () => {
activeWindow.webContents.openDevTools() activeWindow.webContents.openDevTools()
} }
} }
] ])
} }));
const template = [application, edit, help] Menu.setApplicationMenu(application);
Menu.setApplicationMenu(Menu.buildFromTemplate(template))
} }
module.exports = menuService module.exports = menuService

View File

@ -1,5 +1,5 @@
/** /**
* Module for getting settigns in Main process. * Module for getting settings in Main process.
*/ */
const electronSettings = require('electron-settings') const electronSettings = require('electron-settings')
@ -18,4 +18,8 @@ settingsService.set = (itemKey, settingValue) => {
electronSettings.setSync(itemKey, settingValue) electronSettings.setSync(itemKey, settingValue)
} }
settingsService.has = (itemKey) => electronSettings.hasSync(itemKey);
settingsService.unset = (itemKey) => electronSettings.unsetSync(itemKey);
module.exports = settingsService module.exports = settingsService

View File

@ -14,13 +14,13 @@ const trayService = {}
const getTrayServiceIcon = (iconName = 'icon') => { const getTrayServiceIcon = (iconName = 'icon') => {
let iconImage = '' let iconImage = ''
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
iconImage = iconName+'Template' iconImage = iconName
} else if (process.platform === 'win32') { } else if (process.platform === 'win32') {
iconImage = iconName+'-16x16' iconImage = iconName+'-16x16'
} else { } else {
iconImage = iconName+'-48x48' iconImage = iconName+'-48x48'
} }
return path.join(__dirname, '/../resources/images/' + iconImage + '.png') return path.join(__dirname, '..','resources','images', iconImage + '.png')
} }
trayService.initTray = (window) => { trayService.initTray = (window) => {

View File

@ -22,7 +22,7 @@
], ],
"license": "MPL-2.0", "license": "MPL-2.0",
"devDependencies": { "devDependencies": {
"electron": "11.2.3", "electron": "^16.0.0",
"electron-builder": "^22.9.1", "electron-builder": "^22.9.1",
"electron-packager": "^15.2.0", "electron-packager": "^15.2.0",
"electron-rebuild": "^3.2.5", "electron-rebuild": "^3.2.5",
@ -67,7 +67,7 @@
}, },
"win": { "win": {
"target": "nsis", "target": "nsis",
"icon": "resources/images/logo.ico" "icon": "resources/images/logo.png"
} }
} }
} }

42
preload.js Normal file
View File

@ -0,0 +1,42 @@
const {ipcRenderer, contextBridge} = require('electron');
const keytar = require('keytar');
contextBridge.exposeInMainWorld('api', {
reload() {
ipcRenderer.send('reload')
},
settings: {
has(setting) {
return ipcRenderer.invoke('settings', 'has', setting);
},
set(setting, value) {
ipcRenderer.invoke('settings', 'set', setting, value);
},
unset(setting) {
ipcRenderer.invoke('settings', 'unset', setting);
},
get(setting) {
return ipcRenderer.invoke('settings', 'get', setting);
}
},
trayService: {
showEnvelope() {
ipcRenderer.invoke('trayService', 'showEnvelope');
},
hideEnvelope() {
ipcRenderer.invoke('trayService', 'hideEnvelope');
}
},
keytar: {
getPassword(service, login) {
return keytar.getPassword(service, login);
},
setPassword(service, login, password) {
return keytar.setPassword(service, login, password);
},
deletePassword(service, login) {
return keytar.deletePassword(service, login);
}
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,5 +1,6 @@
require('./app/converse-plugins/desktop-credentials.js'); await import('./app/converse-plugins/desktop-credentials.js')
const{ getCredentials } = require('./app/credentials.js') await import('./app/converse-plugins/desktop-trayicon.js')
const getCredentials = (await import('./app/credentials.js')).getCredentials;
async function initialize () { async function initialize () {
@ -39,7 +40,7 @@ async function initialize () {
theme: 'concord', theme: 'concord',
view_mode: 'fullscreen', view_mode: 'fullscreen',
websocket_url, websocket_url,
whitelisted_plugins: ['converse-debug', 'converse-desktop-credentials'], whitelisted_plugins: ['converse-debug', 'converse-desktop-credentials', 'converse-desktop-trayicon'],
}); });
} }