From 8313fb48c5f2efd1cd6742056ac397af50ee326b Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 19 Oct 2017 02:18:32 +0200 Subject: remove unused file --- src/electron/ipc-api/tray.js | 48 -------------------------------------------- 1 file changed, 48 deletions(-) delete mode 100644 src/electron/ipc-api/tray.js (limited to 'src') diff --git a/src/electron/ipc-api/tray.js b/src/electron/ipc-api/tray.js deleted file mode 100644 index 43364c0ed..000000000 --- a/src/electron/ipc-api/tray.js +++ /dev/null @@ -1,48 +0,0 @@ -import { Tray, Menu, ipcMain } from 'electron'; -import path from 'path'; - -const INDICATOR_PLAIN = 'franz-taskbar'; -const INDICATOR_UNREAD = 'franz-taskbar-unread'; - -const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; - -let trayIcon; - -function getAsset(asset) { - return path.join( - __dirname, '..', '..', 'assets', 'images', 'tray', process.platform, `${asset}.${FILE_EXTENSION}`, - ); -} - -export default (params) => { - // if (process.platform === 'win32' || process.platform === 'linux') { - trayIcon = new Tray(getAsset(INDICATOR_PLAIN)); - const trayMenuTemplate = [ - { - label: 'Show Franz', - click() { - params.mainWindow.show(); - }, - }, { - label: 'Quit Franz', - click() { - params.app.quit(); - }, - }, - ]; - - const trayMenu = Menu.buildFromTemplate(trayMenuTemplate); - trayIcon.setContextMenu(trayMenu); - - trayIcon.on('click', () => { - params.mainWindow.show(); - }); - - ipcMain.on('updateTrayIconIndicator', (event, args) => { - trayIcon.setImage(getAsset(args.count !== 0 ? INDICATOR_UNREAD : INDICATOR_PLAIN)); - - if (process.platform === 'darwin') { - trayIcon.setPressedImage(getAsset(`${args.count !== 0 ? INDICATOR_UNREAD : INDICATOR_PLAIN}-active`)); - } - }); -}; -- cgit v1.2.3-70-g09d2 From 9479bf3db965bd8cb4d7c2318204e87d24bc7a56 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 19 Oct 2017 10:56:58 +0200 Subject: remove unnecessary platform check --- src/electron/ipc-api/settings.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/electron/ipc-api/settings.js b/src/electron/ipc-api/settings.js index 1d7eafa6c..995b28fbd 100644 --- a/src/electron/ipc-api/settings.js +++ b/src/electron/ipc-api/settings.js @@ -1,10 +1,7 @@ import { ipcMain } from 'electron'; export default (params) => { - if (process.platform === 'darwin' || process.platform === 'win32') { - // eslint-disable-next-line - ipcMain.on('settings', (event, args) => { - params.settings.set(args); - }); - } + ipcMain.on('settings', (event, args) => { + params.settings.set(args); + }); }; -- cgit v1.2.3-70-g09d2 From ef503a1e29a540c7318efb5f2018efbf00706198 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 19 Oct 2017 11:15:25 +0200 Subject: Add option to disable system tray icon --- .../settings/settings/EditSettingsForm.js | 1 + src/config.js | 10 ++++ src/containers/settings/EditSettingsScreen.js | 23 ++++++-- src/electron/Settings.js | 14 ++++- src/electron/ipc-api/appIndicator.js | 45 +++++---------- src/i18n/locales/en-US.json | 1 + src/index.js | 25 ++++++--- src/lib/Tray.js | 64 ++++++++++++++++++++++ 8 files changed, 136 insertions(+), 47 deletions(-) create mode 100644 src/lib/Tray.js (limited to 'src') diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 02736dbb9..5675fecf4 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js @@ -115,6 +115,7 @@ export default class EditSettingsForm extends Component {

{intl.formatMessage(messages.headlineGeneral)}

+ {process.platform === 'win32' && ( )} diff --git a/src/config.js b/src/config.js index acbf57f3c..0a4856ece 100644 --- a/src/config.js +++ b/src/config.js @@ -3,3 +3,13 @@ export const LOCAL_API = 'http://localhost:3000'; export const DEV_API = 'https://dev.franzinfra.com'; export const LIVE_API = 'https://api.franzinfra.com'; export const GA_ID = 'UA-74126766-6'; + +export const DEFAULT_APP_SETTINGS = { + autoLaunchOnStart: true, + autoLaunchInBackground: false, + runInBackground: false, + enableSystemTray: true, + minimizeToSystemTray: false, + locale: 'en-us', // TODO: Replace with proper solution once translations are in + beta: false, +}; diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js index 0e17cafce..6dc2175e1 100644 --- a/src/containers/settings/EditSettingsScreen.js +++ b/src/containers/settings/EditSettingsScreen.js @@ -9,6 +9,7 @@ import UserStore from '../../stores/UserStore'; import Form from '../../lib/Form'; import languages from '../../i18n/languages'; import { gaPage } from '../../lib/analytics'; +import { DEFAULT_APP_SETTINGS } from '../../config'; import EditSettingsForm from '../../components/settings/settings/EditSettingsForm'; @@ -26,6 +27,10 @@ const messages = defineMessages({ id: 'settings.app.form.runInBackground', defaultMessage: '!!!Keep Franz in background when closing the window', }, + enableSystemTray: { + id: 'settings.app.form.enableSystemTray', + defaultMessage: '!!!Show Franz in system tray', + }, minimizeToSystemTray: { id: 'settings.app.form.minimizeToSystemTray', defaultMessage: '!!!Minimize Franz to system tray', @@ -61,6 +66,7 @@ export default class EditSettingsScreen extends Component { settings.update({ settings: { runInBackground: settingsData.runInBackground, + enableSystemTray: settingsData.enableSystemTray, minimizeToSystemTray: settingsData.minimizeToSystemTray, locale: settingsData.locale, beta: settingsData.beta, @@ -91,33 +97,38 @@ export default class EditSettingsScreen extends Component { autoLaunchOnStart: { label: intl.formatMessage(messages.autoLaunchOnStart), value: app.autoLaunchOnStart, - default: true, + default: DEFAULT_APP_SETTINGS.autoLaunchOnStart, }, autoLaunchInBackground: { label: intl.formatMessage(messages.autoLaunchInBackground), value: app.launchInBackground, - default: false, + default: DEFAULT_APP_SETTINGS.autoLaunchInBackground, }, runInBackground: { label: intl.formatMessage(messages.runInBackground), value: settings.all.runInBackground, - default: true, + default: DEFAULT_APP_SETTINGS.runInBackground, + }, + enableSystemTray: { + label: intl.formatMessage(messages.enableSystemTray), + value: settings.all.enableSystemTray, + default: DEFAULT_APP_SETTINGS.enableSystemTray, }, minimizeToSystemTray: { label: intl.formatMessage(messages.minimizeToSystemTray), value: settings.all.minimizeToSystemTray, - default: false, + default: DEFAULT_APP_SETTINGS.minimizeToSystemTray, }, locale: { label: intl.formatMessage(messages.language), value: app.locale, options, - default: 'en-US', + default: DEFAULT_APP_SETTINGS.locale, }, beta: { label: intl.formatMessage(messages.beta), value: user.data.beta, - default: false, + default: DEFAULT_APP_SETTINGS.beta, }, }, }; diff --git a/src/electron/Settings.js b/src/electron/Settings.js index 049a08296..824b4c20c 100644 --- a/src/electron/Settings.js +++ b/src/electron/Settings.js @@ -1,5 +1,17 @@ +import { observable } from 'mobx'; + +import { DEFAULT_APP_SETTINGS } from '../config'; + export default class Settings { - store = {}; + @observable store = { + autoLaunchOnStart: DEFAULT_APP_SETTINGS.autoLaunchOnStart, + autoLaunchInBackground: DEFAULT_APP_SETTINGS.autoLaunchInBackground, + runInBackground: DEFAULT_APP_SETTINGS.runInBackground, + enableSystemTray: DEFAULT_APP_SETTINGS.enableSystemTray, + minimizeToSystemTray: DEFAULT_APP_SETTINGS.minimizeToSystemTray, + locale: DEFAULT_APP_SETTINGS.locale, + beta: DEFAULT_APP_SETTINGS.beta, + }; set(settings) { this.store = Object.assign(this.store, settings); diff --git a/src/electron/ipc-api/appIndicator.js b/src/electron/ipc-api/appIndicator.js index 576234d25..d31819068 100644 --- a/src/electron/ipc-api/appIndicator.js +++ b/src/electron/ipc-api/appIndicator.js @@ -1,12 +1,11 @@ -import { app, ipcMain, Tray, Menu } from 'electron'; +import { app, ipcMain } from 'electron'; import path from 'path'; +import { autorun } from 'mobx'; -const INDICATOR_TRAY_PLAIN = 'tray'; -const INDICATOR_TRAY_UNREAD = 'tray-unread'; const INDICATOR_TASKBAR = 'taskbar'; - const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; -let trayIcon; + +let isTrayIconEnabled; function getAsset(type, asset) { return path.join( @@ -15,26 +14,14 @@ function getAsset(type, asset) { } export default (params) => { - trayIcon = new Tray(getAsset('tray', INDICATOR_TRAY_PLAIN)); - const trayMenuTemplate = [ - { - label: 'Show Franz', - click() { - params.mainWindow.show(); - }, - }, { - label: 'Quit Franz', - click() { - app.quit(); - }, - }, - ]; - - const trayMenu = Menu.buildFromTemplate(trayMenuTemplate); - trayIcon.setContextMenu(trayMenu); + autorun(() => { + isTrayIconEnabled = params.settings.get('enableSystemTray'); - trayIcon.on('click', () => { - params.mainWindow.show(); + if (!isTrayIconEnabled) { + params.trayIcon.hide(); + } else if (isTrayIconEnabled) { + params.trayIcon.show(); + } }); ipcMain.on('updateAppIndicator', (event, args) => { @@ -68,13 +55,7 @@ export default (params) => { } } - // Update system tray - trayIcon.setImage(getAsset('tray', args.indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN)); - - if (process.platform === 'darwin') { - trayIcon.setPressedImage( - getAsset('tray', `${args.indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN}-active`), - ); - } + // Update Tray + params.trayIcon.setIndicator(args.indicator); }); }; diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 194b8047c..b9ed51b83 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -126,6 +126,7 @@ "settings.app.updateStatusUpToDate": "You are using the latest version of Franz", "settings.app.form.autoLaunchOnStart": "Launch Franz on start", "settings.app.form.autoLaunchInBackground": "Open in background", + "settings.app.form.enableSystemTray": "Show Franz in system tray", "settings.app.form.minimizeToSystemTray": "Minimize Franz to system tray", "settings.app.form.runInBackground": "Keep Franz in background when closing the window", "settings.app.form.language": "Language", diff --git a/src/index.js b/src/index.js index 3244c44ad..6f45d95b8 100644 --- a/src/index.js +++ b/src/index.js @@ -2,16 +2,18 @@ import { app, BrowserWindow, shell } from 'electron'; import fs from 'fs-extra'; import path from 'path'; -// eslint-disable-next-line +/* eslint-disable */ if (require('electron-squirrel-startup')) app.quit(); -import windowStateKeeper from 'electron-window-state'; // eslint-disable-line +import windowStateKeeper from 'electron-window-state'; -import { isDevMode, isWindows } from './environment'; // eslint-disable-line -import ipcApi from './electron/ipc-api'; // eslint-disable-line -import Settings from './electron/Settings'; // eslint-disable-line -import { appId } from './package.json'; // eslint-disable-line -import './electron/exception'; // eslint-disable-line +import { isDevMode, isWindows } from './environment'; +import ipcApi from './electron/ipc-api'; +import Tray from './lib/Tray'; +import Settings from './electron/Settings'; +import { appId } from './package.json'; +import './electron/exception'; +/* eslint-enable */ // 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. @@ -47,8 +49,11 @@ const createWindow = async () => { autoHideMenuBar: true, }); + // Initialize System Tray + const trayIcon = new Tray(mainWindow); + // Initialize ipcApi - ipcApi({ mainWindow, settings }); + ipcApi({ mainWindow, settings, trayIcon }); // Manage Window State mainWindowState.manage(mainWindow); @@ -102,6 +107,10 @@ const createWindow = async () => { if (app.wasMaximized) { mainWindow.maximize(); } + + if (!settings.get('enableSystemTray')) { + trayIcon.hide(); + } }); mainWindow.on('show', () => { diff --git a/src/lib/Tray.js b/src/lib/Tray.js new file mode 100644 index 000000000..631342b24 --- /dev/null +++ b/src/lib/Tray.js @@ -0,0 +1,64 @@ +import { app, Tray, Menu } from 'electron'; +import path from 'path'; + +const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; +const INDICATOR_TRAY_PLAIN = 'tray'; +const INDICATOR_TRAY_UNREAD = 'tray-unread'; + +function getAsset(type, asset) { + return path.join( + __dirname, '..', 'assets', 'images', type, process.platform, `${asset}.${FILE_EXTENSION}`, + ); +} + +export default class TrayIcon { + mainWindow = null; + trayIcon = null; + + constructor(mainWindow) { + this.mainWindow = mainWindow; + } + + show() { + this.trayIcon = new Tray(getAsset('tray', INDICATOR_TRAY_PLAIN)); + const trayMenuTemplate = [ + { + label: 'Show Franz', + click() { + this.mainWindow.show(); + }, + }, { + label: 'Quit Franz', + click() { + app.quit(); + }, + }, + ]; + + const trayMenu = Menu.buildFromTemplate(trayMenuTemplate); + this.trayIcon.setContextMenu(trayMenu); + + this.trayIcon.on('click', () => { + this.mainWindow.show(); + }); + } + + hide() { + if (this.trayIcon) { + this.trayIcon.destroy(); + this.trayIcon = null; + } + } + + setIndicator(indicator) { + if (!this.trayIcon) return; + + this.trayIcon.setImage(getAsset('tray', indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN)); + + if (process.platform === 'darwin') { + this.trayIcon.setPressedImage( + getAsset('tray', `${indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN}-active`), + ); + } + } +} -- cgit v1.2.3-70-g09d2 From 9825e2aabceea0c1bc987abb6834051bfc99ba54 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 19 Oct 2017 15:23:02 +0200 Subject: Display system tray icon when minimizing to system tray --- src/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/index.js b/src/index.js index 6f45d95b8..e7fa7da6d 100644 --- a/src/index.js +++ b/src/index.js @@ -90,6 +90,7 @@ const createWindow = async () => { if (settings.get('minimizeToSystemTray')) { mainWindow.setSkipTaskbar(true); + trayIcon.show(); } }); -- cgit v1.2.3-70-g09d2 From e58f5589edeeedfbd0a4fd9a6e6de94d472be24d Mon Sep 17 00:00:00 2001 From: Gustavo Sampaio Date: Thu, 19 Oct 2017 22:22:10 -0300 Subject: Add tab cycling with ctrl[+shift]+tab or ctrl+[pageup|pagedown] This is related to #35 --- src/actions/service.js | 2 ++ src/stores/AppStore.js | 12 ++++++++++++ src/stores/ServicesStore.js | 24 ++++++++++++++++++++++++ 3 files changed, 38 insertions(+) (limited to 'src') diff --git a/src/actions/service.js b/src/actions/service.js index 7f429ca32..cdd4bbf16 100644 --- a/src/actions/service.js +++ b/src/actions/service.js @@ -4,6 +4,8 @@ export default { setActive: { serviceId: PropTypes.string.isRequired, }, + setActiveNext: {}, + setActivePrev: {}, showAddServiceInterface: { recipeId: PropTypes.string.isRequired, }, diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index a5e0839f2..42ec25204 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -125,6 +125,18 @@ export default class AppStore extends Store { this.actions.service.openDevToolsForActiveService(); }); + // Set active the next service + key( + '⌘+pagedown, ctrl+pagedown, ⌘+shift+tab, ctrl+shift+tab', () => { + this.actions.service.setActiveNext(); + }); + + // Set active the prev service + key( + '⌘+pageup, ctrl+pageup, ⌘+tab, ctrl+tab', () => { + this.actions.service.setActivePrev(); + }); + this.locale = this._getDefaultLocale(); this._healthCheck(); diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 77d2e7da4..823540076 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -24,6 +24,8 @@ export default class ServicesStore extends Store { // Register action handlers this.actions.service.setActive.listen(this._setActive.bind(this)); + this.actions.service.setActiveNext.listen(this._setActiveNext.bind(this)); + this.actions.service.setActivePrev.listen(this._setActivePrev.bind(this)); this.actions.service.showAddServiceInterface.listen(this._showAddServiceInterface.bind(this)); this.actions.service.createService.listen(this._createService.bind(this)); this.actions.service.createFromLegacyService.listen(this._createFromLegacyService.bind(this)); @@ -206,6 +208,24 @@ export default class ServicesStore extends Store { service.isActive = true; } + @action _setActiveNext() { + const nextIndex = this._wrapIndex(this.all.findIndex(service => service.isActive), 1, this.all.length); + + this.all.forEach((s, index) => { + this.all[index].isActive = false; + }); + this.all[nextIndex].isActive = true; + } + + @action _setActivePrev() { + const prevIndex = this._wrapIndex(this.all.findIndex(service => service.isActive), -1, this.all.length); + + this.all.forEach((s, index) => { + this.all[index].isActive = false; + }); + this.all[prevIndex].isActive = true; + } + @action _setUnreadMessageCount({ serviceId, count }) { const service = this.one(serviceId); @@ -500,4 +520,8 @@ export default class ServicesStore extends Store { _reorderAnalytics = debounce(() => { gaEvent('Service', 'order'); }, 5000); + + _wrapIndex(index, delta, size) { + return (((index + delta) % size) + size) % size; + } } -- cgit v1.2.3-70-g09d2 From 6624824fa90415ba5ee0f3272aa82a371566c5cf Mon Sep 17 00:00:00 2001 From: Gustavo Sampaio Date: Fri, 20 Oct 2017 08:29:46 -0300 Subject: Bugfix: Ignore disabled services --- src/stores/ServicesStore.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 823540076..19db05494 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -209,21 +209,21 @@ export default class ServicesStore extends Store { } @action _setActiveNext() { - const nextIndex = this._wrapIndex(this.all.findIndex(service => service.isActive), 1, this.all.length); + const nextIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), 1, this.enabled.length); this.all.forEach((s, index) => { this.all[index].isActive = false; }); - this.all[nextIndex].isActive = true; + this.enabled[nextIndex].isActive = true; } @action _setActivePrev() { - const prevIndex = this._wrapIndex(this.all.findIndex(service => service.isActive), -1, this.all.length); + const prevIndex = this._wrapIndex(this.enabled.findIndex(service => service.isActive), -1, this.enabled.length); this.all.forEach((s, index) => { this.all[index].isActive = false; }); - this.all[prevIndex].isActive = true; + this.enabled[prevIndex].isActive = true; } @action _setUnreadMessageCount({ serviceId, count }) { -- cgit v1.2.3-70-g09d2