-
Notifications
You must be signed in to change notification settings - Fork 715
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add new tray icons for MacOS * Add new tray icons for Linux * Add new tray icons for Windows * Remove option to show user status in tray icon * Remove old icon module * Don't use gulp to update icons * Optimize tray icons * Refactor icon module * Build app icons * Refactor and test icon module * Fix Windows icons
- Loading branch information
Showing
106 changed files
with
2,228 additions
and
250 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
'use strict'; | ||
|
||
require('./tasks/build-app'); | ||
require('./tasks/build-tests'); | ||
require('./tasks/release'); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,121 +1,71 @@ | ||
import { BrowserWindow, nativeImage } from 'electron'; | ||
import jetpack from 'fs-jetpack'; | ||
import { whenReadyToShow } from './utils'; | ||
import { nativeImage, systemPreferences } from 'electron'; | ||
|
||
let rendererWindow = null; | ||
|
||
const getRendererWindow = async() => { | ||
if (!rendererWindow) { | ||
rendererWindow = new BrowserWindow({ show: false }); | ||
|
||
const dataURL = `data:text/html,<!doctype html> | ||
${ jetpack.read(`${ __dirname }/public/images/icon.svg`) }`; | ||
|
||
rendererWindow.loadURL(dataURL); | ||
await whenReadyToShow(rendererWindow); | ||
function getTrayIconSet({ platform, dark }) { | ||
if (platform === 'darwin') { | ||
return `darwin${ dark ? '-dark' : '' }`; | ||
} | ||
|
||
return rendererWindow; | ||
}; | ||
|
||
/* istanbul ignore next */ | ||
const renderInWindow = async(style) => { | ||
const statusColors = { | ||
offline: null, | ||
away: 'yellow', | ||
busy: 'red', | ||
online: 'lime', | ||
}; | ||
|
||
const create = ({ overlay, template, status, badgeText } = {}) => { | ||
const svg = document.querySelector('#icon').cloneNode(true); | ||
|
||
svg.querySelector('.logo .baloon').style.fill = template ? '#FFFFFF' : '#DB2323'; | ||
svg.querySelector('.logo .circles').style.fill = template ? '#FFFFFF' : '#DB2323'; | ||
svg.querySelector('.status .away').style.fill = template ? '#FFFFFF' : '#DB2323'; | ||
svg.querySelector('.status .busy').style.fill = template ? '#FFFFFF' : '#DB2323'; | ||
|
||
svg.querySelector('.logo .bubble').style.display = template ? 'none' : null; | ||
|
||
svg.querySelector('.badge').style.display = (!template && badgeText) ? null : 'none'; | ||
svg.querySelector('.badge text').innerHTML = badgeText; | ||
|
||
svg.querySelector('.logo .circles').style.display = (template && status && status !== 'online') ? 'none' : ''; | ||
svg.querySelector('.status circle').style.display = (template || !status) ? 'none' : null; | ||
svg.querySelector('.status .away').style.display = (template && status === 'away') ? null : 'none'; | ||
svg.querySelector('.status .busy').style.display = (template && status === 'busy') ? null : 'none'; | ||
svg.querySelector('.status circle').style.fill = statusColors[status]; | ||
return platform; | ||
} | ||
|
||
if (overlay) { | ||
const overlaySVG = svg.cloneNode(true); | ||
svg.remove(); | ||
|
||
overlaySVG.querySelector('.logo').remove(); | ||
overlaySVG.querySelector('.status').remove(); | ||
overlaySVG.setAttribute('viewBox', '96 -32 160 160'); | ||
|
||
return overlaySVG; | ||
} | ||
|
||
return svg; | ||
}; | ||
|
||
const rasterize = async(svg, size) => { | ||
const image = new Image(); | ||
image.src = `data:image/svg+xml,${ encodeURIComponent(svg.outerHTML) }`; | ||
image.width = image.height = size; | ||
await new Promise((resolve, reject) => { | ||
image.onload = resolve; | ||
image.onerror = reject; | ||
}); | ||
function getTrayIconName({ title, count, platform }) { | ||
if (platform === 'darwin') { | ||
return (title || count) ? 'notification' : 'default'; | ||
} | ||
|
||
const canvas = document.createElement('canvas'); | ||
canvas.width = canvas.height = size; | ||
if (title === '•') { | ||
return 'notification-dot'; | ||
} else if (count > 0) { | ||
return count > 9 ? 'notification-plus-9' : `notification-${ String(count) }`; | ||
} | ||
|
||
const ctx = canvas.getContext('2d'); | ||
ctx.drawImage(image, 0, 0); | ||
return 'default'; | ||
} | ||
|
||
return canvas.toDataURL('image/png'); | ||
}; | ||
function getTrayIconExtension({ platform }) { | ||
if (platform === 'win32') { | ||
return 'ico'; | ||
} | ||
|
||
const svg = create(style); | ||
const pixelRatio = window.devicePixelRatio; | ||
const sizes = Array.isArray(style.size) ? style.size : [style.size || 256]; | ||
const images = await Promise.all(sizes.map(async(size) => ({ | ||
dataURL: await rasterize(svg, size * pixelRatio), | ||
size, | ||
pixelRatio, | ||
}))); | ||
svg.remove(); | ||
return images; | ||
}; | ||
return 'png'; | ||
} | ||
|
||
const render = async(style = {}) => { | ||
const encodedArgs = JSON.stringify(style); | ||
render.cache = render.cache || []; | ||
export function getAppIconPath() { | ||
return 'public/images/icon.png'; | ||
} | ||
|
||
if (render.cache[encodedArgs]) { | ||
return render.cache[encodedArgs]; | ||
export function getTrayIconPath({ title, count, platform, dark } = {}) { | ||
if (typeof platform === 'undefined') { | ||
platform = process.platform; | ||
} | ||
|
||
const rendererWindow = await getRendererWindow(); | ||
const jsCode = `(${ renderInWindow.toString() })(${ encodedArgs })`; | ||
const images = await rendererWindow.webContents.executeJavaScript(jsCode); | ||
const image = nativeImage.createEmpty(); | ||
for (const { dataURL, size, pixelRatio } of images) { | ||
image.addRepresentation({ | ||
scaleFactor: pixelRatio, | ||
width: size, | ||
height: size, | ||
dataURL, | ||
}); | ||
if (platform === 'darwin' && typeof dark === 'undefined') { | ||
dark = systemPreferences.isDarkMode(); | ||
} | ||
image.setTemplateImage(style.template || false); | ||
render.cache[encodedArgs] = image; | ||
|
||
return image; | ||
}; | ||
|
||
export default { | ||
render, | ||
}; | ||
const params = { title, count, platform, dark }; | ||
const iconset = getTrayIconSet(params); | ||
const name = getTrayIconName(params); | ||
const extension = getTrayIconExtension(params); | ||
return `public/images/tray/${ iconset }/${ name }.${ extension }`; | ||
} | ||
|
||
export function getAppIconImage() { | ||
return nativeImage.createFromPath(`${ __dirname }/${ getAppIconPath() }`); | ||
} | ||
|
||
export function getTrayIconImage({ title, count, platform, dark } = {}) { | ||
return nativeImage.createFromPath(`${ __dirname }/${ getTrayIconPath({ title, count, platform, dark }) }`); | ||
} | ||
|
||
export function getIconImage({ badge: { title, count } }) { | ||
const iconsetsPath = `${ __dirname }/public/images/tray`; | ||
const { platform } = process; | ||
const dark = systemPreferences.isDarkMode(); | ||
const params = { title, count, platform, dark }; | ||
const iconset = getTrayIconSet(params); | ||
const name = getTrayIconName(params); | ||
const extension = getTrayIconExtension(params); | ||
return nativeImage.createFromPath(`${ iconsetsPath }/${ iconset }/${ name }.${ extension }`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { expect } from 'chai'; | ||
import { describe, it } from 'mocha'; | ||
import { getAppIconPath, getTrayIconPath, getAppIconImage, getTrayIconImage } from './icon'; | ||
|
||
describe('icon', () => { | ||
|
||
describe('paths', () => { | ||
it('app', () => { | ||
expect(getAppIconPath()).to.be.equals('public/images/icon.png'); | ||
}); | ||
|
||
describe('tray', () => { | ||
|
||
it('darwin', () => { | ||
|
||
expect(getTrayIconPath({ platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/default.png'); | ||
expect(getTrayIconPath({ title: '•', platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 1, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 2, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 3, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 4, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 5, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 6, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 7, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 8, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 9, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
expect(getTrayIconPath({ count: 10, platform: 'darwin', dark: false })).to.be.equals('public/images/tray/darwin/notification.png'); | ||
}); | ||
|
||
it('darwin-dark', () => { | ||
|
||
expect(getTrayIconPath({ platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/default.png'); | ||
expect(getTrayIconPath({ title: '•', platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 1, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 2, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 3, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 4, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 5, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 6, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 7, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 8, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 9, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
expect(getTrayIconPath({ count: 10, platform: 'darwin', dark: true })).to.be.equals('public/images/tray/darwin-dark/notification.png'); | ||
}); | ||
|
||
it('linux', () => { | ||
|
||
expect(getTrayIconPath({ platform: 'linux' })).to.be.equals('public/images/tray/linux/default.png'); | ||
expect(getTrayIconPath({ title: '•', platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-dot.png'); | ||
expect(getTrayIconPath({ count: 1, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-1.png'); | ||
expect(getTrayIconPath({ count: 2, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-2.png'); | ||
expect(getTrayIconPath({ count: 3, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-3.png'); | ||
expect(getTrayIconPath({ count: 4, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-4.png'); | ||
expect(getTrayIconPath({ count: 5, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-5.png'); | ||
expect(getTrayIconPath({ count: 6, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-6.png'); | ||
expect(getTrayIconPath({ count: 7, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-7.png'); | ||
expect(getTrayIconPath({ count: 8, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-8.png'); | ||
expect(getTrayIconPath({ count: 9, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-9.png'); | ||
expect(getTrayIconPath({ count: 10, platform: 'linux' })).to.be.equals('public/images/tray/linux/notification-plus-9.png'); | ||
}); | ||
|
||
it('win32', () => { | ||
|
||
expect(getTrayIconPath({ platform: 'win32' })).to.be.equals('public/images/tray/win32/default.ico'); | ||
expect(getTrayIconPath({ title: '•', platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-dot.ico'); | ||
expect(getTrayIconPath({ count: 1, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-1.ico'); | ||
expect(getTrayIconPath({ count: 2, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-2.ico'); | ||
expect(getTrayIconPath({ count: 3, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-3.ico'); | ||
expect(getTrayIconPath({ count: 4, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-4.ico'); | ||
expect(getTrayIconPath({ count: 5, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-5.ico'); | ||
expect(getTrayIconPath({ count: 6, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-6.ico'); | ||
expect(getTrayIconPath({ count: 7, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-7.ico'); | ||
expect(getTrayIconPath({ count: 8, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-8.ico'); | ||
expect(getTrayIconPath({ count: 9, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-9.ico'); | ||
expect(getTrayIconPath({ count: 10, platform: 'win32' })).to.be.equals('public/images/tray/win32/notification-plus-9.ico'); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('image', () => { | ||
expect(getAppIconImage()).to.not.be.null; | ||
expect(getTrayIconImage()).to.not.be.null; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.