From de2fabf8954d04eece73e5ea93c875dccfd06101 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 17 Nov 2017 12:49:37 +0000 Subject: [PATCH 1/6] adds choo for UI --- add-on/manifest.json | 2 +- add-on/src/popup/browser-action.js | 289 ------------------ .../popup/browser-action/context-actions.js | 49 +++ .../popup/browser-action/gateway-status.js | 46 +++ .../index.html} | 68 +---- add-on/src/popup/browser-action/index.js | 12 + add-on/src/popup/browser-action/operations.js | 51 ++++ add-on/src/popup/browser-action/page.js | 31 ++ add-on/src/popup/browser-action/store.js | 233 ++++++++++++++ add-on/src/popup/quick-upload.html | 8 +- add-on/src/popup/quick-upload.js | 82 ++--- package.json | 5 +- 12 files changed, 479 insertions(+), 397 deletions(-) delete mode 100644 add-on/src/popup/browser-action.js create mode 100644 add-on/src/popup/browser-action/context-actions.js create mode 100644 add-on/src/popup/browser-action/gateway-status.js rename add-on/src/popup/{browser-action.html => browser-action/index.html} (53%) create mode 100644 add-on/src/popup/browser-action/index.js create mode 100644 add-on/src/popup/browser-action/operations.js create mode 100644 add-on/src/popup/browser-action/page.js create mode 100644 add-on/src/popup/browser-action/store.js diff --git a/add-on/manifest.json b/add-on/manifest.json index a960ddf67..04ebc3c15 100644 --- a/add-on/manifest.json +++ b/add-on/manifest.json @@ -46,7 +46,7 @@ "128": "icons/png/ipfs-logo-off_128.png" }, "default_title": "__MSG_browserAction_title__", - "default_popup": "dist/popup/browser-action.html" + "default_popup": "dist/popup/browser-action/index.html" }, "options_ui": { diff --git a/add-on/src/popup/browser-action.js b/add-on/src/popup/browser-action.js deleted file mode 100644 index 8542d0f99..000000000 --- a/add-on/src/popup/browser-action.js +++ /dev/null @@ -1,289 +0,0 @@ -'use strict' -/* eslint-env browser, webextensions */ - -const browser = require('webextension-polyfill') -const translateDataAttrs = require('../lib/data-i18n') - -translateDataAttrs() - -const ipfsContextActions = document.getElementById('ipfs-resource-context-actions') -const pinResourceButton = document.getElementById('pin-current-ipfs-address') -const unpinResourceButton = document.getElementById('unpin-current-ipfs-address') -const copyIpfsAddressButton = document.getElementById('copy-current-ipfs-address') -const copyPublicGwAddressButton = document.getElementById('copy-current-public-gw-url') - -const enableRedirect = document.getElementById('enable-gateway-redirect') -const disableRedirect = document.getElementById('disable-gateway-redirect') -const openWebUI = document.getElementById('open-webui') -const openPreferences = document.getElementById('open-preferences') -const quickUpload = document.getElementById('quick-upload') - -const ipfsIcon = document.getElementById('icon') -const ipfsIconOn = '../../icons/ipfs-logo-on.svg' -const ipfsIconOff = '../../icons/ipfs-logo-off.svg' -const offline = 'offline' - -var port -var state - -function resolv (element) { - // lookup DOM if element is just a string ID - if (Object.prototype.toString.call(element) === '[object String]') { - return document.getElementById(element) - } - // return as-is otherwise - return element -} - -function set (id, value) { - resolv(id).textContent = value -} - -function show (element) { - element = resolv(element) - element.classList.remove('disabled') - element.classList.remove('hidden') -} - -function disable (element) { - resolv(element).classList.add('disabled') -} - -function hide (element) { - resolv(element).classList.add('hidden') -} - -function getBackgroundPage () { - return browser.runtime.getBackgroundPage() -} - -function notify (title, message) { - port.postMessage({event: 'notification', title: title, message: message}) -} - -// Ipfs Context Page Actions -// =================================================================== - -async function copyCurrentPublicGwAddress () { - const bg = await getBackgroundPage() - await bg.copyAddressAtPublicGw() - window.close() -} - -async function copyCurrentCanonicalAddress () { - const bg = await getBackgroundPage() - await bg.copyCanonicalAddress() - window.close() -} - -async function pinCurrentResource () { - deactivatePinButton() - try { - const bg = await getBackgroundPage() - const currentPath = await resolveToIPFS(new URL(state.currentTab.url).pathname) - const pinResult = await bg.ipfs.pin.add(currentPath, { recursive: true }) - console.log('ipfs.pin.add result', pinResult) - notify('notify_pinnedIpfsResourceTitle', currentPath) - } catch (error) { - handlePinError('notify_pinErrorTitle', error) - } - window.close() -} - -async function unpinCurrentResource () { - deactivatePinButton() - try { - const bg = await getBackgroundPage() - const currentPath = await resolveToIPFS(new URL(state.currentTab.url).pathname) - const result = await bg.ipfs.pin.rm(currentPath, {recursive: true}) - console.log('ipfs.pin.rm result', result) - notify('notify_unpinnedIpfsResourceTitle', currentPath) - } catch (error) { - handlePinError('notify_unpinErrorTitle', error) - } - window.close() -} - -function activatePinning () { - pinResourceButton.onclick = pinCurrentResource - show(pinResourceButton) - unpinResourceButton.onclick = undefined - hide(unpinResourceButton) -} - -function activateUnpinning () { - pinResourceButton.onclick = undefined - unpinResourceButton.onclick = unpinCurrentResource - hide(pinResourceButton) - show(unpinResourceButton) -} - -function deactivatePinButton () { - pinResourceButton.onclick = undefined - unpinResourceButton.onclick = undefined - disable(pinResourceButton) - hide(unpinResourceButton) -} - -async function handlePinError (errorMessageKey, error) { - console.error(browser.i18n.getMessage(errorMessageKey), error) - deactivatePinButton() - try { - notify(errorMessageKey, error.message) - } catch (error) { - console.error('unable to access background page', error) - } -} - -async function resolveToIPFS (path) { - const bg = await getBackgroundPage() - path = bg.safeIpfsPath(path) // https://github.com/ipfs/ipfs-companion/issues/303 - if (/^\/ipns/.test(path)) { - const response = await bg.ipfs.name.resolve(path, {recursive: true, nocache: false}) - return response.Path - } - return path -} - -async function activatePinButton () { - try { - const bg = await getBackgroundPage() - const currentPath = await resolveToIPFS(new URL(state.currentTab.url).pathname) - const response = await bg.ipfs.pin.ls(currentPath, {quiet: true}) - console.log(`positive ipfs.pin.ls for ${currentPath}: ${JSON.stringify(response)}`) - activateUnpinning() - } catch (error) { - if (/is not pinned/.test(error.message)) { - console.log(`negative ipfs.pin.ls: ${error} (${JSON.stringify(error)})`) - activatePinning() - } else { - console.error(`unexpected result of ipfs.pin.ls: ${error} (${JSON.stringify(error)})`) - deactivatePinButton() - } - } -} - -async function updatePageActions () { - // IPFS contexts require access to background page - // which is denied in Private Browsing mode - const bg = await getBackgroundPage() - - // Check if current page is an IPFS one - const ipfsContext = bg && state && state.ipfsPageActionsContext - - // There is no point in displaying actions that require API interaction if API is down - const apiIsUp = state && state.peerCount >= 0 - - if (ipfsContext) { - show(ipfsContextActions) - copyPublicGwAddressButton.onclick = copyCurrentPublicGwAddress - copyIpfsAddressButton.onclick = copyCurrentCanonicalAddress - if (apiIsUp) { - activatePinButton() - } else { - deactivatePinButton() - } - } else { - hide(ipfsContextActions) - } -} - -// Global Actions -// =================================================================== - -quickUpload.onclick = () => browser.tabs.create({ url: browser.extension.getURL('dist/popup/quick-upload.html') }) - -enableRedirect.onclick = () => browser.storage.local.set({useCustomGateway: true}) - .then(updateBrowserActionPopup) - .catch(error => { console.error(`Unable to update redirect state due to ${error}`) }) - -disableRedirect.onclick = () => browser.storage.local.set({useCustomGateway: false}) - .then(updateBrowserActionPopup) - .catch(error => { console.error(`Unable to update redirect state due to ${error}`) }) - -openWebUI.onclick = async () => { - try { - const options = await browser.storage.local.get('ipfsApiUrl') - const apiUrl = options['ipfsApiUrl'] - await browser.tabs.create({ url: apiUrl + '/webui/' }) - window.close() - } catch (error) { - console.error(`Unable Open Web UI due to ${error}`) - } -} - -openPreferences.onclick = () => { - browser.runtime.openOptionsPage().then(() => window.close()) -} - -async function updateBrowserActionPopup () { - updatePageActions() - // update redirect status - const options = await browser.storage.local.get() - try { - const enabled = options['useCustomGateway'] - if (enabled) { - hide('redirect-disabled') - hide('enable-gateway-redirect') - show('redirect-enabled') - show('disable-gateway-redirect') - } else { - hide('redirect-enabled') - hide('disable-gateway-redirect') - show('redirect-disabled') - show('enable-gateway-redirect') - } - set('gateway-address-val', options['customGatewayUrl']) - } catch (error) { - console.error(`Unable update redirect state due to ${error}`) - set('gateway-address-val', '???') - } - - if (state) { - // update swarm peer count - const peerCount = state.peerCount - set('swarm-peers-val', peerCount < 0 ? offline : peerCount) - if (peerCount > 0) { - ipfsIcon.src = ipfsIconOn - ipfsIcon.classList.add('online') - } else { - ipfsIcon.src = ipfsIconOff - ipfsIcon.classList.remove('online') - } - if (peerCount > 0) { // API is online & there are peers - show('quick-upload') - } else { - hide('quick-upload') - } - if (peerCount < 0) { // API is offline - hide('open-webui') - } else { - show('open-webui') - } - // update gateway version - set('gateway-version-val', state.gatewayVersion ? state.gatewayVersion : offline) - } -} - -// hide things that cause ugly reflow if removed later -deactivatePinButton() -hide(ipfsContextActions) -hide('quick-upload') -hide('open-webui') - -function onDOMContentLoaded () { - // set up initial layout that will remain if there are no peers - updateBrowserActionPopup() - // initialize connection to the background script which will trigger UI updates - port = browser.runtime.connect({name: 'browser-action-port'}) - port.onMessage.addListener((message) => { - if (message.statusUpdate) { - // console.log('In browser action, received message from background:', message) - state = message.statusUpdate - updateBrowserActionPopup() - } - }) -} - -// init -document.addEventListener('DOMContentLoaded', onDOMContentLoaded) diff --git a/add-on/src/popup/browser-action/context-actions.js b/add-on/src/popup/browser-action/context-actions.js new file mode 100644 index 000000000..877cdbcf7 --- /dev/null +++ b/add-on/src/popup/browser-action/context-actions.js @@ -0,0 +1,49 @@ +'use strict' +/* eslint-env browser, webextensions */ + +const browser = require('webextension-polyfill') +const html = require('choo/html') + +module.exports = function contextActions ({ + hidden, + pinHidden, + pinDisabled, + unPinHidden, + unPinDisabled, + onCopyIpfsAddr, + onCopyPublicGwAddr, + onPin, + onUnPin +}) { + if (hidden) return null + + return html` +
+
+
+
${browser.i18n.getMessage('panelCopy_currentIpfsAddress')}
+
+
+
+
+
${browser.i18n.getMessage('panel_copyCurrentPublicGwUrl')}
+
+
+ ${pinHidden ? null : html` +
+
+
${browser.i18n.getMessage('panel_pinCurrentIpfsAddress')}
+
+
+ `} + ${unPinHidden ? null : html` +
+
+
${browser.i18n.getMessage('panel_unpinCurrentIpfsAddress')}
+
+
+ `} +
+
+ ` +} diff --git a/add-on/src/popup/browser-action/gateway-status.js b/add-on/src/popup/browser-action/gateway-status.js new file mode 100644 index 000000000..ec760d9a6 --- /dev/null +++ b/add-on/src/popup/browser-action/gateway-status.js @@ -0,0 +1,46 @@ +'use strict' +/* eslint-env browser, webextensions */ + +const browser = require('webextension-polyfill') +const html = require('choo/html') + +module.exports = function gatewayStatus ({ + gatewayAddress, + gatewayVersion, + swarmPeers, + ipfsOnline, + redirectEnabled +}) { + return html` +
+ + +
+ ` +} diff --git a/add-on/src/popup/browser-action.html b/add-on/src/popup/browser-action/index.html similarity index 53% rename from add-on/src/popup/browser-action.html rename to add-on/src/popup/browser-action/index.html index 0f0ffff25..d3d18964d 100644 --- a/add-on/src/popup/browser-action.html +++ b/add-on/src/popup/browser-action/index.html @@ -169,72 +169,8 @@ - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
    -
  • unknown
  • -
  • offline
  • -
  • offline
  • -
  • - - - - -
  • -
-
-
- - +
+ diff --git a/add-on/src/popup/browser-action/index.js b/add-on/src/popup/browser-action/index.js new file mode 100644 index 000000000..c32998c8d --- /dev/null +++ b/add-on/src/popup/browser-action/index.js @@ -0,0 +1,12 @@ +'use strict' +/* eslint-env browser, webextensions */ + +const choo = require('choo') +const browserActionPage = require('./page') +const store = require('./store') + +const app = choo() + +app.use(store) +app.route('*', browserActionPage) +app.mount('#root') diff --git a/add-on/src/popup/browser-action/operations.js b/add-on/src/popup/browser-action/operations.js new file mode 100644 index 000000000..7651df224 --- /dev/null +++ b/add-on/src/popup/browser-action/operations.js @@ -0,0 +1,51 @@ +'use strict' +/* eslint-env browser, webextensions */ + +const browser = require('webextension-polyfill') +const html = require('choo/html') + +module.exports = function operations ({ + quickUploadHidden, + openWebUiHidden, + redirectEnabled, + onQuickUpload, + onOpenWebUi, + onOpenPrefs, + onToggleRedirect +}) { + return html` +
+ ${quickUploadHidden ? null : html` +
+
+
${browser.i18n.getMessage('panel_quickUpload')}
+
+
+ `} + ${openWebUiHidden ? null : html` +
+
+
${browser.i18n.getMessage('panel_openWebui')}
+
+
+ `} +
+
+
${browser.i18n.getMessage('panel_openPreferences')}
+
+
+
+
+
+ ${browser.i18n.getMessage( + redirectEnabled + ? 'panel_toggleGatewayRedirectDisable' + : 'panel_toggleGatewayRedirectEnable' + )} +
+
+
+
+
+ ` +} diff --git a/add-on/src/popup/browser-action/page.js b/add-on/src/popup/browser-action/page.js new file mode 100644 index 000000000..c41cd4e59 --- /dev/null +++ b/add-on/src/popup/browser-action/page.js @@ -0,0 +1,31 @@ +'use strict' +/* eslint-env browser, webextensions */ + +const html = require('choo/html') +const contextActions = require('./context-actions') +const operations = require('./operations') +const gatewayStatus = require('./gateway-status') + +module.exports = function browserActionPage (state, emit) { + const onCopyIpfsAddr = () => emit('copyIpfsAddr') + const onCopyPublicGwAddr = () => emit('copyPublicGwAddr') + const onPin = () => emit('pin') + const onUnPin = () => emit('unPin') + + const onQuickUpload = () => emit('quickUpload') + const onOpenWebUi = () => emit('openWebUi') + const onOpenPrefs = () => emit('openPrefs') + const onToggleRedirect = () => emit('toggleRedirect') + + const contextActionsProps = Object.assign({ hidden: state.contextActionsHidden, onCopyIpfsAddr, onCopyPublicGwAddr, onPin, onUnPin }, state) + const opsProps = Object.assign({ onQuickUpload, onOpenWebUi, onOpenPrefs, onToggleRedirect }, state) + const gwStatusProps = Object.assign({}, state) + + return html` +
+ ${contextActions(contextActionsProps)} + ${operations(opsProps)} + ${gatewayStatus(gwStatusProps)} +
+ ` +} diff --git a/add-on/src/popup/browser-action/store.js b/add-on/src/popup/browser-action/store.js new file mode 100644 index 000000000..38f1a346d --- /dev/null +++ b/add-on/src/popup/browser-action/store.js @@ -0,0 +1,233 @@ +'use strict' +/* eslint-env browser, webextensions */ + +const browser = require('webextension-polyfill') + +module.exports = (state, emitter) => { + Object.assign(state, { + // UI state + contextActionsHidden: true, + pinHidden: false, + pinDisabled: true, + unPinHidden: true, + unPinDisabled: false, + quickUploadHidden: true, + openWebUiHidden: true, + currentTabUrl: null, + // IPFS status + ipfsOnline: false, + gatewayAddress: null, + swarmPeers: null, + gatewayVersion: null, + redirectEnabled: false + }) + + let port + + emitter.on('DOMContentLoaded', async () => { + // A short pause allows the popup to animate in without breaking + await new Promise((resolve) => setTimeout(resolve, 100)) + + // initialize connection to the background script which will trigger UI updates + port = browser.runtime.connect({name: 'browser-action-port'}) + port.onMessage.addListener(async (message) => { + if (message.statusUpdate) { + // console.log('In browser action, received message from background:', message) + await updateBrowserActionPopup(message.statusUpdate) + emitter.emit('render') + } + }) + }) + + emitter.on('copyPublicGwAddr', async function copyCurrentPublicGwAddress () { + const bg = await getBackgroundPage() + await bg.copyAddressAtPublicGw() + window.close() + }) + + emitter.on('copyIpfsAddr', async function copyCurrentCanonicalAddress () { + const bg = await getBackgroundPage() + await bg.copyCanonicalAddress() + window.close() + }) + + emitter.on('pin', async function pinCurrentResource () { + deactivatePinButton() + emitter.emit('render') + + try { + const bg = await getBackgroundPage() + const currentPath = await resolveToIPFS(new URL(state.currentTabUrl).pathname) + const pinResult = await bg.ipfs.pin.add(currentPath, { recursive: true }) + console.log('ipfs.pin.add result', pinResult) + notify('notify_pinnedIpfsResourceTitle', currentPath) + } catch (error) { + handlePinError('notify_pinErrorTitle', error) + } + window.close() + }) + + emitter.on('unPin', async function unPinCurrentResource () { + deactivatePinButton() + emitter.emit('render') + + try { + const bg = await getBackgroundPage() + const currentPath = await resolveToIPFS(new URL(state.currentTabUrl).pathname) + const result = await bg.ipfs.pin.rm(currentPath, {recursive: true}) + console.log('ipfs.pin.rm result', result) + notify('notify_unpinnedIpfsResourceTitle', currentPath) + } catch (error) { + handlePinError('notify_unpinErrorTitle', error) + } + window.close() + }) + + async function handlePinError (errorMessageKey, error) { + console.error(browser.i18n.getMessage(errorMessageKey), error) + try { + notify(errorMessageKey, error.message) + } catch (error) { + console.error('unable to access background page', error) + } + } + + emitter.on('quickUpload', () => { + browser.tabs.create({ url: browser.extension.getURL('dist/popup/quick-upload.html') }) + }) + + emitter.on('openWebUi', async () => { + try { + const options = await browser.storage.local.get('ipfsApiUrl') + const apiUrl = options['ipfsApiUrl'] + await browser.tabs.create({ url: apiUrl + '/webui/' }) + window.close() + } catch (error) { + console.error(`Unable Open Web UI due to ${error}`) + } + }) + + emitter.on('openPrefs', () => { + browser.runtime.openOptionsPage().then(() => window.close()) + }) + + emitter.on('toggleRedirect', async () => { + const enabled = state.redirectEnabled + state.redirectEnabled = !enabled + emitter.emit('render') + + try { + await browser.storage.local.set({useCustomGateway: !enabled}) + } catch (error) { + console.error(`Unable to update redirect state due to ${error}`) + state.redirectEnabled = enabled + emitter.emit('render') + } + }) + + async function updatePageActions (status) { + // IPFS contexts require access to background page + // which is denied in Private Browsing mode + const bg = await getBackgroundPage(status) + + // Check if current page is an IPFS one + const ipfsContext = bg && status && status.ipfsPageActionsContext + + // There is no point in displaying actions that require API interaction if API is down + const apiIsUp = status && status.peerCount >= 0 + + if (apiIsUp) { + await activatePinButton() + } else { + deactivatePinButton() + } + + if (ipfsContext) { + state.contextActionsHidden = false + } else { + state.contextActionsHidden = true + } + + state.currentTabUrl = status.currentTab.url + } + + async function updateBrowserActionPopup (status) { + await updatePageActions(status) + const options = await browser.storage.local.get() + + try { + state.redirectEnabled = options.useCustomGateway + state.gatewayAddress = options.customGatewayUrl + } catch (error) { + console.error(`Unable update redirect state due to ${error}`) + state.gatewayAddress = '???' + } + + if (status) { + state.swarmPeers = status.peerCount < 0 ? null : status.peerCount + state.ipfsOnline = status.peerCount > 0 + state.gatewayVersion = status.gatewayVersion ? status.gatewayVersion : null + state.quickUploadHidden = !state.ipfsOnline + state.openWebUiHidden = !state.ipfsOnline + } else { + state.swarmPeers = null + state.ipfsOnline = false + state.gatewayVersion = null + state.quickUploadHidden = true + state.openWebUiHidden = true + } + } + + async function activatePinButton () { + try { + const bg = await getBackgroundPage() + const currentPath = await resolveToIPFS(new URL(state.currentTabUrl).pathname) + const response = await bg.ipfs.pin.ls(currentPath, {quiet: true}) + console.log(`positive ipfs.pin.ls for ${currentPath}: ${JSON.stringify(response)}`) + activateUnpinning() + } catch (error) { + if (/is not pinned/.test(error.message)) { + console.log(`negative ipfs.pin.ls: ${error} (${JSON.stringify(error)})`) + activatePinning() + } else { + console.error(`unexpected result of ipfs.pin.ls: ${error} (${JSON.stringify(error)})`) + deactivatePinButton() + } + } + } + + function deactivatePinButton () { + state.pinDisabled = true + state.unPinHidden = true + } + + function activatePinning () { + state.pinHidden = false + state.pinDisabled = false + state.unPinHidden = true + } + + function activateUnpinning () { + state.pinHidden = true + state.unPinHidden = false + state.unPinDisabled = false + } + + function notify (title, message) { + port.postMessage({event: 'notification', title: title, message: message}) + } +} + +function getBackgroundPage () { + return browser.runtime.getBackgroundPage() +} + +async function resolveToIPFS (path) { + const bg = await getBackgroundPage() + path = bg.safeIpfsPath(path) // https://github.com/ipfs/ipfs-companion/issues/303 + if (/^\/ipns/.test(path)) { + const response = await bg.ipfs.name.resolve(path, {recursive: true, nocache: false}) + return response.Path + } + return path +} diff --git a/add-on/src/popup/quick-upload.html b/add-on/src/popup/quick-upload.html index 0eda6d6c0..8ea7446ec 100644 --- a/add-on/src/popup/quick-upload.html +++ b/add-on/src/popup/quick-upload.html @@ -1,4 +1,6 @@ + + IPFS Upload @@ -21,11 +23,7 @@ - -

-
- -

+
diff --git a/add-on/src/popup/quick-upload.js b/add-on/src/popup/quick-upload.js index c8646f713..2a01e0734 100644 --- a/add-on/src/popup/quick-upload.js +++ b/add-on/src/popup/quick-upload.js @@ -3,44 +3,58 @@ const browser = require('webextension-polyfill') const IpfsApi = require('ipfs-api') -const translateDataAttrs = require('../lib/data-i18n') +const Buffer = IpfsApi().Buffer +const choo = require('choo') +const html = require('choo/html') -translateDataAttrs() +const app = choo() -const Buffer = IpfsApi().Buffer -const quickUploadInput = document.getElementById('quickUploadInput') -const quickUploadMessage = document.getElementById('quickUploadMessage') +app.use(quickUploadStore) +app.route('*', quickUploadPage) +app.mount('#root') + +function quickUploadStore (state, emitter) { + state.message = browser.i18n.getMessage('panel_quickUpload') -async function onQuickUploadInputChange (event) { - const file = event.target.files[0] - try { - const bg = await browser.runtime.getBackgroundPage() - let reader = new FileReader() - reader.onloadend = () => { - const buffer = Buffer.from(reader.result) - bg.ipfs.add(buffer, (err, result) => { - if (err || !result) { - // keep upload tab and display error message in it - quickUploadMessage.innerText = `Unable to upload to IPFS API: ${err}` - } else { - // close upload tab as it will be replaced with a new tab with uploaded content - browser.tabs.getCurrent().then(tab => { - browser.tabs.remove(tab.id) - }) - } - // execute handler - return bg.uploadResultHandler(err, result) - }) + emitter.on('fileInputChange', async (event) => { + const file = event.target.files[0] + try { + const bg = await browser.runtime.getBackgroundPage() + let reader = new FileReader() + reader.onloadend = () => { + const buffer = Buffer.from(reader.result) + bg.ipfs.add(buffer, (err, result) => { + if (err || !result) { + // keep upload tab and display error message in it + state.message = `Unable to upload to IPFS API: ${err}` + emitter.emit('render') + } else { + // close upload tab as it will be replaced with a new tab with uploaded content + browser.tabs.getCurrent().then(tab => { + browser.tabs.remove(tab.id) + }) + } + // execute handler + return bg.uploadResultHandler(err, result) + }) + } + reader.readAsArrayBuffer(file) + } catch (error) { + console.error(`Unable to perform quick upload due to ${error}`) } - reader.readAsArrayBuffer(file) - } catch (error) { - console.error(`Unable to perform quick upload due to ${error}`) - } + }) } -function initUpload () { - quickUploadInput.onchange = onQuickUploadInputChange - quickUploadInput.click() -} +function quickUploadPage (state, emit) { + const onFileInputChange = (e) => emit('fileInputChange', e) -document.addEventListener('DOMContentLoaded', initUpload) + return html` +
+ +

+ ${state.message}
+ +

+
+ ` +} diff --git a/package.json b/package.json index 25fb5844f..0008b1c08 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,10 @@ "build:copy": "run-s build:copy:*", "build:copy:src": "shx mkdir -p add-on/dist && shx cp -R add-on/src/* add-on/dist", "build:copy:wx-polyfill-lib": "shx cp node_modules/webextension-polyfill/dist/browser-polyfill.min.js add-on/dist/lib/browser-polyfill.min.js", - "build:js": "browserify -t [ browserify-package-json --global ] add-on/src/background/background.js add-on/src/options/options.js add-on/src/popup/browser-action.js add-on/src/popup/quick-upload.js -p [ factor-bundle -o add-on/dist/background/background.js -o add-on/dist/options/options.js -o add-on/dist/popup/browser-action.js -o add-on/dist/popup/quick-upload.js ] -o add-on/dist/ipfs-companion-common.js", + "build:js": "browserify -t [ browserify-package-json --global ] add-on/src/background/background.js add-on/src/options/options.js add-on/src/popup/browser-action/index.js add-on/src/popup/quick-upload.js -p [ factor-bundle -o add-on/dist/background/background.js -o add-on/dist/options/options.js -o add-on/dist/popup/browser-action/browser-action.js -o add-on/dist/popup/quick-upload.js ] -o add-on/dist/ipfs-companion-common.js", "build:bundle-extension": "web-ext build -s add-on/ -i src/ -a build/", "watch": "run-p watch:*", - "watch:js": "watchify add-on/src/background/background.js add-on/src/options/options.js add-on/src/popup/browser-action.js add-on/src/popup/quick-upload.js -p [ factor-bundle -o add-on/dist/background/background.js -o add-on/dist/options/options.js -o add-on/dist/popup/browser-action.js -o add-on/dist/popup/quick-upload.js ] -o add-on/dist/ipfs-companion-common.js -v", + "watch:js": "watchify add-on/src/background/background.js add-on/src/options/options.js add-on/src/popup/browser-action/index.js add-on/src/popup/quick-upload.js -p [ factor-bundle -o add-on/dist/background/background.js -o add-on/dist/options/options.js -o add-on/dist/popup/browser-action/browser-action.js -o add-on/dist/popup/quick-upload.js ] -o add-on/dist/ipfs-companion-common.js -v", "test": "run-s test:*", "test:functional": "mocha test/functional/**/*.test.js", "lint": "run-s lint:*", @@ -66,6 +66,7 @@ "web-ext": "2.2.2" }, "dependencies": { + "choo": "^6.6.0", "ipfs-api": "15.0.1", "is-ipfs": "0.3.2", "lru_map": "0.3.3", From 08f44affe8766c439e0a5849c755f4220c429268 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Fri, 17 Nov 2017 13:40:35 +0000 Subject: [PATCH 2/6] action orientated state --- .../popup/browser-action/context-actions.js | 22 ++--- .../popup/browser-action/gateway-status.js | 6 +- add-on/src/popup/browser-action/index.js | 9 +- add-on/src/popup/browser-action/operations.js | 11 ++- add-on/src/popup/browser-action/page.js | 5 +- add-on/src/popup/browser-action/store.js | 86 +++++++------------ 6 files changed, 60 insertions(+), 79 deletions(-) diff --git a/add-on/src/popup/browser-action/context-actions.js b/add-on/src/popup/browser-action/context-actions.js index 877cdbcf7..35f1e93d4 100644 --- a/add-on/src/popup/browser-action/context-actions.js +++ b/add-on/src/popup/browser-action/context-actions.js @@ -5,17 +5,17 @@ const browser = require('webextension-polyfill') const html = require('choo/html') module.exports = function contextActions ({ - hidden, - pinHidden, - pinDisabled, - unPinHidden, - unPinDisabled, + isIpfsContext, + isPinning, + isUnPinning, + isPinned, + isIpfsOnline, onCopyIpfsAddr, onCopyPublicGwAddr, onPin, onUnPin }) { - if (hidden) return null + if (!isIpfsContext) return null return html`
@@ -29,20 +29,20 @@ module.exports = function contextActions ({
${browser.i18n.getMessage('panel_copyCurrentPublicGwUrl')}
- ${pinHidden ? null : html` -
+ ${isIpfsOnline && isPinned ? null : html` +
${browser.i18n.getMessage('panel_pinCurrentIpfsAddress')}
`} - ${unPinHidden ? null : html` -
+ ${isIpfsOnline && isPinned ? html` +
${browser.i18n.getMessage('panel_unpinCurrentIpfsAddress')}
- `} + ` : null}
` diff --git a/add-on/src/popup/browser-action/gateway-status.js b/add-on/src/popup/browser-action/gateway-status.js index ec760d9a6..85f12125a 100644 --- a/add-on/src/popup/browser-action/gateway-status.js +++ b/add-on/src/popup/browser-action/gateway-status.js @@ -8,15 +8,15 @@ module.exports = function gatewayStatus ({ gatewayAddress, gatewayVersion, swarmPeers, - ipfsOnline, + isIpfsOnline, redirectEnabled }) { return html`
+ src="../../../icons/ipfs-logo-${isIpfsOnline ? 'on' : 'off'}.svg" + class="${isIpfsOnline ? 'online' : ''}"/>
  • ${browser.i18n.getMessage('panel_statusGatewayAddress')} diff --git a/add-on/src/popup/browser-action/index.js b/add-on/src/popup/browser-action/index.js index c32998c8d..fc59582da 100644 --- a/add-on/src/popup/browser-action/index.js +++ b/add-on/src/popup/browser-action/index.js @@ -3,10 +3,15 @@ const choo = require('choo') const browserActionPage = require('./page') -const store = require('./store') +const browserActionStore = require('./store') const app = choo() -app.use(store) +// Use the store to setup state defaults and event listeners for mutations +app.use(browserActionStore) + +// Register our single route app.route('*', browserActionPage) + +// Start the application and render it to the given querySelector app.mount('#root') diff --git a/add-on/src/popup/browser-action/operations.js b/add-on/src/popup/browser-action/operations.js index 7651df224..47fb5dfe9 100644 --- a/add-on/src/popup/browser-action/operations.js +++ b/add-on/src/popup/browser-action/operations.js @@ -5,8 +5,7 @@ const browser = require('webextension-polyfill') const html = require('choo/html') module.exports = function operations ({ - quickUploadHidden, - openWebUiHidden, + isIpfsOnline, redirectEnabled, onQuickUpload, onOpenWebUi, @@ -15,20 +14,20 @@ module.exports = function operations ({ }) { return html`
    - ${quickUploadHidden ? null : html` + ${isIpfsOnline ? html`
    ${browser.i18n.getMessage('panel_quickUpload')}
    - `} - ${openWebUiHidden ? null : html` + ` : null} + ${isIpfsOnline ? html`
    ${browser.i18n.getMessage('panel_openWebui')}
    - `} + ` : null}
    ${browser.i18n.getMessage('panel_openPreferences')}
    diff --git a/add-on/src/popup/browser-action/page.js b/add-on/src/popup/browser-action/page.js index c41cd4e59..00d57a850 100644 --- a/add-on/src/popup/browser-action/page.js +++ b/add-on/src/popup/browser-action/page.js @@ -6,6 +6,9 @@ const contextActions = require('./context-actions') const operations = require('./operations') const gatewayStatus = require('./gateway-status') +// Render the browser action page: +// Passed current app `state` from the store and `emit`, a function to create +// events, allowing views to signal back to the store that something happened. module.exports = function browserActionPage (state, emit) { const onCopyIpfsAddr = () => emit('copyIpfsAddr') const onCopyPublicGwAddr = () => emit('copyPublicGwAddr') @@ -17,7 +20,7 @@ module.exports = function browserActionPage (state, emit) { const onOpenPrefs = () => emit('openPrefs') const onToggleRedirect = () => emit('toggleRedirect') - const contextActionsProps = Object.assign({ hidden: state.contextActionsHidden, onCopyIpfsAddr, onCopyPublicGwAddr, onPin, onUnPin }, state) + const contextActionsProps = Object.assign({ onCopyIpfsAddr, onCopyPublicGwAddr, onPin, onUnPin }, state) const opsProps = Object.assign({ onQuickUpload, onOpenWebUi, onOpenPrefs, onToggleRedirect }, state) const gwStatusProps = Object.assign({}, state) diff --git a/add-on/src/popup/browser-action/store.js b/add-on/src/popup/browser-action/store.js index 38f1a346d..bacb846b0 100644 --- a/add-on/src/popup/browser-action/store.js +++ b/add-on/src/popup/browser-action/store.js @@ -3,19 +3,17 @@ const browser = require('webextension-polyfill') +// The store contains and mutates the state for the app module.exports = (state, emitter) => { Object.assign(state, { // UI state - contextActionsHidden: true, - pinHidden: false, - pinDisabled: true, - unPinHidden: true, - unPinDisabled: false, - quickUploadHidden: true, - openWebUiHidden: true, + isIpfsContext: false, + isPinning: false, + isUnPinning: false, + isPinned: false, currentTabUrl: null, // IPFS status - ipfsOnline: false, + isIpfsOnline: false, gatewayAddress: null, swarmPeers: null, gatewayVersion: null, @@ -33,7 +31,7 @@ module.exports = (state, emitter) => { port.onMessage.addListener(async (message) => { if (message.statusUpdate) { // console.log('In browser action, received message from background:', message) - await updateBrowserActionPopup(message.statusUpdate) + await updateBrowserActionState(message.statusUpdate) emitter.emit('render') } }) @@ -52,7 +50,7 @@ module.exports = (state, emitter) => { }) emitter.on('pin', async function pinCurrentResource () { - deactivatePinButton() + state.isPinning = true emitter.emit('render') try { @@ -61,14 +59,17 @@ module.exports = (state, emitter) => { const pinResult = await bg.ipfs.pin.add(currentPath, { recursive: true }) console.log('ipfs.pin.add result', pinResult) notify('notify_pinnedIpfsResourceTitle', currentPath) + state.isPinned = true } catch (error) { handlePinError('notify_pinErrorTitle', error) } + state.isPinning = false + emitter.emit('render') window.close() }) emitter.on('unPin', async function unPinCurrentResource () { - deactivatePinButton() + state.isUnPinning = true emitter.emit('render') try { @@ -77,9 +78,12 @@ module.exports = (state, emitter) => { const result = await bg.ipfs.pin.rm(currentPath, {recursive: true}) console.log('ipfs.pin.rm result', result) notify('notify_unpinnedIpfsResourceTitle', currentPath) + state.isPinned = false } catch (error) { handlePinError('notify_unpinErrorTitle', error) } + state.isUnPinning = true + emitter.emit('render') window.close() }) @@ -125,7 +129,7 @@ module.exports = (state, emitter) => { } }) - async function updatePageActions (status) { + async function updatePageActionsState (status) { // IPFS contexts require access to background page // which is denied in Private Browsing mode const bg = await getBackgroundPage(status) @@ -133,26 +137,18 @@ module.exports = (state, emitter) => { // Check if current page is an IPFS one const ipfsContext = bg && status && status.ipfsPageActionsContext - // There is no point in displaying actions that require API interaction if API is down - const apiIsUp = status && status.peerCount >= 0 - - if (apiIsUp) { - await activatePinButton() - } else { - deactivatePinButton() - } + state.isIpfsContext = !!ipfsContext + state.currentTabUrl = status.currentTab.url - if (ipfsContext) { - state.contextActionsHidden = false - } else { - state.contextActionsHidden = true + if (state.isIpfsContext) { + // There is no point in displaying actions that require API interaction if API is down + const apiIsUp = status && status.peerCount >= 0 + if (apiIsUp) await updatePinnedState(status) } - - state.currentTabUrl = status.currentTab.url } - async function updateBrowserActionPopup (status) { - await updatePageActions(status) + async function updateBrowserActionState (status) { + await updatePageActionsState(status) const options = await browser.storage.local.get() try { @@ -165,54 +161,32 @@ module.exports = (state, emitter) => { if (status) { state.swarmPeers = status.peerCount < 0 ? null : status.peerCount - state.ipfsOnline = status.peerCount > 0 + state.isIpfsOnline = status.peerCount > 0 state.gatewayVersion = status.gatewayVersion ? status.gatewayVersion : null - state.quickUploadHidden = !state.ipfsOnline - state.openWebUiHidden = !state.ipfsOnline } else { state.swarmPeers = null - state.ipfsOnline = false + state.isIpfsOnline = false state.gatewayVersion = null - state.quickUploadHidden = true - state.openWebUiHidden = true } } - async function activatePinButton () { + async function updatePinnedState (status) { try { const bg = await getBackgroundPage() - const currentPath = await resolveToIPFS(new URL(state.currentTabUrl).pathname) + const currentPath = await resolveToIPFS(new URL(status.currentTab.url).pathname) const response = await bg.ipfs.pin.ls(currentPath, {quiet: true}) console.log(`positive ipfs.pin.ls for ${currentPath}: ${JSON.stringify(response)}`) - activateUnpinning() + state.isPinned = true } catch (error) { if (/is not pinned/.test(error.message)) { console.log(`negative ipfs.pin.ls: ${error} (${JSON.stringify(error)})`) - activatePinning() } else { console.error(`unexpected result of ipfs.pin.ls: ${error} (${JSON.stringify(error)})`) - deactivatePinButton() } + state.isPinned = false } } - function deactivatePinButton () { - state.pinDisabled = true - state.unPinHidden = true - } - - function activatePinning () { - state.pinHidden = false - state.pinDisabled = false - state.unPinHidden = true - } - - function activateUnpinning () { - state.pinHidden = true - state.unPinHidden = false - state.unPinDisabled = false - } - function notify (title, message) { port.postMessage({event: 'notification', title: title, message: message}) } From d0642e1d383a27dccda47ef8b0ad65774cea9d3c Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 21 Nov 2017 09:06:28 +0000 Subject: [PATCH 3/6] removes delay before update --- add-on/src/popup/browser-action/store.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/add-on/src/popup/browser-action/store.js b/add-on/src/popup/browser-action/store.js index bacb846b0..8c26a10ef 100644 --- a/add-on/src/popup/browser-action/store.js +++ b/add-on/src/popup/browser-action/store.js @@ -23,9 +23,6 @@ module.exports = (state, emitter) => { let port emitter.on('DOMContentLoaded', async () => { - // A short pause allows the popup to animate in without breaking - await new Promise((resolve) => setTimeout(resolve, 100)) - // initialize connection to the background script which will trigger UI updates port = browser.runtime.connect({name: 'browser-action-port'}) port.onMessage.addListener(async (message) => { From 6c6b00a19fd48f3dc4a9f132a08a4829e014f8b8 Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 21 Nov 2017 20:06:31 +0000 Subject: [PATCH 4/6] removes rc2 version suffix --- add-on/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/add-on/manifest.json b/add-on/manifest.json index 04ebc3c15..c5fd47c78 100644 --- a/add-on/manifest.json +++ b/add-on/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_manifest_extensionName__", "short_name": "__MSG_manifest_shortExtensionName__", - "version" : "2.1.0rc2", + "version" : "2.1.0", "description": "__MSG_manifest_extensionDescription__", "homepage_url": "https://github.com/ipfs/ipfs-companion", From 8d19a3b9d9a128ce1e6c583f12f14b8ed19916f7 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Wed, 22 Nov 2017 00:13:16 +0100 Subject: [PATCH 5/6] fix(quickupload): close browser action popup on click + add choo to yarn.lock --- add-on/src/popup/browser-action/store.js | 1 + package.json | 2 +- yarn.lock | 106 +++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/add-on/src/popup/browser-action/store.js b/add-on/src/popup/browser-action/store.js index 8c26a10ef..d3218740c 100644 --- a/add-on/src/popup/browser-action/store.js +++ b/add-on/src/popup/browser-action/store.js @@ -95,6 +95,7 @@ module.exports = (state, emitter) => { emitter.on('quickUpload', () => { browser.tabs.create({ url: browser.extension.getURL('dist/popup/quick-upload.html') }) + window.close() }) emitter.on('openWebUi', async () => { diff --git a/package.json b/package.json index 0008b1c08..1215e2a1a 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "web-ext": "2.2.2" }, "dependencies": { - "choo": "^6.6.0", + "choo": "6.6.0", "ipfs-api": "15.0.1", "is-ipfs": "0.3.2", "lru_map": "0.3.3", diff --git a/yarn.lock b/yarn.lock index 508d917ed..66d612e7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -613,6 +613,14 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bel@^5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/bel/-/bel-5.1.5.tgz#99d9381ce8503b120702e920e23daf515a6cba53" + dependencies: + hyperx "^2.3.0" + is-electron "^2.0.0" + pelo "^0.0.4" + better-assert@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" @@ -1099,6 +1107,23 @@ chokidar@^1.0.0, chokidar@^1.4.1, chokidar@^1.4.3: optionalDependencies: fsevents "^1.0.0" +choo@6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/choo/-/choo-6.6.0.tgz#2726211b8205a746d6a8d535042ef03f1ebd2a6d" + dependencies: + bel "^5.1.3" + document-ready "^2.0.1" + nanobus "^4.2.0" + nanohref "^3.0.0" + nanolocation "^1.0.0" + nanomorph "^5.1.2" + nanoquery "^1.1.0" + nanoraf "^3.0.0" + nanorouter "^2.0.0" + nanotiming "^6.0.0" + scroll-to-anchor "^1.0.0" + xtend "^4.0.1" + chownr@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" @@ -1725,6 +1750,10 @@ doctrine@^2.0.0: esutils "^2.0.2" isarray "^1.0.0" +document-ready@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/document-ready/-/document-ready-2.0.1.tgz#3e3bf31d3235b94e232e7b2c5fa1a634e873bae4" + dom-serialize@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" @@ -3070,6 +3099,16 @@ husky@0.14.3: normalize-path "^1.0.0" strip-indent "^2.0.0" +hyperscript-attribute-to-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hyperscript-attribute-to-property/-/hyperscript-attribute-to-property-1.0.0.tgz#825308d49bb8e2957923f731981bcc811cad7aff" + +hyperx@^2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/hyperx/-/hyperx-2.3.2.tgz#17518dad514209b3f7090f149c08a9a64386396e" + dependencies: + hyperscript-attribute-to-property "^1.0.0" + iconv-lite@0.4.19, iconv-lite@^0.4.17: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -3324,6 +3363,10 @@ is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" +is-electron@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.1.0.tgz#37dd2e9e7167efa8bafce86c0c25762bc4b851fa" + is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" @@ -4352,6 +4395,51 @@ nan@^2.2.1, nan@^2.3.0, nan@^2.3.3: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" +nanoassert@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/nanoassert/-/nanoassert-1.1.0.tgz#4f3152e09540fde28c76f44b19bbcd1d5a42478d" + +nanobus@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/nanobus/-/nanobus-4.3.1.tgz#d85139b5ee057e36db0113cdcf01a09b7efd10ac" + dependencies: + nanotiming "^6.0.0" + remove-array-items "^1.0.0" + +nanohref@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/nanohref/-/nanohref-3.0.1.tgz#3879428e4fa80b7d5484692471cfa0b4a3348f8e" + +nanolocation@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/nanolocation/-/nanolocation-1.0.0.tgz#15b5c7af05895d1a9f21f0d136495d994450686b" + +nanomorph@^5.1.2: + version "5.1.3" + resolved "https://registry.yarnpkg.com/nanomorph/-/nanomorph-5.1.3.tgz#65b81912bb32278aaa7aacc9ccd99b4508f6a21d" + dependencies: + nanoassert "^1.1.0" + +nanoquery@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/nanoquery/-/nanoquery-1.2.0.tgz#0e44537ac1a2717e11ee796abce605f141984982" + dependencies: + nanoassert "^1.1.0" + +nanoraf@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/nanoraf/-/nanoraf-3.0.1.tgz#ab9fb9c257b9adcc71d82982cb58d8fa3503764a" + +nanorouter@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/nanorouter/-/nanorouter-2.1.0.tgz#4fcaf96203a00898da89188b1bff5a8fc06ef4ff" + dependencies: + wayfarer "^6.5.0" + +nanotiming@^6.0.0: + version "6.1.5" + resolved "https://registry.yarnpkg.com/nanotiming/-/nanotiming-6.1.5.tgz#673b104bd651ba6e98e4172ee744f2ccb4d6f11b" + native-promise-only@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" @@ -4870,6 +4958,10 @@ peer-info@~0.11.0: multiaddr "^3.0.1" peer-id "~0.10.2" +pelo@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/pelo/-/pelo-0.0.4.tgz#ca30c8d59a669d3b43a6d14c28681ca21b604b0f" + pem-jwk@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/pem-jwk/-/pem-jwk-1.5.1.tgz#7a8637fd2f67a827e57c0c42e1c23c3fd52cfb01" @@ -5371,6 +5463,10 @@ remark@^5.0.1: remark-stringify "^1.1.0" unified "^4.1.1" +remove-array-items@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/remove-array-items/-/remove-array-items-1.0.0.tgz#07bf42cb332f4cf6e85ead83b5e4e896d2326b21" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -5611,6 +5707,10 @@ sax@>=0.6.0: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" +scroll-to-anchor@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/scroll-to-anchor/-/scroll-to-anchor-1.1.0.tgz#c99b8d2e5d95056752787ca78095ab75b520b3fd" + secp256k1@^3.3.0: version "3.3.1" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.3.1.tgz#d1d325519db714789c11ec0450d4b9a3aa01eb1a" @@ -6706,6 +6806,12 @@ watchpack@1.3.0: chokidar "^1.4.3" graceful-fs "^4.1.2" +wayfarer@^6.5.0: + version "6.6.2" + resolved "https://registry.yarnpkg.com/wayfarer/-/wayfarer-6.6.2.tgz#3baadc1c4b85ef9be26ee75fac6cde9b075ae473" + dependencies: + xtend "^4.0.1" + wcwidth@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" From e3ede8e596000ac28732ad2572271150283050b5 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Wed, 22 Nov 2017 01:16:13 +0100 Subject: [PATCH 6/6] chore: remove unused data-i18n --- add-on/src/popup/browser-action/operations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/add-on/src/popup/browser-action/operations.js b/add-on/src/popup/browser-action/operations.js index 47fb5dfe9..1fc0cb771 100644 --- a/add-on/src/popup/browser-action/operations.js +++ b/add-on/src/popup/browser-action/operations.js @@ -17,7 +17,7 @@ module.exports = function operations ({ ${isIpfsOnline ? html`
    -
    ${browser.i18n.getMessage('panel_quickUpload')}
    +
    ${browser.i18n.getMessage('panel_quickUpload')}
    ` : null}