@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<!-- Entitlements from electron-builder's defaults |
||||
(https://github.com/electron-userland/electron-builder/blob/master/packages/app-builder-lib/templates/entitlements.mac.plist) |
||||
nb. This does *not* include the app sandbox: at the time of adding this file, |
||||
we were using electron-builder 21.2.0 which does not have the sandbox entitlement. |
||||
Latest electron-builder does, but it appears to be causing issues: |
||||
(https://github.com/electron-userland/electron-builder/issues/4390) |
||||
--> |
||||
<!-- https://github.com/electron/electron-notarize#prerequisites --> |
||||
<key>com.apple.security.cs.allow-jit</key> |
||||
<true/> |
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key> |
||||
<true/> |
||||
<!-- https://github.com/electron-userland/electron-builder/issues/3940 --> |
||||
<key>com.apple.security.cs.disable-library-validation</key> |
||||
<true/> |
||||
|
||||
<!-- Our own additional entitlements (we need to access the camera and |
||||
mic for VoIP calls --> |
||||
<key>com.apple.security.device.camera</key> |
||||
<true/> |
||||
<key>com.apple.security.device.audio-input</key> |
||||
<true/> |
||||
</dict> |
||||
</plist> |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 581 B |
Before Width: | Height: | Size: 824 B |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 4.7 KiB |
@ -1,15 +0,0 @@
|
||||
{ |
||||
"name": "riot-web", |
||||
"productName": "Riot", |
||||
"main": "src/electron-main.js", |
||||
"version": "1.6.0", |
||||
"description": "A feature-rich client for Matrix.org", |
||||
"author": "New Vector Ltd.", |
||||
"dependencies": { |
||||
"auto-launch": "^5.0.1", |
||||
"electron-store": "^2.0.0", |
||||
"electron-window-state": "^4.1.0", |
||||
"minimist": "^1.2.0", |
||||
"png-to-ico": "^1.0.2" |
||||
} |
||||
} |
@ -1,34 +0,0 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIF0jCCBLqgAwIBAgIRAISYBqZi3VvCUeSfHXF+cbwwDQYJKoZIhvcNAQELBQAw |
||||
gZExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO |
||||
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTcwNQYD |
||||
VQQDEy5DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gQ29kZSBTaWduaW5n |
||||
IENBMB4XDTE3MDgyMzAwMDAwMFoXDTIwMDgyMjIzNTk1OVowgdgxETAPBgNVBAUT |
||||
CDEwODczNjYxMRMwEQYLKwYBBAGCNzwCAQMTAkdCMR0wGwYDVQQPExRQcml2YXRl |
||||
IE9yZ2FuaXphdGlvbjELMAkGA1UEBhMCR0IxETAPBgNVBBEMCFdDMVIgNEFHMQ8w |
||||
DQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEbMBkGA1UECQwSMjYgUmVk |
||||
IExpb24gU3F1YXJlMRcwFQYDVQQKDA5OZXcgVmVjdG9yIEx0ZDEXMBUGA1UEAwwO |
||||
TmV3IFZlY3RvciBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7 |
||||
X0HP3oM/SVr6PboD03ndtYTONZDcJ/GJ3EyYi6UNrcbKjuDHwPktx9hjAhNjcVkG |
||||
lmuTEPluPj9DbvjaTrers0cQsAS1vJ0RHjLfA93Flg1ys9Q6OThUMw77FtFPtiJU |
||||
z5cSYzfFAhn/4dv7BcgGptn+Mv/8CaTu+RUZJUgoSlRWcT1TREmxkzWotbblqsHO |
||||
zjDmUg20tL5/qpt6BSWsNespf5udKQFXMtqkczBcLvBLmql0vurVcQy8BibB+Q89 |
||||
QKwRzwLgaIa7O8WEssFcW8uJe9s0SNtUy8ehbuoSxpA/DbHFwsiDbNA78vp7HrqM |
||||
qY6t6OIgLtDYBFCfe/btAgMBAAGjggHaMIIB1jAfBgNVHSMEGDAWgBTfj/MgDOnK |
||||
pgTYW1g3Kj2rRtyDSTAdBgNVHQ4EFgQUH+mDOdRkF3bYDxCWEaGB4lxiCxcwDgYD |
||||
VR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMw |
||||
EQYJYIZIAYb4QgEBBAQDAgQQMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQYBMCsw |
||||
KQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMFUGA1Ud |
||||
HwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JTQUV4 |
||||
dGVuZGVkVmFsaWRhdGlvbkNvZGVTaWduaW5nQ0EuY3JsMIGGBggrBgEFBQcBAQR6 |
||||
MHgwUAYIKwYBBQUHMAKGRGh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JT |
||||
QUV4dGVuZGVkVmFsaWRhdGlvbkNvZGVTaWduaW5nQ0EuY3J0MCQGCCsGAQUFBzAB |
||||
hhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wJgYDVR0RBB8wHaAbBggrBgEFBQcI |
||||
A6APMA0MC0dCLTEwODczNjYxMA0GCSqGSIb3DQEBCwUAA4IBAQBJ2aH4aixh0aiz |
||||
4WKlK+LMVLHpQ2POE3FZYNpAW7o1q2YDGEADXdGrygPE9NCGNBXKo0CAemCYNWfX |
||||
Ov/jdoiMfeqW3vrZ66oEy8OqbvJSwK1xmomWuYw3wYPWcPVG+YbWYD2CGdQu8jTz |
||||
fzAJCpvAuY3Wji3fQjiecAC7JCSB4fBHa0ALJOmiSqKQUUpkXs5kW7O0lPBnHzNF |
||||
2tQGltXMSIrq1QfFtcreMyKlwDOxPIh360dv5aHhaeSRDRKxq7uq5ikQF2gjKx4k |
||||
ieg2HRbAW6fVPpFr4zRS5umpeZV3i06i11VQQPS/mA/OBEXyaqzx4mr6B7U6ptrp |
||||
jMqiUv2w |
||||
-----END CERTIFICATE----- |
@ -1,6 +0,0 @@
|
||||
This directory contains the config file for the official riot.im distribution |
||||
of Riot Desktop. |
||||
|
||||
You probably do not want to build with this config unless you're building the |
||||
official riot.im distribution, or you'll find your builds will replace |
||||
themselves with the riot.im build. |
@ -1,32 +0,0 @@
|
||||
{ |
||||
"update_base_url": "https://packages.riot.im/desktop/update/", |
||||
"default_server_name": "matrix.org", |
||||
"brand": "Riot", |
||||
"integrations_ui_url": "https://scalar.vector.im/", |
||||
"integrations_rest_url": "https://scalar.vector.im/api", |
||||
"integrations_widgets_urls": [ |
||||
"https://scalar.vector.im/_matrix/integrations/v1", |
||||
"https://scalar.vector.im/api", |
||||
"https://scalar-staging.vector.im/_matrix/integrations/v1", |
||||
"https://scalar-staging.vector.im/api", |
||||
"https://scalar-staging.riot.im/scalar/api" |
||||
], |
||||
"hosting_signup_link": "https://modular.im/?utm_source=riot-web&utm_medium=web", |
||||
"bug_report_endpoint_url": "https://riot.im/bugreports/submit", |
||||
"roomDirectory": { |
||||
"servers": [ |
||||
"matrix.org" |
||||
] |
||||
}, |
||||
"piwik": { |
||||
"url": "https://piwik.riot.im/", |
||||
"siteId": 1, |
||||
"policyUrl": "https://matrix.org/legal/riot-im-cookie-policy" |
||||
}, |
||||
"features": { |
||||
}, |
||||
"enable_presence_by_hs_url": { |
||||
"https://matrix.org": false, |
||||
"https://matrix-client.matrix.org": false |
||||
} |
||||
} |
@ -1 +0,0 @@
|
||||
export OSSLSIGNCODE_SIGNARGS='-pkcs11module /Library/Frameworks/eToken.framework/Versions/Current/libeToken.dylib -pkcs11engine /usr/local/lib/engines/engine_pkcs11.so -certs electron_app/riot.im/New_Vector_Ltd.pem -key 0a3271cbc1ec0fd8afb37f6bbe0cd65ba08d3b4d -t http://timestamp.comodoca.com -verbose' |
@ -1,658 +0,0 @@
|
||||
/* |
||||
Copyright 2016 Aviral Dasgupta |
||||
Copyright 2016 OpenMarket Ltd |
||||
Copyright 2018, 2019 New Vector Ltd |
||||
Copyright 2017, 2019 Michael Telatynski <7t3chguy@gmail.com> |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
*/ |
||||
|
||||
// Squirrel on windows starts the app with various flags
|
||||
// as hooks to tell us when we've been installed/uninstalled
|
||||
// etc.
|
||||
const checkSquirrelHooks = require('./squirrelhooks'); |
||||
if (checkSquirrelHooks()) return; |
||||
|
||||
const argv = require('minimist')(process.argv, { |
||||
alias: {help: "h"}, |
||||
}); |
||||
|
||||
const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu, autoUpdater, protocol} = require('electron'); |
||||
const AutoLaunch = require('auto-launch'); |
||||
const path = require('path'); |
||||
|
||||
const tray = require('./tray'); |
||||
const vectorMenu = require('./vectormenu'); |
||||
const webContentsHandler = require('./webcontents-handler'); |
||||
const updater = require('./updater'); |
||||
const {getProfileFromDeeplink, protocolInit, recordSSOSession} = require('./protocol'); |
||||
|
||||
const windowStateKeeper = require('electron-window-state'); |
||||
const Store = require('electron-store'); |
||||
|
||||
const fs = require('fs'); |
||||
const afs = fs.promises; |
||||
|
||||
let Seshat = null; |
||||
|
||||
try { |
||||
Seshat = require('matrix-seshat'); |
||||
} catch (e) { |
||||
if (e.code === "MODULE_NOT_FOUND") { |
||||
console.log("Seshat isn't installed, event indexing is disabled."); |
||||
} else { |
||||
console.warn("Seshat unexpected error:", e); |
||||
} |
||||
} |
||||
|
||||
if (argv["help"]) { |
||||
console.log("Options:"); |
||||
console.log(" --profile-dir {path}: Path to where to store the profile."); |
||||
console.log(" --profile {name}: Name of alternate profile to use, allows for running multiple accounts."); |
||||
console.log(" --devtools: Install and use react-devtools and react-perf."); |
||||
console.log(" --no-update: Disable automatic updating."); |
||||
console.log(" --hidden: Start the application hidden in the system tray."); |
||||
console.log(" --help: Displays this help message."); |
||||
console.log("And more such as --proxy, see:" + |
||||
"https://electronjs.org/docs/api/chrome-command-line-switches#supported-chrome-command-line-switches"); |
||||
app.exit(); |
||||
} |
||||
|
||||
// check if we are passed a profile in the SSO callback url
|
||||
const userDataPathInProtocol = getProfileFromDeeplink(argv["_"]); |
||||
if (userDataPathInProtocol) { |
||||
app.setPath('userData', userDataPathInProtocol); |
||||
} else if (argv['profile-dir']) { |
||||
app.setPath('userData', argv['profile-dir']); |
||||
} else if (argv['profile']) { |
||||
app.setPath('userData', `${app.getPath('userData')}-${argv['profile']}`); |
||||
} |
||||
|
||||
let vectorConfig = {}; |
||||
try { |
||||
vectorConfig = require('../../webapp/config.json'); |
||||
} catch (e) { |
||||
// it would be nice to check the error code here and bail if the config
|
||||
// is unparseable, but we get MODULE_NOT_FOUND in the case of a missing
|
||||
// file or invalid json, so node is just very unhelpful.
|
||||
// Continue with the defaults (ie. an empty config)
|
||||
} |
||||
|
||||
try { |
||||
// Load local config and use it to override values from the one baked with the build
|
||||
const localConfig = require(path.join(app.getPath('userData'), 'config.json')); |
||||
|
||||
// If the local config has a homeserver defined, don't use the homeserver from the build
|
||||
// config. This is to avoid a problem where Riot thinks there are multiple homeservers
|
||||
// defined, and panics as a result.
|
||||
const homeserverProps = ['default_is_url', 'default_hs_url', 'default_server_name', 'default_server_config']; |
||||
if (Object.keys(localConfig).find(k => homeserverProps.includes(k))) { |
||||
// Rip out all the homeserver options from the vector config
|
||||
vectorConfig = Object.keys(vectorConfig) |
||||
.filter(k => !homeserverProps.includes(k)) |
||||
.reduce((obj, key) => {obj[key] = vectorConfig[key]; return obj;}, {}); |
||||
} |
||||
|
||||
vectorConfig = Object.assign(vectorConfig, localConfig); |
||||
} catch (e) { |
||||
// Could not load local config, this is expected in most cases.
|
||||
} |
||||
|
||||
const eventStorePath = path.join(app.getPath('userData'), 'EventStore'); |
||||
const store = new Store({ name: "electron-config" }); |
||||
|
||||
let eventIndex = null; |
||||
|
||||
let mainWindow = null; |
||||
global.appQuitting = false; |
||||
|
||||
// It's important to call `path.join` so we don't end up with the packaged asar in the final path.
|
||||
const iconFile = `riot.${process.platform === 'win32' ? 'ico' : 'png'}`; |
||||
const iconPath = path.join(__dirname, "..", "..", "img", iconFile); |
||||
const trayConfig = { |
||||
icon_path: iconPath, |
||||
brand: vectorConfig.brand || 'Riot', |
||||
}; |
||||
|
||||
// handle uncaught errors otherwise it displays
|
||||
// stack traces in popup dialogs, which is terrible (which
|
||||
// it will do any time the auto update poke fails, and there's
|
||||
// no other way to catch this error).
|
||||
// Assuming we generally run from the console when developing,
|
||||
// this is far preferable.
|
||||
process.on('uncaughtException', function(error) { |
||||
console.log('Unhandled exception', error); |
||||
}); |
||||
|
||||
let focusHandlerAttached = false; |
||||
ipcMain.on('setBadgeCount', function(ev, count) { |
||||
app.setBadgeCount(count); |
||||
if (count === 0 && mainWindow) { |
||||
mainWindow.flashFrame(false); |
||||
} |
||||
}); |
||||
|
||||
ipcMain.on('loudNotification', function() { |
||||
if (process.platform === 'win32' && mainWindow && !mainWindow.isFocused() && !focusHandlerAttached) { |
||||
mainWindow.flashFrame(true); |
||||
mainWindow.once('focus', () => { |
||||
mainWindow.flashFrame(false); |
||||
focusHandlerAttached = false; |
||||
}); |
||||
focusHandlerAttached = true; |
||||
} |
||||
}); |
||||
|
||||
let powerSaveBlockerId = null; |
||||
ipcMain.on('app_onAction', function(ev, payload) { |
||||
switch (payload.action) { |
||||
case 'call_state': |
||||
if (powerSaveBlockerId !== null && powerSaveBlocker.isStarted(powerSaveBlockerId)) { |
||||
if (payload.state === 'ended') { |
||||
powerSaveBlocker.stop(powerSaveBlockerId); |
||||
powerSaveBlockerId = null; |
||||
} |
||||
} else { |
||||
if (powerSaveBlockerId === null && payload.state === 'connected') { |
||||
powerSaveBlockerId = powerSaveBlocker.start('prevent-display-sleep'); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
}); |
||||
|
||||
autoUpdater.on('update-downloaded', (ev, releaseNotes, releaseName, releaseDate, updateURL) => { |
||||
if (!mainWindow) return; |
||||
// forward to renderer
|
||||
mainWindow.webContents.send('update-downloaded', { |
||||
releaseNotes, |
||||
releaseName, |
||||
releaseDate, |
||||
updateURL, |
||||
}); |
||||
}); |
||||
|
||||
ipcMain.on('ipcCall', async function(ev, payload) { |
||||
if (!mainWindow) return; |
||||
|
||||
const args = payload.args || []; |
||||
let ret; |
||||
|
||||
switch (payload.name) { |
||||
case 'getUpdateFeedUrl': |
||||
ret = autoUpdater.getFeedURL(); |
||||
break; |
||||
case 'getAutoLaunchEnabled': |
||||
ret = await launcher.isEnabled(); |
||||
break; |
||||
case 'setAutoLaunchEnabled': |
||||
if (args[0]) { |
||||
launcher.enable(); |
||||
} else { |
||||
launcher.disable(); |
||||
} |
||||
break; |
||||
case 'getMinimizeToTrayEnabled': |
||||
ret = tray.hasTray(); |
||||
break; |
||||
case 'setMinimizeToTrayEnabled': |
||||
if (args[0]) { |
||||
// Create trayIcon icon
|
||||
tray.create(trayConfig); |
||||
} else { |
||||
tray.destroy(); |
||||
} |
||||
store.set('minimizeToTray', args[0]); |
||||
break; |
||||
case 'getAutoHideMenuBarEnabled': |
||||
ret = global.mainWindow.isMenuBarAutoHide(); |
||||
break; |
||||
case 'setAutoHideMenuBarEnabled': |
||||
store.set('autoHideMenuBar', args[0]); |
||||
global.mainWindow.setAutoHideMenuBar(args[0]); |
||||
global.mainWindow.setMenuBarVisibility(!args[0]); |
||||
break; |
||||
case 'getAppVersion': |
||||
ret = app.getVersion(); |
||||
break; |
||||
case 'focusWindow': |
||||
if (mainWindow.isMinimized()) { |
||||
mainWindow.restore(); |
||||
} else if (!mainWindow.isVisible()) { |
||||
mainWindow.show(); |
||||
} else { |
||||
mainWindow.focus(); |
||||
} |
||||
break; |
||||
case 'getConfig': |
||||
ret = vectorConfig; |
||||
break; |
||||
case 'navigateBack': |
||||
if (mainWindow.webContents.canGoBack()) { |
||||
mainWindow.webContents.goBack(); |
||||
} |
||||
break; |
||||
case 'navigateForward': |
||||
if (mainWindow.webContents.canGoForward()) { |
||||
mainWindow.webContents.goForward(); |
||||
} |
||||
break; |
||||
case 'startSSOFlow': |
||||
recordSSOSession(args[0]); |
||||
break; |
||||
|
||||
default: |
||||
mainWindow.webContents.send('ipcReply', { |
||||
id: payload.id, |
||||
error: "Unknown IPC Call: " + payload.name, |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
mainWindow.webContents.send('ipcReply', { |
||||
id: payload.id, |
||||
reply: ret, |
||||
}); |
||||
}); |
||||
|
||||
ipcMain.on('seshat', async function(ev, payload) { |
||||
if (!mainWindow) return; |
||||
|
||||
const sendError = (id, e) => { |
||||
const error = { |
||||
message: e.message |
||||
} |
||||
|
||||
mainWindow.webContents.send('seshatReply', { |
||||
id:id, |
||||
error: error |
||||
}); |
||||
} |
||||
|
||||
const args = payload.args || []; |
||||
let ret; |
||||
|
||||
switch (payload.name) { |
||||
case 'supportsEventIndexing': |
||||
if (Seshat === null) ret = false; |
||||
else ret = true; |
||||
break; |
||||
|
||||
case 'initEventIndex': |
||||
if (eventIndex === null) { |
||||
try { |
||||
await afs.mkdir(eventStorePath, {recursive: true}); |
||||
eventIndex = new Seshat(eventStorePath, {passphrase: "DEFAULT_PASSPHRASE"}); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case 'closeEventIndex': |
||||
eventIndex = null; |
||||
break; |
||||
|
||||
case 'deleteEventIndex': |
||||
const deleteFolderRecursive = async(p) => { |
||||
for (let entry of await afs.readdir(p)) { |
||||
const curPath = path.join(p, entry); |
||||
await afs.unlink(curPath); |
||||
} |
||||
} |
||||
|
||||
try { |
||||
await deleteFolderRecursive(eventStorePath); |
||||
} catch (e) { |
||||
} |
||||
|
||||
break; |
||||
|
||||
case 'isEventIndexEmpty': |
||||
if (eventIndex === null) ret = true; |
||||
else ret = await eventIndex.isEmpty(); |
||||
break; |
||||
|
||||
case 'addEventToIndex': |
||||
try { |
||||
eventIndex.addEvent(args[0], args[1]); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
break; |
||||
|
||||
case 'commitLiveEvents': |
||||
try { |
||||
ret = await eventIndex.commit(); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
break; |
||||
|
||||
case 'searchEventIndex': |
||||
try { |
||||
ret = await eventIndex.search(args[0]); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
break; |
||||
|
||||
case 'addHistoricEvents': |
||||
if (eventIndex === null) ret = false; |
||||
else { |
||||
try { |
||||
ret = await eventIndex.addHistoricEvents( |
||||
args[0], args[1], args[2]); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case 'getStats': |
||||
if (eventIndex === null) ret = 0; |
||||
else { |
||||
try { |
||||
ret = await eventIndex.getStats(); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case 'removeCrawlerCheckpoint': |
||||
if (eventIndex === null) ret = false; |
||||
else { |
||||
try { |
||||
ret = await eventIndex.removeCrawlerCheckpoint(args[0]); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case 'addCrawlerCheckpoint': |
||||
if (eventIndex === null) ret = false; |
||||
else { |
||||
try { |
||||
ret = await eventIndex.addCrawlerCheckpoint(args[0]); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case 'loadFileEvents': |
||||
if (eventIndex === null) ret = []; |
||||
else { |
||||
try { |
||||
ret = await eventIndex.loadFileEvents(args[0]); |
||||
} catch (e) { |
||||
sendError(payload.id, e); |
||||
return; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case 'loadCheckpoints': |
||||
if (eventIndex === null) ret = []; |
||||
else { |
||||
try { |
||||
ret = await eventIndex.loadCheckpoints(); |
||||
} catch (e) { |
||||
ret = []; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
mainWindow.webContents.send('seshatReply', { |
||||
id: payload.id, |
||||
error: "Unknown IPC Call: " + payload.name, |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
mainWindow.webContents.send('seshatReply', { |
||||
id: payload.id, |
||||
reply: ret, |
||||
}); |
||||
}); |
||||
|
||||
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing'); |
||||
|
||||
const gotLock = app.requestSingleInstanceLock(); |
||||
if (!gotLock) { |
||||
console.log('Other instance detected: exiting'); |
||||
app.exit(); |
||||
} |
||||
|
||||
// do this after we know we are the primary instance of the app
|
||||
protocolInit(); |
||||
|
||||
const launcher = new AutoLaunch({ |
||||
name: vectorConfig.brand || 'Riot', |
||||
isHidden: true, |
||||
mac: { |
||||
useLaunchAgent: true, |
||||
}, |
||||
}); |
||||
|
||||
// Register the scheme the app is served from as 'standard'
|
||||
// which allows things like relative URLs and IndexedDB to
|
||||
// work.
|
||||
// Also mark it as secure (ie. accessing resources from this
|
||||
// protocol and HTTPS won't trigger mixed content warnings).
|
||||
protocol.registerSchemesAsPrivileged([{ |
||||
scheme: 'vector', |
||||
privileges: { |
||||
standard: true, |
||||
secure: true, |
||||
supportFetchAPI: true, |
||||
}, |
||||
}]); |
||||
|
||||
app.on('ready', () => { |
||||
if (argv['devtools']) { |
||||
try { |
||||
const { default: installExt, REACT_DEVELOPER_TOOLS, REACT_PERF } = require('electron-devtools-installer'); |
||||
installExt(REACT_DEVELOPER_TOOLS) |
||||
.then((name) => console.log(`Added Extension: ${name}`)) |
||||
.catch((err) => console.log('An error occurred: ', err)); |
||||
installExt(REACT_PERF) |
||||
.then((name) => console.log(`Added Extension: ${name}`)) |
||||
.catch((err) => console.log('An error occurred: ', err)); |
||||
} catch (e) { |
||||
console.log(e); |
||||
} |
||||
} |
||||
|
||||
protocol.registerFileProtocol('vector', (request, callback) => { |
||||
if (request.method !== 'GET') { |
||||
callback({error: -322}); // METHOD_NOT_SUPPORTED from chromium/src/net/base/net_error_list.h
|
||||
return null; |
||||
} |
||||
|
||||
const parsedUrl = new URL(request.url); |
||||
if (parsedUrl.protocol !== 'vector:') { |
||||
callback({error: -302}); // UNKNOWN_URL_SCHEME
|
||||
return; |
||||
} |
||||
if (parsedUrl.host !== 'vector') { |
||||
callback({error: -105}); // NAME_NOT_RESOLVED
|
||||
return; |
||||
} |
||||
|
||||
const target = parsedUrl.pathname.split('/'); |
||||
|
||||
// path starts with a '/'
|
||||
if (target[0] !== '') { |
||||
callback({error: -6}); // FILE_NOT_FOUND
|
||||
return; |
||||
} |
||||
|
||||
if (target[target.length - 1] == '') { |
||||
target[target.length - 1] = 'index.html'; |
||||
} |
||||
|
||||
let baseDir; |
||||
// first part of the path determines where we serve from
|
||||
if (target[1] === 'webapp') { |
||||
baseDir = __dirname + "/../../webapp"; |
||||
} else { |
||||
callback({error: -6}); // FILE_NOT_FOUND
|
||||
return; |
||||
} |
||||
|
||||
// Normalise the base dir and the target path separately, then make sure
|
||||
// the target path isn't trying to back out beyond its root
|
||||
baseDir = path.normalize(baseDir); |
||||
|
||||
const relTarget = path.normalize(path.join(...target.slice(2))); |
||||
if (relTarget.startsWith('..')) { |
||||
callback({error: -6}); // FILE_NOT_FOUND
|
||||
return; |
||||
} |
||||
const absTarget = path.join(baseDir, relTarget); |
||||
|
||||
callback({ |
||||
path: absTarget, |
||||
}); |
||||
}, (error) => { |
||||
if (error) console.error('Failed to register protocol'); |
||||
}); |
||||
|
||||
if (argv['no-update']) { |
||||
console.log('Auto update disabled via command line flag "--no-update"'); |
||||
} else if (vectorConfig['update_base_url']) { |
||||
console.log(`Starting auto update with base URL: ${vectorConfig['update_base_url']}`); |
||||
updater.start(vectorConfig['update_base_url']); |
||||
} else { |
||||
console.log('No update_base_url is defined: auto update is disabled'); |
||||
} |
||||
|
||||
// Load the previous window state with fallback to defaults
|
||||
const mainWindowState = windowStateKeeper({ |
||||
defaultWidth: 1024, |
||||
defaultHeight: 768, |
||||
}); |
||||
|
||||
const preloadScript = path.normalize(`${__dirname}/preload.js`); |
||||
mainWindow = global.mainWindow = new BrowserWindow({ |
||||
icon: iconPath, |
||||
show: false, |
||||
autoHideMenuBar: store.get('autoHideMenuBar', true), |
||||
|
||||
x: mainWindowState.x, |
||||
y: mainWindowState.y, |
||||
width: mainWindowState.width, |
||||
height: mainWindowState.height, |
||||
webPreferences: { |
||||
preload: preloadScript, |
||||
nodeIntegration: false, |
||||
sandbox: true, |
||||
enableRemoteModule: false, |
||||
// We don't use this: it's useful for the preload script to
|
||||
// share a context with the main page so we can give select
|
||||
// objects to the main page. The sandbox option isolates the
|
||||
// main page from the background script.
|
||||
contextIsolation: false, |
||||
webgl: false, |
||||
}, |
||||
}); |
||||
mainWindow.loadURL('vector://vector/webapp/'); |
||||
Menu.setApplicationMenu(vectorMenu); |
||||
|
||||
// Create trayIcon icon
|
||||
if (store.get('minimizeToTray', true)) tray.create(trayConfig); |
||||
|
||||
mainWindow.once('ready-to-show', () => { |
||||
mainWindowState.manage(mainWindow); |
||||
|
||||
if (!argv['hidden']) { |
||||
mainWindow.show(); |
||||
} else { |
||||
// hide here explicitly because window manage above sometimes shows it
|
||||
mainWindow.hide(); |
||||
} |
||||
}); |
||||
|
||||
mainWindow.on('closed', () => { |
||||
mainWindow = global.mainWindow = null; |
||||
}); |
||||
mainWindow.on('close', (e) => { |
||||
// If we are not quitting and have a tray icon then minimize to tray
|
||||
if (!global.appQuitting && (tray.hasTray() || process.platform === 'darwin')) { |
||||
// On Mac, closing the window just hides it
|
||||
// (this is generally how single-window Mac apps
|
||||
// behave, eg. Mail.app)
|
||||
e.preventDefault(); |
||||
mainWindow.hide(); |
||||
return false; |
||||
} |
||||
}); |
||||
|
||||
if (process.platform === 'win32') { |
||||
// Handle forward/backward mouse buttons in Windows
|
||||
mainWindow.on('app-command', (e, cmd) => { |
||||
if (cmd === 'browser-backward' && mainWindow.webContents.canGoBack()) { |
||||
mainWindow.webContents.goBack(); |
||||
} else if (cmd === 'browser-forward' && mainWindow.webContents.canGoForward()) { |
||||
mainWindow.webContents.goForward(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
webContentsHandler(mainWindow.webContents); |
||||
}); |
||||
|
||||
app.on('window-all-closed', () => { |
||||
app.quit(); |
||||
}); |
||||
|
||||
app.on('activate', () => { |
||||
mainWindow.show(); |
||||
}); |
||||
|
||||
app.on('before-quit', () => { |
||||
global.appQuitting = true; |
||||
if (mainWindow) { |
||||
mainWindow.webContents.send('before-quit'); |
||||
} |
||||
}); |
||||
|
||||
app.on('second-instance', (ev, commandLine, workingDirectory) => { |
||||
// If other instance launched with --hidden then skip showing window
|
||||
if (commandLine.includes('--hidden')) return; |
||||
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (mainWindow) { |
||||
if (!mainWindow.isVisible()) mainWindow.show(); |
||||
if (mainWindow.isMinimized()) mainWindow.restore(); |
||||
mainWindow.focus(); |
||||
} |
||||
}); |
||||
|
||||
// Set the App User Model ID to match what the squirrel
|
||||
// installer uses for the shortcut icon.
|
||||
// This makes notifications work on windows 8.1 (and is
|
||||
// a noop on other platforms).
|
||||
app.setAppUserModelId('com.squirrel.riot-web.Riot'); |
@ -1,20 +0,0 @@
|
||||
/* |
||||
Copyright 2018, 2019 New Vector Ltd |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
*/ |
||||
|
||||
const { ipcRenderer } = require('electron'); |
||||
|
||||
// expose ipcRenderer to the renderer process
|
||||
window.ipcRenderer = ipcRenderer; |
@ -1,104 +0,0 @@
|
||||
/* |
||||
Copyright 2020 The Matrix.org Foundation C.I.C. |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
*/ |
||||
|
||||
const {app} = require("electron"); |
||||
const path = require("path"); |
||||
const fs = require("fs"); |
||||
|
||||
const PROTOCOL = "riot://"; |
||||
const SEARCH_PARAM = "riot-desktop-ssoid"; |
||||
const STORE_FILE_NAME = "sso-sessions.json"; |
||||
|
||||
// we getPath userData before electron-main changes it, so this is the default value
|
||||
const storePath = path.join(app.getPath("userData"), STORE_FILE_NAME); |
||||
|
||||
const processUrl = (url) => { |
||||
if (!global.mainWindow) return; |
||||
console.log("Handling link: ", url); |
||||
global.mainWindow.loadURL(url.replace(PROTOCOL, "vector://")); |
||||
}; |
||||
|
||||
const readStore = () => { |
||||
try { |
||||
const s = fs.readFileSync(storePath, { encoding: "utf8" }); |
||||
const o = JSON.parse(s); |
||||
return typeof o === "object" ? o : {}; |
||||
} catch (e) { |
||||
return {}; |
||||
} |
||||
}; |
||||
|
||||
const writeStore = (data) => { |
||||
fs.writeFileSync(storePath, JSON.stringify(data)); |
||||
}; |
||||
|
||||
module.exports = { |
||||
recordSSOSession: (sessionID) => { |
||||
const userDataPath = app.getPath('userData'); |
||||
const store = readStore(); |
||||
for (const key in store) { |
||||
// ensure each instance only has one (the latest) session ID to prevent the file growing unbounded
|
||||
if (store[key] === userDataPath) { |
||||
delete store[key]; |
||||
break; |
||||
} |
||||
} |
||||
store[sessionID] = userDataPath; |
||||
writeStore(store); |
||||
}, |
||||
getProfileFromDeeplink: (args) => { |
||||
// check if we are passed a profile in the SSO callback url
|
||||
const deeplinkUrl = args.find(arg => arg.startsWith('riot://')); |
||||
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) { |
||||
const parsedUrl = new URL(deeplinkUrl); |
||||
if (parsedUrl.protocol === 'riot:') { |
||||
const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM); |
||||
const store = readStore(); |
||||
console.log("Forwarding to profile: ", store[ssoID]); |
||||
return store[ssoID]; |
||||
} |
||||
} |
||||
}, |
||||
protocolInit: () => { |
||||
// get all args except `hidden` as it'd mean the app would not get focused
|
||||
// XXX: passing args to protocol handlers only works on Windows, so unpackaged deep-linking
|
||||
// --profile/--profile-dir are passed via the SEARCH_PARAM var in the callback url
|
||||
const args = process.argv.slice(1).filter(arg => arg !== "--hidden" && arg !== "-hidden"); |
||||
if (app.isPackaged) { |
||||
app.setAsDefaultProtocolClient('riot', process.execPath, args); |
||||
} else if (process.platform === 'win32') { // on Mac/Linux this would just cause the electron binary to open
|
||||
// special handler for running without being packaged, e.g `electron .` by passing our app path to electron
|
||||
app.setAsDefaultProtocolClient('riot', process.execPath, [app.getAppPath(), ...args]); |
||||
} |
||||
|
||||
if (process.platform === 'darwin') { |
||||
// Protocol handler for macos
|
||||
app.on('open-url', function(ev, url) { |
||||
ev.preventDefault(); |
||||
processUrl(url); |
||||
}); |
||||
} else { |
||||
// Protocol handler for win32/Linux
|
||||
app.on('second-instance', (ev, commandLine) => { |
||||
const url = commandLine[commandLine.length - 1]; |
||||
if (!url.startsWith(PROTOCOL)) return; |
||||
processUrl(url); |
||||
}); |
||||
} |
||||
}, |
||||
}; |
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
/* |
||||
Copyright 2017 OpenMarket Ltd |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
*/ |
||||
|
||||
const path = require('path'); |
||||
const spawn = require('child_process').spawn; |
||||
const {app} = require('electron'); |
||||
|
||||
function runUpdateExe(args, done) { |
||||
// Invokes Squirrel's Update.exe which will do things for us like create shortcuts
|
||||
// Note that there's an Update.exe in the app-x.x.x directory and one in the parent
|
||||
// directory: we need to run the one in the parent directory, because it discovers
|
||||
// information about the app by inspecting the directory it's run from.
|
||||
const updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe'); |
||||
console.log(`Spawning '${updateExe}' with args '${args}'`); |
||||
spawn(updateExe, args, { |
||||
detached: true, |
||||
}).on('close', done); |
||||
} |
||||
|
||||
function checkSquirrelHooks() { |
||||
if (process.platform !== 'win32') return false; |
||||
|
||||
const cmd = process.argv[1]; |
||||
const target = path.basename(process.execPath); |
||||
if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') { |
||||
runUpdateExe(['--createShortcut=' + target + ''], app.quit); |
||||
return true; |
||||
} else if (cmd === '--squirrel-uninstall') { |
||||
runUpdateExe(['--removeShortcut=' + target + ''], app.quit); |
||||
return true; |
||||
} else if (cmd === '--squirrel-obsolete') { |
||||
app.quit(); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
module.exports = checkSquirrelHooks; |
@ -1,106 +0,0 @@
|
||||
/* |
||||
Copyright 2017 Karl Glatz <karl@glatz.biz> |
||||
Copyright 2017 OpenMarket Ltd |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
*/ |
||||
|
||||
const {app, Tray, Menu, nativeImage} = require('electron'); |
||||
const pngToIco = require('png-to-ico'); |
||||
const path = require('path'); |
||||
const fs = require('fs'); |
||||
|
||||
let trayIcon = null; |
||||
|
||||
exports.hasTray = function hasTray() { |
||||
return (trayIcon !== null); |
||||
}; |
||||
|
||||
exports.destroy = function() { |
||||
if (trayIcon) { |
||||
trayIcon.destroy(); |
||||
trayIcon = null; |
||||
} |
||||
}; |
||||
|
||||
exports.create = function(config) { |
||||
// no trays on darwin
|
||||
if (process.platform === 'darwin' || trayIcon) return; |
||||
|
||||
const toggleWin = function() { |
||||
if (global.mainWindow.isVisible() && !global.mainWindow.isMinimized()) { |
||||
global.mainWindow.hide(); |
||||
} else { |
||||
if (global.mainWindow.isMinimized()) global.mainWindow.restore(); |
||||
if (!global.mainWindow.isVisible()) global.mainWindow.show(); |
||||
global.mainWindow.focus(); |
||||
} |
||||
}; |
||||
|
||||
const contextMenu = Menu.buildFromTemplate([ |
||||
{ |
||||
label: `Show/Hide ${config.brand}`, |
||||
click: toggleWin, |
||||
}, |
||||
{ type: 'separator' }, |
||||
{ |
||||
label: 'Quit', |
||||
click: function() { |
||||
app.quit(); |
||||
}, |
||||
}, |
||||
]); |
||||
|
||||
const defaultIcon = nativeImage.createFromPath(config.icon_path); |
||||
|
||||
trayIcon = new Tray(defaultIcon); |
||||
trayIcon.setToolTip(config.brand); |
||||
trayIcon.setContextMenu(contextMenu); |
||||
trayIcon.on('click', toggleWin); |
||||
|
||||
let lastFavicon = null; |
||||
global.mainWindow.webContents.on('page-favicon-updated', async function(ev, favicons) { |
||||
if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) { |
||||
if (lastFavicon !== null) { |
||||
global.mainWindow.setIcon(defaultIcon); |
||||
trayIcon.setImage(defaultIcon); |
||||
lastFavicon = null; |
||||
} |
||||
return; |
||||
} |
||||
|
||||
// No need to change, shortcut
|
||||
if (favicons[0] === lastFavicon) return; |
||||
lastFavicon = favicons[0]; |
||||
|
||||
let newFavicon = nativeImage.createFromDataURL(favicons[0]); |
||||
|
||||
// Windows likes ico's too much.
|
||||
if (process.platform === 'win32') { |
||||
try { |
||||
const icoPath = path.join(app.getPath('temp'), 'win32_riot_icon.ico'); |
||||
fs.writeFileSync(icoPath, await pngToIco(newFavicon.toPNG())); |
||||
newFavicon = nativeImage.createFromPath(icoPath); |
||||
} catch (e) { |
||||
console.error("Failed to make win32 ico", e); |
||||
} |
||||
} |
||||
|
||||
trayIcon.setImage(newFavicon); |
||||
global.mainWindow.setIcon(newFavicon); |
||||
}); |
||||
|
||||
global.mainWindow.webContents.on('page-title-updated', function(ev, title) { |
||||
trayIcon.setToolTip(title); |
||||
}); |
||||
}; |
@ -1,84 +0,0 @@
|
||||
const { app, autoUpdater, ipcMain } = require('electron'); |
||||
|
||||
const UPDATE_POLL_INTERVAL_MS = 60 * 60 * 1000; |
||||
const INITIAL_UPDATE_DELAY_MS = 30 * 1000; |
||||
|
||||
function installUpdate() { |
||||
// for some reason, quitAndInstall does not fire the
|
||||
// before-quit event, so we need to set the flag here.
|
||||
global.appQuitting = true; |
||||
autoUpdater.quitAndInstall(); |
||||
} |
||||
|
||||
function pollForUpdates() { |
||||
try { |
||||
autoUpdater.checkForUpdates(); |
||||
} catch (e) { |
||||
console.log('Couldn\'t check for update', e); |
||||
} |
||||
} |
||||
|
||||
module.exports = {}; |
||||
module.exports.start = function startAutoUpdate(updateBaseUrl) { |
||||
if (updateBaseUrl.slice(-1) !== '/') { |
||||
updateBaseUrl = updateBaseUrl + '/'; |
||||
} |
||||
try { |
||||
let url; |
||||
// For reasons best known to Squirrel, the way it checks for updates
|
||||
// is completely different between macOS and windows. On macOS, it
|
||||
// hits a URL that either gives it a 200 with some json or
|
||||
// 204 No Content. On windows it takes a base path and looks for
|
||||
// files under that path.
|
||||
if (process.platform === 'darwin') { |
||||
// include the current version in the URL we hit. Electron doesn't add
|
||||
// it anywhere (apart from the User-Agent) so it's up to us. We could
|
||||
// (and previously did) just use the User-Agent, but this doesn't
|
||||
// rely on NSURLConnection setting the User-Agent to what we expect,
|
||||
// and also acts as a convenient cache-buster to ensure that when the
|
||||
// app updates it always gets a fresh value to avoid update-looping.
|
||||
url = `${updateBaseUrl}macos/?localVersion=${encodeURIComponent(app.getVersion())}`; |
||||
|
||||
} else if (process.platform === 'win32') { |
||||
url = `${updateBaseUrl}win32/${process.arch}/`; |
||||
} else { |
||||
// Squirrel / electron only supports auto-update on these two platforms.
|
||||
// I'm not even going to try to guess which feed style they'd use if they
|
||||
// implemented it on Linux, or if it would be different again.
|
||||
console.log('Auto update not supported on this platform'); |
||||
} |
||||
|
||||
if (url) { |
||||
autoUpdater.setFeedURL(url); |
||||
// We check for updates ourselves rather than using 'updater' because we need to
|
||||
// do it in the main process (and we don't really need to check every 10 minutes:
|
||||
// every hour should be just fine for a desktop app)
|
||||
// However, we still let the main window listen for the update events.
|
||||
// We also wait a short time before checking for updates the first time because
|
||||
// of squirrel on windows and it taking a small amount of time to release a
|
||||
// lock file.
|
||||
setTimeout(pollForUpdates, INITIAL_UPDATE_DELAY_MS); |
||||
setInterval(pollForUpdates, UPDATE_POLL_INTERVAL_MS); |
||||
} |
||||
} catch (err) { |
||||
// will fail if running in debug mode
|
||||
console.log('Couldn\'t enable update checking', err); |
||||
} |
||||
} |
||||
|
||||
ipcMain.on('install_update', installUpdate); |
||||
ipcMain.on('check_updates', pollForUpdates); |
||||
|
||||
function ipcChannelSendUpdateStatus(status) { |
||||
if (global.mainWindow) { |
||||
global.mainWindow.webContents.send('check_updates', status); |
||||
} |
||||
} |
||||
|
||||
autoUpdater.on('update-available', function() { |
||||
ipcChannelSendUpdateStatus(true); |
||||
}).on('update-not-available', function() { |
||||
ipcChannelSendUpdateStatus(false); |
||||
}).on('error', function(error) { |
||||
ipcChannelSendUpdateStatus(error.message); |
||||
}); |
@ -1,144 +0,0 @@
|
||||
/* |
||||
Copyright 2016 OpenMarket Ltd |
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
you may not use this file except in compliance with the License. |
||||
You may obtain a copy of the License at |
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software |
||||
distributed under the License is distributed on an "AS IS" BASIS, |
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
See the License for the specific language governing permissions and |
||||
limitations under the License. |
||||
*/ |
||||
|
||||
const {app, shell, Menu} = require('electron'); |
||||
|
||||
// Menu template from http://electron.atom.io/docs/api/menu/, edited
|
||||
const template = [ |
||||
{ |
||||
label: '&Edit', |
||||
submenu: [ |
||||
{ role: 'undo' }, |
||||
{ role: 'redo' }, |
||||
{ type: 'separator' }, |
||||
{ role: 'cut' }, |
||||
{ role: 'copy' }, |
||||
{ role: 'paste' }, |
||||
{ role: 'pasteandmatchstyle' }, |
||||
{ role: 'delete' }, |
||||
{ role: 'selectall' }, |
||||
], |
||||
}, |
||||
{ |
||||
label: '&View', |
||||
submenu: [ |
||||
{ type: 'separator' }, |
||||
{ role: 'resetzoom' }, |
||||
{ role: 'zoomin', accelerator: 'CommandOrControl+=' }, |
||||
{ role: 'zoomout' }, |
||||
{ type: 'separator' }, |
||||
{ |
||||