diff --git a/add-on/icons/png/ipfs-logo-off_128.png b/add-on/icons/png/ipfs-logo-off_128.png new file mode 100644 index 000000000..defd45354 Binary files /dev/null and b/add-on/icons/png/ipfs-logo-off_128.png differ diff --git a/add-on/icons/png/ipfs-logo-off_19.png b/add-on/icons/png/ipfs-logo-off_19.png new file mode 100644 index 000000000..99b22f31d Binary files /dev/null and b/add-on/icons/png/ipfs-logo-off_19.png differ diff --git a/add-on/icons/png/ipfs-logo-off_38.png b/add-on/icons/png/ipfs-logo-off_38.png new file mode 100644 index 000000000..d0b95b131 Binary files /dev/null and b/add-on/icons/png/ipfs-logo-off_38.png differ diff --git a/add-on/icons/png/ipfs-logo-on_128.png b/add-on/icons/png/ipfs-logo-on_128.png new file mode 100644 index 000000000..26917bed9 Binary files /dev/null and b/add-on/icons/png/ipfs-logo-on_128.png differ diff --git a/add-on/icons/png/ipfs-logo-on_19.png b/add-on/icons/png/ipfs-logo-on_19.png new file mode 100644 index 000000000..859bcac47 Binary files /dev/null and b/add-on/icons/png/ipfs-logo-on_19.png differ diff --git a/add-on/icons/png/ipfs-logo-on_38.png b/add-on/icons/png/ipfs-logo-on_38.png new file mode 100644 index 000000000..921556d06 Binary files /dev/null and b/add-on/icons/png/ipfs-logo-on_38.png differ diff --git a/add-on/manifest.json b/add-on/manifest.json index a161daacf..340123c0d 100644 --- a/add-on/manifest.json +++ b/add-on/manifest.json @@ -8,7 +8,9 @@ "homepage_url": "https://github.com/lidel/ipfs-firefox-addon", "author": "Marcin Rataj", "icons": { - "48": "icons/ipfs-logo-on.svg" + "19": "icons/png/ipfs-logo-on_19.png", + "38": "icons/png/ipfs-logo-on_38.png", + "128": "icons/png/ipfs-logo-on_128.png" }, "applications": { "gecko": { @@ -37,7 +39,11 @@ "browser_action": { "browser_style": true, - "default_icon": "icons/ipfs-logo-off.svg", + "default_icon": { + "19": "icons/png/ipfs-logo-off_19.png", + "38": "icons/png/ipfs-logo-off_38.png", + "128": "icons/png/ipfs-logo-off_128.png" + }, "default_title": "__MSG_browserAction_title__", "default_popup": "src/popup/browser-action.html" }, diff --git a/add-on/src/lib/common.js b/add-on/src/lib/common.js index 03230dc6b..d5ba65661 100644 --- a/add-on/src/lib/common.js +++ b/add-on/src/lib/common.js @@ -368,13 +368,15 @@ function createIpfsApiStatusUpdateAlarm (ipfsApiPollMs) { return browser.alarms.create(ipfsApiStatusUpdateAlarm, { when, periodInMinutes }) } -function updateBrowserActionBadge () { +async function updateBrowserActionBadge () { let badgeText, badgeColor, badgeIcon badgeText = state.peerCount.toString() if (state.peerCount > 0) { + // All is good (online with peers) badgeColor = '#418B8E' badgeIcon = '/icons/ipfs-logo-on.svg' } else if (state.peerCount === 0) { + // API is online but no peers badgeColor = 'red' badgeIcon = '/icons/ipfs-logo-on.svg' } else { @@ -383,21 +385,60 @@ function updateBrowserActionBadge () { badgeColor = '#8C8C8C' badgeIcon = '/icons/ipfs-logo-off.svg' } - setBrowserActionBadge(badgeText, badgeColor, badgeIcon) + try { + await browser.browserAction.setBadgeBackgroundColor({color: badgeColor}) + await browser.browserAction.setBadgeText({text: badgeText}) + await setBrowserActionIcon(badgeIcon) + } catch (error) { + console.error('Unable to update browserAction badge due to error', error) + } } -async function setBrowserActionBadge (text, color, icon) { +async function setBrowserActionIcon (iconPath) { + let iconDefinition = {path: iconPath} try { - await Promise.all([ - browser.browserAction.setBadgeBackgroundColor({color: color}), - browser.browserAction.setBadgeText({text: text}), - browser.browserAction.setIcon({path: icon}) - ]) + // Try SVG first -- Firefox supports it natively + await browser.browserAction.setIcon(iconDefinition) } catch (error) { - console.error('Unable to update browserAction badge due to error', error) + // Fallback! + // Chromium does not support SVG [ticket below is 8 years old, I can't even..] + // https://bugs.chromium.org/p/chromium/issues/detail?id=29683 + // Still, we want icon, so we precompute rasters of popular sizes and use them instead + await browser.browserAction.setIcon(rasterIconDefinition(iconPath)) + } +} + +function rasterIconDefinition (svgPath) { + // icon sizes to cover ranges from: + // - https://bugs.chromium.org/p/chromium/issues/detail?id=647182 + // - https://developer.chrome.com/extensions/manifest/icons + return { + 'path': { + '19': rasterIconPath(svgPath, 19), + '38': rasterIconPath(svgPath, 38), + '128': rasterIconPath(svgPath, 128) + } } } +function rasterIconPath (iconPath, size) { + // point at precomputed PNG file + let baseName = /\/icons\/(.+)\.svg/.exec(iconPath)[1] + return `/icons/png/${baseName}_${size}.png` +} + +/* Easter-Egg: PoC that generates raster on the fly ;-) +function rasterIconData (iconPath, size) { + let icon = new Image() + icon.src = iconPath + let canvas = document.createElement('canvas') + let context = canvas.getContext('2d') + context.clearRect(0, 0, size, size) + context.drawImage(icon, 0, 0, size, size) + return context.getImageData(0, 0, size, size) +} +*/ + // OPTIONS // =================================================================== diff --git a/generate-png-icons.sh b/generate-png-icons.sh new file mode 100755 index 000000000..8abc5d854 --- /dev/null +++ b/generate-png-icons.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +for svg in add-on/icons/*.svg; do + for size in 19 38 128; do + png=add-on/icons/png/$(basename -s .svg ${svg})_${size}.png + inkscape -z -e $png -w $size -h $size $svg + optipng -o7 -i0 $png + done +done diff --git a/test/unit/00-init.test.js b/test/unit/00-init.test.js index 6ef4f0a35..2ee589fbb 100644 --- a/test/unit/00-init.test.js +++ b/test/unit/00-init.test.js @@ -1,6 +1,6 @@ 'use strict' /* eslint-env webextensions, mocha */ -/* globals sinon, init, URL, IpfsApi, onStorageChange, storeMissingOptions, optionDefaults, setBrowserActionBadge */ +/* globals sinon, init, URL, IpfsApi, onStorageChange, storeMissingOptions, optionDefaults */ var sandbox @@ -118,32 +118,4 @@ describe('init.js', function () { }) }) - describe('setBrowserActionBadge()', function () { - it('should update text, color and icon of Browser Action button', done => { - setBrowserActionBadge('text', 'yellow', 'icon.svg') - .then(() => { - sinon.assert.calledWith(browser.browserAction.setBadgeText, {text: 'text'}) - sinon.assert.calledWith(browser.browserAction.setBadgeBackgroundColor, {color: 'yellow'}) - sinon.assert.calledWith(browser.browserAction.setIcon, {path: 'icon.svg'}) - done() - }) - .catch(error => { done(error) }) - }) - }) - - /* TODO :-) - describe('updateIpfsApiStatus', function () { - it('should update Browser Action button if API is offline', done => { - sandbox.stub(window, 'setBrowserActionBadge') - //sandbox.stub(ipfs.swarm, 'peers').returns(Promise.resolve([{}, {}, {}, {}])) - updateIpfsApiStatus() - .then(() => { - sinon.assert.calledWith(browser.browserAction.setBadgeText, {text: '4'}) - sinon.assert.calledWith(setBrowserActionBadge, '4', 'red', 'foo') - done() - }) - .catch(error => { done(error) }) - }) - }) - */ })