Improve OS menu (#1563)

* Remove reload options, new file/help menus, tools/log at bottom

* Further menus refactor: install handlers at template creation

* WIP: Further tune menus, add custom about window

* New About window, new help menu items, menu labels now i18n

* Default device name on registration is now computer hostname

The OS of the device makes sense for those of us testing across a lot of
different OSes. And maybe for a user with just one desktop device. But
most users with multiple desktop devices are using the same OS for both.

* About window: Only show window when content is ready

* Fix typo in app/menu.js
This commit is contained in:
Scott Nonnenberg 2017-10-13 16:49:16 -07:00 committed by GitHub
parent 61a2a1a8f8
commit 75cece3358
7 changed files with 290 additions and 105 deletions

View File

@ -360,6 +360,38 @@
"message": "Submit debug log",
"description": "Menu item and header text for debug log modal, title case."
},
"debugLog": {
"message": "Debug Log",
"description": "View menu item to open the debug log, capitalized"
},
"goToReleaseNotes": {
"message": "Go to release notes",
"description": ""
},
"goToForums": {
"message": "Go to forums",
"description": "Item under the Help menu, takes you to the forums"
},
"goToSupportPage": {
"message": "Go to support page",
"description": "Item under the Help menu, takes you to the support page"
},
"fileABug": {
"message": "File a bug",
"description": "Item under the Help menu, takes you to GitHub new issue form"
},
"aboutSignalDesktop": {
"message": "About Signal Desktop",
"description": "Item under the Help menu, which opens a small about window"
},
"speech": {
"message": "Speech",
"description": "Item under the Edit menu, with 'start/stop speaking' items below it"
},
"show": {
"message": "Show",
"description": "Command under Window menu, to show the window"
},
"searchForPeopleOrGroups": {
"message": "Search...",
"description": "Placeholder text in the search input"

39
about.html Normal file
View File

@ -0,0 +1,39 @@
<html>
<head>
<link href="stylesheets/manifest.css" rel="stylesheet" type="text/css" />
<style>
body {
text-align: center;
background-color: #2090EA;
color: white;
font-size: 14px;
}
img {
margin-top: 2em;
margin-bottom: 1em;
}
a {
color: white;
}
</style>
</head>
<body>
<img src='images/icon_250.png'>
<div>
<script>
document.write('v', window.config.version);
</script>
</div>
<div>
<a href="https://signal.org">signal.org</a>
</div>
</body>
</html>

View File

@ -1,35 +1,48 @@
const {Menu} = require('electron')
function createTemplate(options, messages) {
const showDebugLog = options.showDebugLog;
const showAbout = options.showAbout;
const openReleaseNotes = options.openReleaseNotes;
const openNewBugForm = options.openNewBugForm;
const openSupportPage = options.openSupportPage;
const openForums = options.openForums;
const template = [
let template = [{
label: 'File',
submenu: [
{
role: 'quit',
},
]
},
{
label: 'Edit',
submenu: [
{
role: 'undo'
role: 'undo',
},
{
role: 'redo'
role: 'redo',
},
{
type: 'separator'
type: 'separator',
},
{
role: 'cut'
role: 'cut',
},
{
role: 'copy'
role: 'copy',
},
{
role: 'paste'
role: 'paste',
},
{
role: 'pasteandmatchstyle'
role: 'pasteandmatchstyle',
},
{
role: 'delete'
role: 'delete',
},
{
role: 'selectall'
role: 'selectall',
}
]
},
@ -37,123 +50,163 @@ const template = [
label: 'View',
submenu: [
{
label: 'Debug Log'
role: 'resetzoom',
},
{
type: 'separator'
role: 'zoomin',
},
{
role: 'reload'
role: 'zoomout',
},
{
role: 'forcereload'
type: 'separator',
},
{
role: 'toggledevtools'
role: 'togglefullscreen',
},
{
type: 'separator'
type: 'separator',
},
{
role: 'resetzoom'
label: messages.debugLog.message,
click: showDebugLog,
},
{
role: 'zoomin'
type: 'separator',
},
{
role: 'zoomout'
role: 'toggledevtools',
},
{
type: 'separator'
},
{
role: 'togglefullscreen'
}
]
},
{
role: 'window',
submenu: [
{
role: 'minimize'
role: 'minimize',
},
]
},
{
role: 'help',
submenu: [
{
label: messages.goToReleaseNotes.message,
click: openReleaseNotes,
},
{
role: 'close'
}
type: 'separator',
},
{
label: messages.goToForums.message,
click: openForums,
},
{
label: messages.goToSupportPage.message,
click: openSupportPage,
},
{
label: messages.fileABug.message,
click: openNewBugForm,
},
{
type: 'separator',
},
{
label: messages.aboutSignalDesktop.message,
click: showAbout,
},
]
}
]
}];
if (process.platform === 'darwin') {
if (process.platform === 'darwin') {
return updateForMac(template, messages, options);
}
return template;
}
function updateForMac(template, messages, options) {
const showWindow = options.showWindow;
const showAbout = options.showAbout;
// Remove About item and separator from Help menu, since it's on the first menu
template[4].submenu.pop();
template[4].submenu.pop();
// Replace File menu
template.shift();
template.unshift({
submenu: [
{
role: 'about'
label: messages.aboutSignalDesktop.message,
click: showAbout,
},
{
type: 'separator'
type: 'separator',
},
{
role: 'hide'
role: 'hide',
},
{
role: 'hideothers'
role: 'hideothers',
},
{
role: 'unhide'
role: 'unhide',
},
{
type: 'separator'
type: 'separator',
},
{
role: 'quit'
}
role: 'quit',
},
]
})
// Edit menu.
});
// Add to Edit menu
template[1].submenu.push(
{
type: 'separator'
},
{
label: 'Speech',
label: messages.speech.message,
submenu: [
{
role: 'startspeaking'
role: 'startspeaking',
},
{
role: 'stopspeaking'
}
role: 'stopspeaking',
},
]
}
)
// Window menu.
);
// Add to Window menu
template[3].submenu = [
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
role: 'close',
},
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
role: 'minimize',
},
{
label: 'Zoom',
role: 'zoom'
role: 'zoom',
},
{
label: 'Show',
label: messages.show.message,
click: showWindow,
},
{
type: 'separator'
type: 'separator',
},
{
label: 'Bring All to Front',
role: 'front'
}
]
role: 'front',
},
];
return template;
}
module.exports = template;
module.exports = createTemplate;

View File

@ -147,7 +147,6 @@
welcomeToSignal : i18n('welcomeToSignal'),
selectAContact : i18n('selectAContact'),
searchForPeopleOrGroups : i18n('searchForPeopleOrGroups'),
submitDebugLog : i18n('submitDebugLog'),
settings : i18n('settings'),
restartSignal : i18n('restartSignal'),
},

View File

@ -45,13 +45,7 @@
var deviceName = textsecure.storage.user.getDeviceName();
if (!deviceName) {
if (navigator.userAgent.match('Mac OS')) {
deviceName = 'Mac';
} else if (navigator.userAgent.match('Linux')) {
deviceName = 'Linux';
} else if (navigator.userAgent.match('Windows')) {
deviceName = 'Windows';
}
deviceName = window.config.hostname;
}
this.$('#device-name').val(deviceName);

139
main.js
View File

@ -1,5 +1,6 @@
const path = require('path');
const url = require('url');
const os = require('os');
const electron = require('electron')
@ -52,6 +53,38 @@ const loadLocale = require('./app/locale').load;
let locale;
function prepareURL(pathSegments) {
return url.format({
pathname: path.join.apply(null, pathSegments),
protocol: 'file:',
slashes: true,
query: {
locale: locale.name,
version: app.getVersion(),
buildExpiration: config.get('buildExpiration'),
serverUrl: config.get('serverUrl'),
cdnUrl: config.get('cdnUrl'),
certificateAuthorities: config.get('certificateAuthorities'),
environment: config.environment,
node_version: process.versions.node,
hostname: os.hostname(),
}
})
}
function handleUrl(event, target) {
event.preventDefault();
const protocol = url.parse(target).protocol;
if (protocol === 'http:' || protocol === 'https:') {
shell.openExternal(target);
}
}
function captureClicks(window) {
window.webContents.on('will-navigate', handleUrl)
window.webContents.on('new-window', handleUrl);
}
function createWindow () {
const windowOptions = Object.assign({
width: 800,
@ -112,24 +145,6 @@ function createWindow () {
event.returnValue = locale.messages;
});
function prepareURL(pathSegments) {
return url.format({
pathname: path.join.apply(null, pathSegments),
protocol: 'file:',
slashes: true,
query: {
locale: locale.name,
version: app.getVersion(),
buildExpiration: config.get('buildExpiration'),
serverUrl: config.get('serverUrl'),
cdnUrl: config.get('cdnUrl'),
certificateAuthorities: config.get('certificateAuthorities'),
environment: config.environment,
node_version: process.versions.node
}
})
}
if (config.environment === 'test') {
mainWindow.loadURL(prepareURL([__dirname, 'test', 'index.html']));
} else {
@ -141,13 +156,7 @@ function createWindow () {
mainWindow.webContents.openDevTools()
}
mainWindow.webContents.on('new-window', (e, url) => {
e.preventDefault();
const protocol = require('url').parse(url).protocol
if (protocol === 'http:' || protocol === 'https:') {
shell.openExternal(url)
}
});
captureClicks(mainWindow);
mainWindow.webContents.on('will-navigate', function(e) {
logger.info('will-navigate');
@ -189,6 +198,65 @@ function showDebugLog() {
}
}
function showWindow() {
if (mainWindow) {
mainWindow.show();
}
};
function openReleaseNotes() {
shell.openExternal('https://github.com/WhisperSystems/Signal-Desktop/releases/tag/v' + app.getVersion());
}
function openNewBugForm() {
shell.openExternal('https://github.com/WhisperSystems/Signal-Desktop/issues/new');
}
function openSupportPage() {
shell.openExternal('https://support.signal.org/hc/en-us/categories/202319038-Desktop');
}
function openForums() {
shell.openExternal('https://whispersystems.discoursehosting.net/');
}
let aboutWindow;
function showAbout() {
if (aboutWindow) {
aboutWindow.show();
return;
}
const options = {
width: 500,
height: 400,
resizable: false,
title: locale.messages.aboutSignalDesktop.message,
autoHideMenuBar: true,
backgroundColor: '#2090EA',
show: false,
webPreferences: {
nodeIntegration: false,
preload: path.join(__dirname, 'preload.js')
}
};
aboutWindow = new BrowserWindow(options);
captureClicks(aboutWindow);
aboutWindow.loadURL(prepareURL([__dirname, 'about.html']));
aboutWindow.on('closed', function () {
aboutWindow = null;
});
aboutWindow.once('ready-to-show', function() {
aboutWindow.show();
});
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
@ -203,16 +271,17 @@ app.on('ready', function() {
createWindow();
let template = require('./app/menu.js');
if (process.platform === 'darwin') {
template[3].submenu[3].click = function() {
mainWindow.show();
};
template[2].submenu[0].click = showDebugLog;
} else {
template[1].submenu[0].click = showDebugLog;
}
const options = {
showDebugLog,
showWindow,
showAbout,
openReleaseNotes,
openNewBugForm,
openSupportPage,
openForums,
};
const createTemplate = require('./app/menu.js');
const template = createTemplate(options, locale.messages);
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);

View File

@ -47,7 +47,6 @@
<button class='hamburger' alt='signal menu'></button>
<ul class='menu-list'>
<li class='showSettings'>{{ settings }}</li>
<li class='show-debug-log'>{{ submitDebugLog }}</li>
<li class='restart-signal'>{{ restartSignal }}</li>
</ul>
</div>