Skip to content

Commit

Permalink
feat: replace pinning with import to mfs (#997)
Browse files Browse the repository at this point in the history
This changes the way IPFS content is kept around.
Instead of using low level pins we copy the item to MFS,
unifying experience to match recent changes in ipfs-webui v2.12:
https://github.com/ipfs/ipfs-webui/releases/v2.12.0
and ipfs-desktop v0.15.0:
https://github.com/ipfs/ipfs-desktop/releases/tag/v0.15.0

This also removed page-action, because it was Firefox-specific feature
and made maintenance and testing more difficult
(now we have same UX in all browsers).

Closes #742
Closes #888
Closes ipfs/ipfs-gui#91

Co-authored-by: Jessica Schilling <jessica@protocol.ai>
  • Loading branch information
lidel and jessicaschilling authored May 10, 2021
1 parent 72fca61 commit 7aba6d9
Show file tree
Hide file tree
Showing 17 changed files with 78 additions and 257 deletions.
30 changes: 9 additions & 21 deletions add-on/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@
"message": "Enable/disable all IPFS integrations on $1.",
"description": "A menu item tooltip in Browser Action pop-up (panel_activeTabSiteIntegrationsToggleTooltip)"
},
"panel_pinCurrentIpfsAddress": {
"message": "Pin IPFS Resource",
"description": "A menu item in Browser Action pop-up (panel_pinCurrentIpfsAddress)"
"panel_importCurrentIpfsAddress": {
"message": "Import to Files on My Node",
"description": "A menu item in Browser Action pop-up (panel_importCurrentIpfsAddress)"
},
"panel_pinCurrentIpfsAddressTooltip": {
"message": "Pin this page's IPFS resources to your node to have a local copy that's available offline and never thrown away.",
"description": "A menu item tooltip in Browser Action pop-up (panel_pinCurrentIpfsAddressTooltip)"
"panel_importCurrentIpfsAddressTooltip": {
"message": "Import this tab's IPFS resources to your Files to have a persistent local copy that's available offline and never thrown away.",
"description": "A menu item tooltip in Browser Action pop-up (panel_importCurrentIpfsAddressTooltip)"
},
"panelCopy_currentIpnsAddress": {
"message": "Copy IPNS Path",
Expand Down Expand Up @@ -195,21 +195,9 @@
"message": "Copied",
"description": "A title of system notification (notify_copiedTitle)"
},
"notify_pinnedIpfsResourceTitle": {
"message": "IPFS Resource Pinned",
"description": "A title of system notification (notify_pinnedIpfsResourceTitle)"
},
"notify_unpinnedIpfsResourceTitle": {
"message": "Removed IPFS Pin",
"description": "A title of system notification (notify_unpinnedIpfsResourceTitle)"
},
"notify_pinErrorTitle": {
"message": "Error Pinning IPFS Resource",
"description": "A title of system notification (notify_pinErrorTitle)"
},
"notify_unpinErrorTitle": {
"message": "Error Removing IPFS Pin",
"description": "A title of system notification (notify_unpinErrorTitle)"
"notify_fileCpImportErrorTitle": {
"message": "Error while importing IPFS Resource",
"description": "A title of system notification (notify_fileCpImportErrorTitle)"
},
"notify_apiOnlineTitle": {
"message": "IPFS API is Online",
Expand Down
7 changes: 0 additions & 7 deletions add-on/manifest.firefox.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@
"strict_min_version": "68.0"
}
},
"page_action": {
"default_icon": {
"128": "icons/ipfs-logo-off.svg"
},
"default_title": "__MSG_pageAction_titleNonIpfs__",
"default_popup": "dist/popup/page-action/index.html"
},
"permissions": [
"<all_urls>",
"idle",
Expand Down
2 changes: 1 addition & 1 deletion add-on/src/landing-pages/welcome/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const renderInstallSteps = (i18n, isIpfsOnline) => {
</svg>
`

const optionsUrl = browser.extension.getURL(optionsPage)
const optionsUrl = browser.runtime.getURL(optionsPage)
return html`
<div class="w-80 mt0 flex flex-column transition-all ${stateUnknown && 'state-unknown'}">
<div class="mb4 flex flex-column justify-center items-center">
Expand Down
4 changes: 2 additions & 2 deletions add-on/src/lib/ipfs-client/brave.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ async function activationUiCleanup (browser) {
})
log('[activation ui cleanup] Brave gateway is up, cleaning up')

const welcomePageUrl = browser.extension.getURL(welcomePage)
const optionsPageUrl = browser.extension.getURL(optionsPage)
const welcomePageUrl = browser.runtime.getURL(welcomePage)
const optionsPageUrl = browser.runtime.getURL(optionsPage)
// we are unable to query ipfs:// directly due to reasons mentioned in 'closeIpfsTab'
// so we make quick pass over all tabs and check welcome and options while at it.
for (const tab of await browser.tabs.query({})) {
Expand Down
3 changes: 2 additions & 1 deletion add-on/src/lib/ipfs-companion.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const createDnslinkResolver = require('./dnslink')
const { createRequestModifier } = require('./ipfs-request')
const { initIpfsClient, destroyIpfsClient } = require('./ipfs-client')
const { braveNodeType, useBraveEndpoint, releaseBraveEndpoint } = require('./ipfs-client/brave')
const { createIpfsImportHandler, formatImportDirectory } = require('./ipfs-import')
const { createIpfsImportHandler, formatImportDirectory, browserActionFilesCpImportCurrentTab } = require('./ipfs-import')
const createNotifier = require('./notifier')
const createCopier = require('./copier')
const createInspector = require('./inspector')
Expand Down Expand Up @@ -234,6 +234,7 @@ module.exports = async function init () {

const BrowserActionMessageHandlers = {
notification: (message) => notify(message.title, message.message),
[browserActionFilesCpImportCurrentTab]: () => ipfsImportHandler.filesCpImportCurrentTab(browser),
[contextMenuViewOnGateway]: inspector.viewOnGateway,
[contextMenuCopyCanonicalAddress]: copier.copyCanonicalAddress,
[contextMenuCopyCidAddress]: copier.copyCidAddress,
Expand Down
47 changes: 43 additions & 4 deletions add-on/src/lib/ipfs-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ log.error = debug('ipfs-companion:import:error')
const browser = require('webextension-polyfill')

const { redirectOptOutHint } = require('./ipfs-request')
const { ipfsContentPath } = require('./ipfs-path')

module.exports.browserActionFilesCpImportCurrentTab = 'browserActionFilesCpImportCurrentTab'

module.exports.createIpfsImportHandler = (getState, getIpfs, ipfsPathValidator, runtime, copier) => {
const { resolveToPublicUrl } = ipfsPathValidator
const {
resolveToPublicUrl,
resolveToCid
} = ipfsPathValidator
const ipfsImportHandler = {
getIpfsPathAndNativeAddress (cid) {
const state = getState()
Expand All @@ -33,9 +39,8 @@ module.exports.createIpfsImportHandler = (getState, getIpfs, ipfsPathValidator,

async openFilesAtWebUI (mfsPath) {
const state = getState()
await browser.tabs.create({
url: `${state.webuiRootUrl}#/files${mfsPath}`
})
const url = `${state.webuiRootUrl}#/files${mfsPath}`
await browser.tabs.create({ url })
},

async copyImportResultsToFiles (results, importDir) {
Expand Down Expand Up @@ -82,7 +87,41 @@ module.exports.createIpfsImportHandler = (getState, getIpfs, ipfsPathValidator,
}
}
}
},

async filesCpImportCurrentTab (browser) {
try {
const {
copyShareLink,
preloadFilesAtPublicGateway,
openFilesAtWebUI
} = this
const currentTab = await browser.tabs.query({ active: true, currentWindow: true }).then(tabs => tabs[0])
const importDir = module.exports.formatImportDirectory(getState().importDir)
const ipfs = getIpfs()
const contentPath = ipfsContentPath(currentTab.url, { keepURIParams: false })
const pathSegments = contentPath.split('/').filter(Boolean)
const namedImport = typeof pathSegments[2] !== 'undefined'
const resolvedCid = await resolveToCid(contentPath)

// best-effort name based on last path segment, or IPNS root
const name = namedImport
? pathSegments.slice(-1)
: `${pathSegments[0] === 'ipns' ? pathSegments[1] : 'unnamed'}_${resolvedCid.slice(-4)}`

// import to mfs
await ipfs.files.mkdir(importDir, { parents: true })
await ipfs.files.cp(`/ipfs/${resolvedCid}`, `${importDir}${name}`)
await openFilesAtWebUI(importDir)

// create fake ipfs.add results, so we can reuse code from quick-import feature
const { cid } = await ipfs.files.stat(importDir, { hash: true })
const results = [{ path: '', cid }, { path: name, cid: resolvedCid }]
await copyShareLink(results)
await preloadFilesAtPublicGateway(results)
} catch (e) { log.error('unexpected error during filesCpImportCurrentTab', e) }
}

}
return ipfsImportHandler
}
Expand Down
2 changes: 1 addition & 1 deletion add-on/src/lib/ipfs-proxy/request-access.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function createRequestAccess (browser, screen) {
// TODO: cleanup so below stub is not needed
permissions = Array.isArray(permissions) ? permissions : [permissions]

const url = browser.extension.getURL(opts.dialogPath || DIALOG_PATH)
const url = browser.runtime.getURL(opts.dialogPath || DIALOG_PATH)

let dialogTabId

Expand Down
2 changes: 1 addition & 1 deletion add-on/src/lib/notifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function createNotifier (getState) {
try {
return await browser.notifications.create({
type: 'basic',
iconUrl: browser.extension.getURL('icons/ipfs-logo-on.svg'),
iconUrl: browser.runtime.getURL('icons/ipfs-logo-on.svg'),
title: title,
message: message
})
Expand Down
2 changes: 1 addition & 1 deletion add-on/src/options/forms/experiments-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ function experimentsForm ({
${browser.i18n.getMessage('option_ipfsProxy_description')}
<p>${ipfsProxy
? html`
<a class="link underline hover-aqua" href="${browser.extension.getURL('dist/pages/proxy-acl/index.html')}" target="_blank">
<a class="link underline hover-aqua" href="${browser.runtime.getURL('dist/pages/proxy-acl/index.html')}" target="_blank">
${browser.i18n.getMessage('option_ipfsProxy_link_manage_permissions')}
</a>`
: html`<del>${browser.i18n.getMessage('option_ipfsProxy_link_manage_permissions')}</del>`}
Expand Down
21 changes: 9 additions & 12 deletions add-on/src/popup/browser-action/context-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const html = require('choo/html')
const navItem = require('./nav-item')
const navHeader = require('./nav-header')
const { sameGateway } = require('../../lib/ipfs-path')
const { formatImportDirectory } = require('../../lib/ipfs-import')
const {
contextMenuViewOnGateway,
contextMenuCopyAddressAtPublicGw,
Expand Down Expand Up @@ -35,26 +36,22 @@ function contextActions ({
currentTabPermalink = notReady,
ipfsNodeType,
isIpfsContext,
isPinning,
isUnPinning,
isPinned,
isIpfsOnline,
isApiAvailable,
onToggleSiteIntegrations,
onViewOnGateway,
onCopy,
onPin,
onUnPin
importDir,
onFilesCpImport
}) {
const activeCidResolver = active && isIpfsOnline && isApiAvailable && currentTabCid
const activePinControls = active && isIpfsOnline && isApiAvailable
const activeFilesCpImport = active && isIpfsOnline && isApiAvailable && !ipfsNodeType.startsWith('embedded')
const isMutable = currentTabContentPath.startsWith('/ipns/')
const activeViewOnGateway = (currentTab) => {
if (!currentTab) return false
const { url } = currentTab
return !(url.startsWith('ip') || sameGateway(url, gwURLString) || sameGateway(url, pubGwURLString))
}

const renderIpfsContextItems = () => {
if (!isIpfsContext) return
return html`<div>
Expand Down Expand Up @@ -100,11 +97,11 @@ function contextActions ({
onClick: () => onCopy(contextMenuCopyRawCid)
})}
${navItem({
text: browser.i18n.getMessage('panel_pinCurrentIpfsAddress'),
title: browser.i18n.getMessage('panel_pinCurrentIpfsAddressTooltip'),
disabled: !activePinControls,
switchValue: (isPinned || isPinning) && !isUnPinning,
onClick: isPinned ? onUnPin : onPin
text: browser.i18n.getMessage('panel_importCurrentIpfsAddress'),
title: browser.i18n.getMessage('panel_importCurrentIpfsAddressTooltip'),
helperText: formatImportDirectory(importDir),
disabled: !activeFilesCpImport,
onClick: onFilesCpImport
})}
</div>
`
Expand Down
5 changes: 2 additions & 3 deletions add-on/src/popup/browser-action/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ const tools = require('./tools')
module.exports = function browserActionPage (state, emit) {
const onViewOnGateway = () => emit('viewOnGateway')
const onCopy = (copyAction) => emit('copy', copyAction)
const onPin = () => emit('pin')
const onUnPin = () => emit('unPin')
const onFilesCpImport = () => emit('filesCpImport')

const onQuickImport = () => emit('quickImport')
const onOpenWebUi = () => emit('openWebUi', '/')
Expand All @@ -25,7 +24,7 @@ module.exports = function browserActionPage (state, emit) {
const onToggleActive = () => emit('toggleActive')

const headerProps = Object.assign({ onToggleActive, onOpenPrefs, onOpenReleaseNotes, onOpenWelcomePage }, state)
const activeTabActionsProps = Object.assign({ onViewOnGateway, onToggleSiteIntegrations, onCopy, onPin, onUnPin }, state)
const activeTabActionsProps = Object.assign({ onViewOnGateway, onToggleSiteIntegrations, onCopy, onFilesCpImport }, state)
const opsProps = Object.assign({ onQuickImport, onOpenWebUi, onToggleGlobalRedirect }, state)

return html`
Expand Down
Loading

0 comments on commit 7aba6d9

Please sign in to comment.