Skip to content

Commit

Permalink
feat: copy link to clipboard when adding to ipfs (#1221)
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Henrique Dias <hacdias@gmail.com>
  • Loading branch information
hacdias committed Oct 29, 2019
1 parent 71fbcbf commit c12e18b
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 38 deletions.
19 changes: 12 additions & 7 deletions assets/locales/en.json
Expand Up @@ -22,14 +22,8 @@
"shareableLinkCopied": "Shareable link copied to the clipboard. Click here to view the screenshot.",
"couldNotTakeScreenshot": "Could not take screenshot",
"errorwhileTakingScreenshot": "An error occurred while taking the screenshot.",
"yourFilesCouldntBeAdded": "Your files couldn't be added.",
"folderAdded": "Folder added",
"folderAddedToIpfsClickToView": "Folder { name } added to IPFS. Click to view the folder.",
"fileAdded": "File added",
"fileAddedToIpfsClickToView": "File { name } added to IPFS. Click to view the file.",
"clickToOpenLogs": "Click here to open the logs.",
"ipfsNotRunning": "IPFS is not running",
"desktopIsStartedButDaemonOffline": "IPFS Desktop is started but the daemon is turned off.",
"cantDownloadHash": "Could not download hash",
"invalidHashClipboard": "The hash on the clipboard is not valid.",
"errorWhileDownloadingHash": "An error occurred while getting the hash.",
Expand All @@ -51,7 +45,6 @@
"reportTheError": "Report the error",
"restartIpfsDesktop": "Restart IPFS Desktop",
"openLogs": "Open logs",
"anErrorHasOccurred": "An error has occurred",
"takeScreenshot": "Take Screenshot",
"downloadHash": "Download Hash",
"moveRepositoryLocation": "Move Repository Location",
Expand Down Expand Up @@ -110,5 +103,17 @@
"title": "Ports are busy",
"message": "Cannot bind to one or more of the API or Gateway addresses because the ports are busy.",
"action": "Open configuration file"
},
"itemsAddedNotification": {
"title": "Items added",
"message": "{ count } items added to your node. A shareable link was copied to your clipboard. Click here to see your files."
},
"itemAddedNotification": {
"title": "Item added",
"message": "Item added to your node. A shareable link was copied to your clipboard. Click here to see your file."
},
"itemsFailedNotification": {
"title": "Failed to add items",
"message": "Could not add your items to your node."
}
}
98 changes: 73 additions & 25 deletions src/add-to-ipfs.js
@@ -1,9 +1,10 @@
import { extname, basename } from 'path'
import { clipboard } from 'electron'
import i18n from 'i18next'
import logger from './common/logger'
import { notify, notifyError } from './common/notify'

async function copyFile (launch, ipfs, hash, name, folder = false) {
async function copyFile (ipfs, hash, name) {
let i = 0
const ext = extname(name)
const base = basename(name, ext)
Expand All @@ -21,41 +22,88 @@ async function copyFile (launch, ipfs, hash, name, folder = false) {
i++
}

await ipfs.files.cp(`/ipfs/${hash}`, `/${name}`)
return ipfs.files.cp(`/ipfs/${hash}`, `/${name}`)
}

async function makeShareableObject (ipfs, results) {
if (results.length === 1) {
// If it's just one object, we link it directly.
return results[0]
}

let baseCID = await ipfs.object.new('unixfs-dir')

for (const { hash, path, size } of results) {
baseCID = (await ipfs.object.patch.addLink(baseCID, {
name: path,
size,
cid: hash
})).toString()
}

notify({
title: folder ? i18n.t('folderAdded') : i18n.t('fileAdded'),
body: i18n.t(`${folder ? 'folder' : 'file'}AddedToIpfsClickToView`, { name })
}, () => {
launch(`/files/${name}`)
return { hash: baseCID, path: '' }
}

function sendNotification (failures, successes, launch, path) {
let link, title, body, fn

if (failures.length === 0) {
// All worked well!
fn = notify

if (successes.length === 1) {
link = `/files/${path}`
title = i18n.t('itemAddedNotification.title')
body = i18n.t('itemAddedNotification.message')
} else {
link = '/files'
title = i18n.t('itemsAddedNotification.title')
body = i18n.t('itemsAddedNotification.message', { count: successes.length })
}
} else {
// Some/all failed!
fn = notifyError
title = i18n.t('itemsFailedNotification.title')
body = i18n.t('itemsFailedNotification.message')
}

fn({ title, body }, () => {
launch(link)
})
}

export default async function ({ getIpfsd, launchWebUI }, file) {
export default async function ({ getIpfsd, launchWebUI }, files) {
const ipfsd = await getIpfsd()

if (!ipfsd) {
return
}

logger.info(`[add to ipfs] started ${file}`, { withAnalytics: 'ADD_VIA_DESKTOP' })
ipfsd.api.addFromFs(file, { recursive: true }, async (err, result) => {
if (err) {
logger.error(`[add to ipfs] ${err.toString()}`)
return notifyError({
title: i18n.t('yourFilesCouldntBeAdded')
})
}
const successes = []
const failures = []

const { path, hash } = result[result.length - 1]
const log = logger.start('[add to ipfs] started', { withAnalytics: 'ADD_VIA_DESKTOP' })

await Promise.all(files.map(async file => {
try {
await copyFile(launchWebUI, ipfsd.api, hash, path, result.length > 1)
logger.info(`[add to ipfs] completed ${file}`)
} catch (err) {
logger.error(`[add to ipfs] ${err.toString()}`)
notifyError({
title: i18n.t('yourFilesCouldntBeAdded')
})
const results = await ipfsd.api.addFromFs(file, { recursive: true })
const { path, hash, size } = results[results.length - 1]
await copyFile(ipfsd.api, hash, path)
successes.push({ path, hash, size })
} catch (e) {
failures.push(e)
}
})
}))

if (failures.length > 0) {
log.fail(new Error(failures.reduce((prev, curr) => `${prev} ${curr.toString()}`, '')))
} else {
log.end()
}

const { hash, path } = await makeShareableObject(ipfsd.api, successes)
sendNotification(failures, successes, launchWebUI, path)

const url = `https://ipfs.io/ipfs/${hash}`
clipboard.writeText(url)
}
9 changes: 7 additions & 2 deletions src/argv-files-handler.js
Expand Up @@ -4,6 +4,7 @@ import addToIpfs from './add-to-ipfs'
export async function argvHandler (argv, ctx) {
let handled = false

const files = []
for (const arg of argv.slice(1)) {
if (!arg.startsWith('--add')) {
continue
Expand All @@ -12,11 +13,15 @@ export async function argvHandler (argv, ctx) {
const filename = arg.slice(6)

if (await fs.pathExists(filename)) {
await addToIpfs(ctx, filename)
handled = true
files.push(filename)
}
}

if (files.length > 0) {
await addToIpfs(ctx, files)
handled = true
}

return handled
}

Expand Down
5 changes: 1 addition & 4 deletions src/tray.js
Expand Up @@ -150,10 +150,7 @@ export default function (ctx) {

// macOS tray drop files
tray.on('drop-files', async (_, files) => {
for (const file of files) {
await addToIpfs(ctx, file)
}

await addToIpfs(ctx, files)
ctx.launchWebUI('/files', { focus: false })
})

Expand Down

0 comments on commit c12e18b

Please sign in to comment.