Skip to content

Commit

Permalink
Merge pull request chrisknepper#25 from chrisknepper/feature/mac-noti…
Browse files Browse the repository at this point in the history
…fication-badges-and-windows-tray-support

Feature/mac notification badges and windows tray support
  • Loading branch information
chrisknepper authored Jun 28, 2018
2 parents 1980680 + 810dc5b commit 2e9904c
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 53 deletions.
44 changes: 34 additions & 10 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,62 @@ import './stylesheets/main.css';
import './helpers/context_menu.js';
import './helpers/external_links.js';

const state = {
loaded: false
};

import { remote, shell } from 'electron';
import url from 'url';
import jetpack from 'fs-jetpack';
import { IS_MAC } from './constants';

const state = {
loaded: false,
unreadNotificationCount: 0
};

const app = remote.app;
const appDir = jetpack.cwd(app.getAppPath());

// TODO: Insert or update webview here instead of in the HTML file to make testing (swapping URLs) easier

androidMessagesWebview.addEventListener('did-start-loading', () => {

// Intercept request for notifications and accept it
androidMessagesWebview.getWebContents().session.setPermissionRequestHandler((webContents, permission, callback) => {
const url = webContents.getURL()


if (permission === 'notifications') {
/*
* We always get a "notification" in dev mode when the app starts due to calling setPermissionRequestHandler,
* which accepts the permission to send browser notifications on behalf of the user--this false
* notification should not result in an indicator for the user to see.
* TODO: Figure out a way to modify and override notifications to solve this and other issues.
*/
if (IS_MAC) {
if (app.mainWindow && !(app.mainWindow.isFocused())) {
state.unreadNotificationCount += 1;
app.dock.setBadge('' + state.unreadNotificationCount);
}
}

// TODO: Provide visual indicators for Windows/Linux, possibly via mainWindow.setOverlayIcon

return callback(true); // Approve
}

// if (!url.startsWith('https://my-website.com')) {
// return callback(false) // Deny
// }
if (!url.startsWith('https://messages.android.com')) {
return callback(false); // Deny
}
});

if (IS_MAC && app.mainWindow) {
app.mainWindow.on('focus', () => {
state.unreadNotificationCount = 0;
app.dock.setBadge('');
})
}
});

androidMessagesWebview.addEventListener('did-finish-load', () => { // just before onLoad
console.log('finished loading');

});

androidMessagesWebview.addEventListener('did-stop-loading', () => { // coincident with onLoad, can fire multiple times
Expand All @@ -43,7 +67,7 @@ androidMessagesWebview.addEventListener('did-stop-loading', () => { // coinciden
state.loaded = true;
loader.classList.add('hidden');
}

});

androidMessagesWebview.addEventListener('dom-ready', () => {
Expand Down
164 changes: 121 additions & 43 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,142 @@

import path from 'path';
import url from 'url';
import { app, Menu } from 'electron';
import { app, Menu, Tray } from 'electron';
import { autoUpdater } from 'electron-updater';
import { baseMenuTemplate } from './menu/base_menu_template';
import { devMenuTemplate } from './menu/dev_menu_template';
import { helpMenuTemplate } from './menu/help_menu_template';
import createWindow from './helpers/window';
import { IS_WINDOWS } from './constants';
import { IS_MAC, IS_WINDOWS, IS_LINUX, IS_DEV } from './constants';

// Special module holding environment variables which you declared
// in config/env_xxx.json file.
import env from 'env';

const setApplicationMenu = () => {
const menus = baseMenuTemplate;
let mainWindow = null;

// Prevent multiple instances of the app which causes many problems with an app like ours
// Without this, if an instance were minimized to the tray in Windows, clicking a shortcut would launch another instance, icky
// Adapted from https://github.com/electron/electron/blob/v2.0.2/docs/api/app.md#appmakesingleinstancecallback
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, let's show our existing instance instead
if (mainWindow) {
if (!mainWindow.isVisible()) {
mainWindow.show();
}
}
});

if (isSecondInstance) {
app.quit()
} else {
let tray; // Must declare reference to instance of Tray as a variable, not a const, or bad/weird things happen

const setApplicationMenu = () => {
const menus = baseMenuTemplate;
if (env.name !== 'production') {
menus.push(devMenuTemplate);
}
menus.push(helpMenuTemplate);
Menu.setApplicationMenu(Menu.buildFromTemplate(menus));
};

// Save userData in separate folders for each environment.
// Thanks to this you can use production and development versions of the app
// on same machine like those are two separate apps.
if (env.name !== 'production') {
menus.push(devMenuTemplate);
const userDataPath = app.getPath('userData');
app.setPath('userData', `${userDataPath} (${env.name})`);
}
menus.push(helpMenuTemplate);
Menu.setApplicationMenu(Menu.buildFromTemplate(menus));
};

// Save userData in separate folders for each environment.
// Thanks to this you can use production and development versions of the app
// on same machine like those are two separate apps.
if (env.name !== 'production') {
const userDataPath = app.getPath('userData');
app.setPath('userData', `${userDataPath} (${env.name})`);
}

if (IS_WINDOWS) {
// Stupid, DUMB calls that have to be made to let notifications come through on Windows (only Windows 10?)
// See: https://github.com/electron/electron/issues/10864#issuecomment-382519150
app.setAppUserModelId('com.knepper.android-messages-desktop');
app.setAsDefaultProtocolClient('android-messages-desktop');
}
if (IS_WINDOWS) {
// Stupid, DUMB calls that have to be made to let notifications come through on Windows (only Windows 10?)
// See: https://github.com/electron/electron/issues/10864#issuecomment-382519150
app.setAppUserModelId('com.knepper.android-messages-desktop');
app.setAsDefaultProtocolClient('android-messages-desktop');
}

app.on('ready', () => {
setApplicationMenu();
autoUpdater.checkForUpdatesAndNotify();
app.on('ready', () => {
setApplicationMenu();
autoUpdater.checkForUpdatesAndNotify();

const mainWindow = createWindow('main', {
width: 1100,
height: 800
});
mainWindow = createWindow('main', {
width: 1100,
height: 800
});

mainWindow.loadURL(
url.format({
pathname: path.join(__dirname, 'app.html'),
protocol: 'file:',
slashes: true
})
);
mainWindow.loadURL(
url.format({
pathname: path.join(__dirname, 'app.html'),
protocol: 'file:',
slashes: true
})
);

if (env.name === 'development') {
mainWindow.openDevTools();
}
});
app.mainWindow = mainWindow; // Quick and dirty way for renderer process to access mainWindow for communication

app.on('window-all-closed', () => {
app.quit();
});
if (IS_MAC) {
let quitViaContext = false;
app.on('before-quit', () => {
quitViaContext = true;
});

mainWindow.on('close', (event) => {
if (!quitViaContext) {
event.preventDefault();
mainWindow.hide();
}
});

app.on('activate', () => {
mainWindow.show();
});
}

if (IS_WINDOWS) {
mainWindow.on('close', (event) => {
app.quit();
});

tray = new Tray(__dirname + '../../resources/icon.ico');

let contextMenu = Menu.buildFromTemplate([
{
label: 'Show',
click: () => {
mainWindow.show();
}
},
{
label: 'Quit',
click: () => {
app.quit();
}
}
]);

tray.setContextMenu(contextMenu);

tray.on('double-click', (event) => {
event.preventDefault();
mainWindow.show();
});

mainWindow.on('minimize', (event) => {
event.preventDefault();
mainWindow.hide();
});
}

// TODO: Better UX for Linux...likely similar to Windows as far as tray behavior
if (IS_LINUX) {
app.on('window-all-closed', (event) => {
app.quit();
});
}

if (IS_DEV) {
mainWindow.openDevTools();
}
});
}
8 changes: 8 additions & 0 deletions src/menu/app_menu_template.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ export const appMenuTemplate = {
{
type: 'separator',
},
{
label: 'Hide Android Messages Desktop',
accelerator: 'Command+H',
click: () => app.mainWindow && app.mainWindow.hide()
},
{
type: 'separator',
},
{
label: 'Quit',
accelerator: 'Command+Q',
Expand Down

0 comments on commit 2e9904c

Please sign in to comment.