Skip to content

Commit

Permalink
fix: avoid internal requests for action icons (#788)
Browse files Browse the repository at this point in the history
This change checks if icon changed, and sets it only when it is needed,
removing overhead of redraw and internal requests.

Context: every time peer count was updated, the browser action icon got set,
which caused unnecessary  internal request for PNG assets on Chrome.
Chrome does not support SVG in browser action, so we also had to compute
the path of PNG (it is now memoized).
  • Loading branch information
lidel committed Oct 11, 2019
1 parent e037f0a commit 7b84a06
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 29 deletions.
79 changes: 51 additions & 28 deletions add-on/src/lib/ipfs-companion.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ log.error = debug('ipfs-companion:main:error')

const browser = require('webextension-polyfill')
const toMultiaddr = require('uri-to-multiaddr')
const pMemoize = require('p-memoize')
const { optionDefaults, storeMissingOptions, migrateOptions } = require('./options')
const { initState, offlinePeerCount } = require('./state')
const { createIpfsPathValidator } = require('./ipfs-path')
Expand Down Expand Up @@ -526,9 +527,13 @@ module.exports = async function init () {
badgeIcon = '/icons/ipfs-logo-off.svg'
}
try {
await browser.browserAction.setBadgeBackgroundColor({ color: badgeColor })
await browser.browserAction.setBadgeText({ text: badgeText })
await setBrowserActionIcon(badgeIcon)
const oldColor = colorArraytoHex(await browser.browserAction.getBadgeBackgroundColor({}))
if (badgeColor !== oldColor) {
await browser.browserAction.setBadgeBackgroundColor({ color: badgeColor })
await setBrowserActionIcon(badgeIcon)
}
const oldText = await browser.browserAction.getBadgeText({})
if (oldText !== badgeText) await browser.browserAction.setBadgeText({ text: badgeText })
} catch (error) {
console.error('Unable to update browserAction badge due to error', error)
}
Expand All @@ -548,35 +553,53 @@ module.exports = async function init () {
}
}

function rasterIconDefinition (svgPath) {
// ColorArray [0,0,0,0] → Hex #000000
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction/ColorArray
function colorArraytoHex (colorArray) {
if (!colorArray) return ''
const colorAt = i => colorArray[i].toString(16).padStart(2, '0')
const r = colorAt(0)
const g = colorAt(1)
const b = colorAt(2)
return ('#' + r + g + b).toUpperCase()
}

const rasterIconDefinition = pMemoize((svgPath) => {
const pngPath = (size) => {
// point at precomputed PNG file
const baseName = /\/icons\/(.+)\.svg/.exec(svgPath)[1]
return `/icons/png/${baseName}_${size}.png`
}
// 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)
}
const r19 = pngPath(19)
const r38 = pngPath(38)
const r128 = pngPath(128)
// return computed values to be cached by p-memoize
return { path: { 19: r19, 38: r38, 128: r128 } }
})

/* Alternative: raster images generated on the fly
const rasterIconDefinition = pMemoize((svgPath) => {
const rasterData = (size) => {
const icon = new Image()
icon.src = svgPath
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
context.clearRect(0, 0, size, size)
context.drawImage(icon, 0, 0, size, size)
return context.getImageData(0, 0, size, size)
}
}

function rasterIconPath (iconPath, size) {
// point at precomputed PNG file
const 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)
}
// icon sizes to cover ranges from:
// - https://bugs.chromium.org/p/chromium/issues/detail?id=647182
// - https://developer.chrome.com/extensions/manifest/icons
const r19 = rasterData(19)
const r38 = rasterData(38)
const r128 = rasterData(128)
// return computed values to be cached by p-memoize
return { imageData: { 19: r19, 38: r38, 128: r128 } }
})
*/

// OPTIONS
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
"mime-types": "2.1.24",
"multiaddr": "7.1.0",
"multiaddr-to-uri": "5.0.0",
"p-memoize": "3.1.0",
"p-queue": "6.1.1",
"path-browserify": "1.0.0",
"piggybacker": "2.0.0",
Expand Down
10 changes: 9 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9643,7 +9643,7 @@ mem-storage-area@1.0.3:
resolved "https://registry.yarnpkg.com/mem-storage-area/-/mem-storage-area-1.0.3.tgz#a8a9bc75eaf5ae69efe185fedd475fb731d14880"
integrity sha512-UwDsIj6Fmml8NPiPp7QGJavwZVbXMFLvVDfshv3486KQHDcxOExr0od4YkUdJVWFlujZxtct59mEtsPvAQTOMQ==

mem@^4.0.0:
mem@^4.0.0, mem@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
Expand Down Expand Up @@ -11173,6 +11173,14 @@ p-map@^3.0.0:
dependencies:
aggregate-error "^3.0.0"

p-memoize@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-memoize/-/p-memoize-3.1.0.tgz#ac7587983c9e530139f969ca7b41ef40e93659aa"
integrity sha512-e5tIvrsr7ydUUnxb534iQWtXxWgk/86IsH+H+nV4FHouIggBt4coXboKBt26o4lTu7JbEnGSeXdEsYR8BhAHFA==
dependencies:
mem "^4.3.0"
mimic-fn "^2.1.0"

p-queue@6.1.1, p-queue@^6.0.0:
version "6.1.1"
resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.1.1.tgz#eedbaf7335b4931ef857e2e58063fed461b97e80"
Expand Down

0 comments on commit 7b84a06

Please sign in to comment.