Skip to content

Commit b3469cd

Browse files
committed
New tray behaviour for linux
Resolves: #207
1 parent b73d40e commit b3469cd

File tree

5 files changed

+155
-75
lines changed

5 files changed

+155
-75
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* Remove @gyselroth/windows-fsstat dependency #132
1414
* Show selective sync on separate page in startup wizard #172
1515
* Remove windows registry entries on uninstall #32
16+
* New tray behaviour for linux #207
1617

1718

1819
## 1.2.1

app/main.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ ipcMain.on('link-account', (event, id) => {
428428

429429
tray.toggleState('loggedout', false);
430430
startSync(true);
431-
event.sender.send('link-account-result', true);
431+
tray.emit('link-account-result', true);
432432
}).catch((err) => {
433433
if(err.code !== 'E_BLN_OAUTH_WINDOW_OPEN') {
434434
logger.error('login not successfull', {
@@ -441,7 +441,7 @@ ipcMain.on('link-account', (event, id) => {
441441
});
442442
}
443443

444-
event.sender.send('link-account-result', false);
444+
tray.emit('link-account-result', false);
445445
});
446446
});
447447

app/ui/tray/browser.js

+11-67
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {fullSyncFactory} = require('@gyselroth/balloon-node-sync');
99

1010
const i18n = require('../../lib/i18n.js');
1111
const instance = require('../../lib/instance.js');
12+
const menuFactory = require('./menu-factory.js');
1213
const clientConfig = require('../../lib/config.js');
1314
const globalConfig = require('../../lib/global-config.js');
1415
const appState = require('../../lib/state.js');
@@ -60,70 +61,7 @@ $(window).blur(function(){
6061
});
6162

6263
function buildMenu() {
63-
var label;
64-
const {Menu, MenuItem} = remote
65-
const menu = new Menu()
66-
67-
if(showLogin === false && clientConfig.get('username')) {
68-
menu.append(new MenuItem({label: clientConfig.get('username'), enabled: false}))
69-
}
70-
71-
if(showLogin === true) {
72-
label = i18n.__('tray.menu.link');
73-
menu.append(new MenuItem({label: label, click: function(){
74-
ipcRenderer.send('link-account');
75-
ipcRenderer.send('tray-hide');
76-
}}))
77-
} else {
78-
label = i18n.__('tray.menu.unlink');
79-
menu.append(new MenuItem({label: label, click: function(){
80-
ipcRenderer.send('unlink-account');
81-
ipcRenderer.send('tray-hide');
82-
}}))
83-
}
84-
85-
menu.append(new MenuItem({type: 'separator', enabled: false}))
86-
87-
if(clientConfig.get('loggedin') === true) {
88-
if(syncStatus === true) {
89-
label = i18n.__('tray.menu.pauseSync');
90-
} else {
91-
label = i18n.__('tray.menu.continueSync');
92-
}
93-
menu.append(new MenuItem({label: label, click:function(){
94-
ipcRenderer.send('sync-toggle-pause');
95-
ipcRenderer.send('tray-hide');
96-
}}))
97-
98-
menu.append(new MenuItem({type: 'separator', enabled: false}))
99-
}
100-
101-
label = i18n.__('tray.menu.status');
102-
menu.append(new MenuItem({label: label, click: function(){
103-
loadMenu('status');
104-
}}))
105-
106-
label = i18n.__('tray.menu.settings');
107-
menu.append(new MenuItem({label: label, click: function(){
108-
loadMenu('settings');
109-
}}))
110-
111-
label = i18n.__('tray.menu.feedback');
112-
menu.append(new MenuItem({label: label, click: function(){
113-
loadMenu('feedback');
114-
}}))
115-
116-
label = i18n.__('tray.menu.about');
117-
menu.append(new MenuItem({label: label, click: function(){
118-
loadMenu('about');
119-
}}))
120-
121-
menu.append(new MenuItem({type: 'separator', enabled: false}))
122-
123-
label = i18n.__('tray.menu.close');
124-
menu.append(new MenuItem({label: label, click: function(){
125-
ipcRenderer.send('quit');
126-
}}))
64+
const menu = menuFactory(loadMenu, clientConfig, showLogin, syncStatus);
12765

12866
menu.popup(remote.getCurrentWindow());
12967
}
@@ -132,7 +70,9 @@ $('document').ready(function() {
13270
$('body').addClass(process.platform);
13371
compileTemplate();
13472

135-
ipcRenderer.on('update-window', updateWindow);
73+
ipcRenderer.on('update-window', (event, menu) => {
74+
updateWindow(menu)
75+
});
13676

13777
$('#item-installupdate').bind('click', function() {
13878
ipcRenderer.send('tray-hide');
@@ -173,6 +113,10 @@ ipcRenderer.on('sync-paused' , function() {
173113
syncStatus = false;
174114
});
175115

116+
ipcRenderer.on('tray-load-menu' , function(event, menu) {
117+
loadMenu(menu);
118+
});
119+
176120
ipcRenderer.send('tray-window-loaded');
177121
ipcRenderer.on('config', function(event, secret, secretType) {
178122
logger.info('got config', {category: 'tray-browser', secretType});
@@ -209,13 +153,13 @@ function toggleInstallUpdate() {
209153
}
210154
}
211155

212-
function updateWindow() {
156+
function updateWindow(menu='status') {
213157
logger.info('updateWindow', {category: 'tray-browser'});
214158

215159
//TODO pixtron - do we still need this?
216160
$('#tray-main').html('');
217161
toggleInstallUpdate();
218-
loadMenu('status');
162+
loadMenu(menu);
219163
}
220164

221165
function getOnLineState(callback) {

app/ui/tray/controller.js

+51-6
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ const path = require('path');
22
const os = require('os');
33

44
const electron = require('electron');
5-
const {app, BrowserWindow, ipcMain, nativeImage, Tray} = require('electron');
5+
const {app, BrowserWindow, ipcMain, Menu, nativeImage, Tray} = require('electron');
66
const positioner = require('electron-traywindow-positioner');
77

88
const url = require('url');
99
const clientConfig = require('../../lib/config.js');
1010

1111
const i18n = require('../../lib/i18n.js');
12+
const menuFactory = require('./menu-factory.js');
1213

1314
const animationSpeed = 1000/24; //24 fps
1415

@@ -17,6 +18,8 @@ const feedback = require('../feedback/controller.js');
1718
const logger = require('../../lib/logger.js');
1819
const contextMenuFactory = require('../../lib/context-menu-factory.js');
1920

21+
const TRAY_CLICK_SHOW_WINDOW = process.platform !== 'darwin';
22+
2023
const stateIconNameMap = {
2124
default: 'default',
2225
sync: 'sync',
@@ -111,6 +114,9 @@ const currentStates = {
111114
const trayWindowHeight = 410;
112115
const trayWindowWidth = 500;
113116

117+
let showLogin = true;
118+
let syncStatus = true;
119+
114120
var tray;
115121
var animationTimeout = null;
116122

@@ -224,9 +230,13 @@ module.exports = function(env, clientConfig) {
224230
tray = new Tray(icon);
225231
changeTrayIcon();
226232

227-
tray.on('click', function (event) {
228-
toggle();
229-
});
233+
if (TRAY_CLICK_SHOW_WINDOW) {
234+
tray.on('click', function (event) {
235+
toggle();
236+
});
237+
}
238+
239+
updateTrayMenu();
230240

231241
clientConfig.updateTraySecret();
232242
}
@@ -250,15 +260,15 @@ module.exports = function(env, clientConfig) {
250260
if(trayWindow) trayWindow.hide();
251261
}
252262

253-
function show() {
263+
function show(menu='status') {
254264
logger.info('show tray window', {category: 'tray'});
255265

256266
if(!trayWindow) trayWindow = createWindow();
257267

258268

259269
//UPDATE ACCESS_TOKEN
260270

261-
trayWindow.webContents.send('update-window');
271+
trayWindow.webContents.send('update-window', menu);
262272
positioner.position(trayWindow, tray.getBounds());
263273
trayWindow.setAlwaysOnTop(true);
264274
trayWindow.show();
@@ -301,29 +311,64 @@ module.exports = function(env, clientConfig) {
301311
return trayWindow;
302312
}
303313

314+
function loadMenu(menu) {
315+
if(trayWindow.isVisible()) {
316+
trayWindow.webContents.send('tray-load-menu', menu);
317+
} else {
318+
show(menu);
319+
}
320+
}
321+
322+
function updateTrayMenu() {
323+
if (TRAY_CLICK_SHOW_WINDOW) return;
324+
325+
const menu = menuFactory(loadMenu, clientConfig, showLogin, syncStatus)
326+
327+
tray.setContextMenu(menu);
328+
}
329+
304330
function emit(key, message) {
305331
if(trayWindow) trayWindow.webContents.send(key, message);
332+
333+
switch(key) {
334+
case 'unlink-account-result':
335+
showLogin = message;
336+
updateTrayMenu();
337+
break;
338+
case 'link-account-result':
339+
showLogin = !message;
340+
updateTrayMenu();
341+
break;
342+
}
306343
}
307344

308345
ipcMain.on('tray-window-loaded', function(){
309346
clientConfig.setTraySecretCallback(updateSecret);
310347
});
311348

312349
function updateSecret() {
350+
showLogin = (!clientConfig.get('loggedin') || !clientConfig.isActiveInstance())
313351
trayWindow.webContents.send('config', clientConfig.getSecret(), clientConfig.getSecretType());
352+
updateTrayMenu()
314353
}
315354

316355
function syncPaused() {
317356
trayWindow.webContents.send('sync-paused');
357+
syncStatus = false;
358+
updateTrayMenu();
318359
}
319360

320361
function syncResumed() {
321362
trayWindow.webContents.send('sync-resumed');
363+
syncStatus = true;
364+
updateTrayMenu();
322365
}
323366

324367
function syncStarted() {
325368
trayWindow.webContents.send('sync-started');
326369
toggleState('sync', true);
370+
syncStatus = true;
371+
updateTrayMenu();
327372
}
328373

329374
function syncEnded() {

app/ui/tray/menu-factory.js

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
const i18n = require('../../lib/i18n.js');
3+
4+
let Menu, MenuItem, emit;
5+
if(!process || process.type === 'renderer') {
6+
const {ipcRenderer, remote} = require('electron');
7+
Menu = remote.Menu;
8+
MenuItem = remote.MenuItem;
9+
emit = function() {
10+
ipcRenderer.send(...arguments);
11+
}
12+
13+
} else {
14+
const electron = require('electron');
15+
const ipcMain = electron.ipcMain;
16+
Menu = electron.Menu;
17+
MenuItem = electron.MenuItem;
18+
19+
emit = function() {
20+
ipcMain.emit(...arguments);
21+
}
22+
}
23+
24+
module.exports = function menuFactory(loadMenu, clientConfig, showLogin=true, syncStatus=true) {
25+
var label;
26+
const menu = new Menu()
27+
28+
if(showLogin === false && clientConfig.get('username')) {
29+
menu.append(new MenuItem({label: clientConfig.get('username'), enabled: false}))
30+
}
31+
32+
if(showLogin === true) {
33+
label = i18n.__('tray.menu.link');
34+
menu.append(new MenuItem({label: label, click: function(){
35+
emit('link-account');
36+
emit('tray-hide');
37+
}}))
38+
} else {
39+
label = i18n.__('tray.menu.unlink');
40+
menu.append(new MenuItem({label: label, click: function(){
41+
emit('unlink-account');
42+
emit('tray-hide');
43+
}}))
44+
}
45+
46+
menu.append(new MenuItem({type: 'separator', enabled: false}))
47+
48+
if(clientConfig.get('loggedin') === true) {
49+
if(syncStatus === true) {
50+
label = i18n.__('tray.menu.pauseSync');
51+
} else {
52+
label = i18n.__('tray.menu.continueSync');
53+
}
54+
menu.append(new MenuItem({label: label, click:function(){
55+
emit('sync-toggle-pause');
56+
emit('tray-hide');
57+
}}))
58+
59+
menu.append(new MenuItem({type: 'separator', enabled: false}))
60+
}
61+
62+
label = i18n.__('tray.menu.status');
63+
menu.append(new MenuItem({label: label, click: function(){
64+
loadMenu('status');
65+
}}))
66+
67+
label = i18n.__('tray.menu.settings');
68+
menu.append(new MenuItem({label: label, click: function(){
69+
loadMenu('settings');
70+
}}))
71+
72+
label = i18n.__('tray.menu.feedback');
73+
menu.append(new MenuItem({label: label, click: function(){
74+
loadMenu('feedback');
75+
}}))
76+
77+
label = i18n.__('tray.menu.about');
78+
menu.append(new MenuItem({label: label, click: function(){
79+
loadMenu('about');
80+
}}))
81+
82+
menu.append(new MenuItem({type: 'separator', enabled: false}))
83+
84+
label = i18n.__('tray.menu.close');
85+
menu.append(new MenuItem({label: label, click: function(){
86+
emit('quit');
87+
}}))
88+
89+
return menu;
90+
}

0 commit comments

Comments
 (0)