Merge branch 'kicken-pr-electron-16'

This commit is contained in:
JC Brand 2022-03-23 21:56:57 +01:00
commit 6b9910aa13
16 changed files with 169 additions and 108 deletions

1
.gitignore vendored
View File

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

View File

@ -1,5 +1,4 @@
const { addCredentials } = require('../credentials.js');
const { getCredentials, removeCredentials } = require('../credentials.js');
const credentials = await import('../credentials.js');
converse.plugins.add('converse-desktop-credentials', {
@ -9,7 +8,7 @@ converse.plugins.add('converse-desktop-credentials', {
api.listen.on('afterResourceBinding', () => {
if (_converse.connection.pass) {
addCredentials(
credentials.addCredentials(
converse.connectionManager,
_converse.bare_jid,
_converse.connection.pass
@ -18,7 +17,7 @@ converse.plugins.add('converse-desktop-credentials', {
});
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');
const keytar = require('keytar')
function addCredentials (connectionManager, login, password) {
async function addCredentials(connectionManager, login, password) {
const xmppService = login.split('@').pop()
settings.setSync('connectionManager', connectionManager)
settings.setSync('login', login)
keytar.setPassword(xmppService, login, password)
await api.settings.set('connectionManager', connectionManager)
await api.settings.set('login', login)
await api.keytar.setPassword(xmppService, login, password)
}
function getCredentials () {
async function getCredentials() {
const credentials = {}
credentials.login = settings.getSync('login')
return new Promise((resolve) => {
if (credentials.login) {
credentials.connectionManager = settings.getSync('connectionManager')
credentials.xmppService = credentials.login.split('@').pop()
let password = keytar.getPassword(credentials.xmppService, credentials.login)
password.then((result) => {
credentials.password = result
resolve(credentials)
})
} else {
resolve({});
}
});
credentials.login = await api.settings.get('login')
if (credentials.login) {
credentials.connectionManager = await api.settings.get('connectionManager') || null
credentials.xmppService = credentials.login.split('@').pop()
credentials.password = await api.keytar.getPassword(credentials.xmppService, credentials.login)
}
return credentials;
}
function removeCredentials (login) {
const xmppService = login.split('@').pop()
const passwordDelete = keytar.deletePassword(xmppService, login)
return new Promise((resolve, reject) => {
passwordDelete.then(() => {
settings.unsetSync('login')
settings.unsetSync('connectionManager')
resolve()
}, (error) => {
reject(error)
})
})
async function removeCredentials(login) {
const xmppService = login.split('@').pop();
await api.keytar.deletePassword(xmppService, login);
await api.settings.unset('login');
await api.settings.unset('connectionManager');
}
module.exports = {
export {
addCredentials,
getCredentials,
removeCredentials

View File

@ -11,30 +11,15 @@
<link rel="stylesheet" type="text/css" href="resources/css/page-settings.css">
</head>
<base href="./">
<body class="converse-fullscreen" ng-app="app">
<body class="converse-fullscreen">
<div class="main-window">
<div class="page-default">
<div id="conversejs-bg"></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 -->
<script src="./3rdparty/libsignal-protocol.js"></script>
<script>
window.require = window.nodeRequire
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>
<script src="./node_modules/converse.js/dist/converse.min.js"></script>
<script type="module" src="./setup.js"></script>
</body>
</html>

21
main.js
View File

@ -1,5 +1,6 @@
// Modules to control application life and create native browser window
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
// be closed automatically when the JavaScript object is garbage collected.
@ -26,20 +27,15 @@ function createWindow () {
const mainWindowOptions = {
zoomToPageWidth: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
preload: path.join(__dirname, 'preload.js')
},
icon: './resources/images/logo.png',
}
// Create the browser window.
mainWindow = new BrowserWindow(mainWindowOptions)
app.mainWindow = mainWindow = new BrowserWindow(mainWindowOptions)
mainWindow.maximize();
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Init tray
trayService.initTray(mainWindow)
@ -88,6 +84,17 @@ function createWindow () {
e.preventDefault()
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);
});
// and load the index.html of the app.
mainWindow.loadFile('index.html')
}
// This method will be called when Electron has finished

View File

@ -1,16 +1,19 @@
/**
* 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 prompt = require('electron-prompt');
const menuService = {}
menuService.createMenu = () => {
const application = {
label: 'Converse Desktop',
submenu: [
let converse;
const application = new Menu();
application.append(new MenuItem({
label: 'Converse Desktop'
, submenu: converse = Menu.buildFromTemplate([
{
label: 'Reconnect',
accelerator: 'CmdOrCtrl+R',
@ -23,10 +26,30 @@ menuService.createMenu = () => {
{
label: 'Minimize on close',
type: 'checkbox',
id: 'minimize-on-close',
checked: settingsService.get('minimizeOnClose'),
click: () => {
this.checked = !this.checked;
settingsService.set('minimizeOnClose', this.checked);
settingsService.set('minimizeOnClose', converse.getMenuItemById('minimize-on-close').checked);
}
},
{
label: 'Connection Manager...',
click: () => {
let currentValue = settingsService.get('connectionManager') || '';
prompt({
title: 'Connection manager'
, label: 'Connection manager URL:'
, value: currentValue
, resizable: true
, width: 620
, height: 180
}, app.mainWindow).then(function (newValue) {
if (newValue !== null && newValue !== currentValue) {
settingsService.set('connectionManager', newValue === '' ? null : newValue);
app.mainWindow.reload()
}
}).catch(function (ex) {
});
}
},
{
@ -40,12 +63,11 @@ menuService.createMenu = () => {
app.quit()
},
},
],
}
const edit = {
label: 'Edit',
submenu: [
])
}));
application.append(new MenuItem({
label: 'Edit'
, submenu: Menu.buildFromTemplate([
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
@ -77,12 +99,11 @@ menuService.createMenu = () => {
accelerator: 'CmdOrCtrl+A',
role: 'selectAll',
},
],
}
const help = {
label: 'Help',
submenu: [
])
}));
application.append(new MenuItem({
label: 'Help'
, submenu: Menu.buildFromTemplate([
{
label: 'Debug info',
accelerator: 'F12',
@ -91,12 +112,10 @@ menuService.createMenu = () => {
activeWindow.webContents.openDevTools()
}
}
]
}
])
}));
const template = [application, edit, help]
Menu.setApplicationMenu(Menu.buildFromTemplate(template))
Menu.setApplicationMenu(application);
}
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')
@ -18,4 +18,8 @@ settingsService.set = (itemKey, settingValue) => {
electronSettings.setSync(itemKey, settingValue)
}
settingsService.has = (itemKey) => electronSettings.hasSync(itemKey);
settingsService.unset = (itemKey) => electronSettings.unsetSync(itemKey);
module.exports = settingsService

View File

@ -2,38 +2,32 @@
* Module for Tray functions.
*/
const { BrowserWindow, Tray } = require('electron')
const { Tray } = require('electron')
const path = require('path')
let trayServiceWindow = null
let tray = null
const trayService = {}
const getTrayServiceIcon = (iconName = 'icon') => {
let iconImage = ''
if (process.platform === 'darwin') {
iconImage = iconName+'Template'
} else if (process.platform === 'win32') {
let iconImage;
if (process.platform === 'darwin' || process.platform === 'win32') {
iconImage = iconName+'-16x16'
} else {
iconImage = iconName+'-48x48'
}
return path.join(__dirname, '/../resources/images/' + iconImage + '.png')
return path.join(__dirname, '..','resources','images', iconImage + '.png')
}
trayService.initTray = (window) => {
trayServiceWindow = window
const iconPath = getTrayServiceIcon()
tray = new Tray(iconPath)
tray.setToolTip('Converse Desktop')
tray.on('click', function() {
// Sent open-related-chat event only on click
const activeWindow = BrowserWindow.getAllWindows()[0]
activeWindow.webContents.send('open-unread-chat')
window.webContents.send('open-unread-chat')
trayService.hideEnvelope()
trayServiceWindow.show()
window.show()
})
}

View File

@ -22,18 +22,19 @@
],
"license": "MPL-2.0",
"devDependencies": {
"electron": "11.2.3",
"electron": "^16.0.0",
"electron-builder": "^22.9.1",
"electron-packager": "^15.2.0",
"electron-rebuild": "^3.2.5",
"eslint": "^8.4.1"
},
"dependencies": {
"converse.js": "conversejs/converse.js#ba6da97416b912a35060a4c5667bc77f76852780",
"converse.js": "conversejs/converse.js#cb0b176",
"electron-settings": "^4.0.2",
"github-buttons": "^2.8.0",
"keytar": "^7.3.0",
"open-iconic": "^1.1.1"
"open-iconic": "^1.1.1",
"electron-prompt": "^1.7.0"
},
"build": {
"appId": "com.denry.converse-desktop",
@ -67,7 +68,7 @@
},
"win": {
"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');
const{ getCredentials } = require('./app/credentials.js')
await import('./app/converse-plugins/desktop-credentials.js')
await import('./app/converse-plugins/desktop-trayicon.js')
const getCredentials = (await import('./app/credentials.js')).getCredentials;
async function initialize () {
@ -39,7 +40,7 @@ async function initialize () {
theme: 'concord',
view_mode: 'fullscreen',
websocket_url,
whitelisted_plugins: ['converse-debug', 'converse-desktop-credentials'],
whitelisted_plugins: ['converse-debug', 'converse-desktop-credentials', 'converse-desktop-trayicon'],
});
}