-
Notifications
You must be signed in to change notification settings - Fork 865
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ux): improve download cid (#1419)
License: MIT Signed-off-by: Henrique Dias <hacdias@gmail.com>
- Loading branch information
Showing
7 changed files
with
341 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
const { join } = require('path') | ||
const fs = require('fs-extra') | ||
const i18n = require('i18next') | ||
const isIPFS = require('is-ipfs') | ||
const { clipboard, app, shell } = require('electron') | ||
const logger = require('./common/logger') | ||
const { IS_MAC } = require('./common/consts') | ||
const setupGlobalShortcut = require('./setup-global-shortcut') | ||
const { selectDirectory } = require('./dialogs') | ||
const dock = require('./dock') | ||
const showPrompt = require('./prompt') | ||
const { showDialog } = require('./dialogs') | ||
|
||
const CONFIG_KEY = 'downloadHashShortcut' | ||
|
||
const SHORTCUT = IS_MAC | ||
? 'Command+Control+H' | ||
: 'CommandOrControl+Alt+D' | ||
|
||
async function saveFile (dir, file) { | ||
const location = join(dir, file.path) | ||
await fs.outputFile(location, file.content) | ||
} | ||
|
||
async function getCID () { | ||
const text = clipboard.readText().trim() | ||
|
||
const { button, input } = await showPrompt({ | ||
title: i18n.t('downloadCidContentDialog.title'), | ||
message: i18n.t('downloadCidContentDialog.message'), | ||
defaultValue: (isIPFS.cid(text) || isIPFS.path(text)) ? text : '', | ||
buttons: [ | ||
i18n.t('downloadCidContentDialog.action'), | ||
i18n.t('cancel') | ||
], | ||
window: { | ||
width: 500, | ||
height: 120 | ||
} | ||
}) | ||
|
||
if (button !== 0) { | ||
return | ||
} | ||
|
||
return input | ||
} | ||
|
||
async function downloadCid (ctx) { | ||
const cid = await getCID() | ||
if (!cid) { | ||
logger.info('[cid download] user canceled') | ||
return | ||
} | ||
|
||
const { getIpfsd } = ctx | ||
const ipfsd = await getIpfsd() | ||
|
||
if (!ipfsd) { | ||
return | ||
} | ||
|
||
let path | ||
try { | ||
path = await ipfsd.api.resolve(cid) | ||
} catch (_) { | ||
showDialog({ | ||
title: i18n.t('cantResolveCidDialog.title'), | ||
message: i18n.t('cantResolveCidDialog.message', { path: cid }), | ||
buttons: [i18n.t('close')] | ||
}) | ||
|
||
return | ||
} | ||
|
||
const dir = await dock.run(() => selectDirectory({ | ||
defaultPath: app.getPath('downloads') | ||
})) | ||
|
||
if (!dir) { | ||
logger.info(`[cid download] dropping ${path}: user didn't choose a path.`) | ||
return | ||
} | ||
|
||
let files | ||
|
||
try { | ||
logger.info(`[cid download] downloading ${path}: started`, { withAnalytics: 'DOWNLOAD_HASH' }) | ||
files = await ipfsd.api.get(path) | ||
logger.info(`[cid download] downloading ${path}: completed`) | ||
} catch (err) { | ||
logger.error(`[cid download] ${err.stack}`) | ||
|
||
showDialog({ | ||
title: i18n.t('couldNotGetCidDialog.title'), | ||
message: i18n.t('couldNotGetCidDialog.message', { path }), | ||
buttons: [i18n.t('close')] | ||
}) | ||
|
||
return | ||
} | ||
|
||
try { | ||
await Promise.all( | ||
files | ||
.filter(file => !!file.content) | ||
.map(file => saveFile(dir, file)) | ||
) | ||
|
||
const opt = showDialog({ | ||
title: i18n.t('contentsSavedDialog.title'), | ||
message: i18n.t('contentsSavedDialog.message', { path }), | ||
buttons: [ | ||
i18n.t('contentsSavedDialog.action'), | ||
i18n.t('close') | ||
] | ||
}) | ||
|
||
if (opt === 0) { | ||
shell.showItemInFolder(join(dir, files[0].path)) | ||
} | ||
} catch (err) { | ||
logger.error(`[cid download] ${err.toString()}`) | ||
|
||
showDialog({ | ||
title: i18n.t('couldNotSaveDialog.title'), | ||
message: i18n.t('couldNotSaveDialog.message'), | ||
buttons: [i18n.t('close')] | ||
}) | ||
} | ||
} | ||
|
||
module.exports = function (ctx) { | ||
setupGlobalShortcut(ctx, { | ||
settingsOption: CONFIG_KEY, | ||
accelerator: SHORTCUT, | ||
action: () => { | ||
downloadCid(ctx) | ||
} | ||
}) | ||
} | ||
|
||
module.exports.downloadCid = downloadCid | ||
module.exports.SHORTCUT = SHORTCUT |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
const { BrowserWindow, ipcMain, nativeTheme } = require('electron') | ||
const crypto = require('crypto') | ||
const { IS_MAC } = require('../common/consts') | ||
const makePage = require('./template') | ||
|
||
const pallette = { | ||
default: { | ||
background: '#ECECEC', | ||
color: '#262626', | ||
inputBackground: '#ffffff', | ||
defaultBackground: '#007AFF' | ||
}, | ||
dark: { | ||
background: '#323232', | ||
color: '#ffffff', | ||
inputBackground: '#656565', | ||
defaultBackground: '#0A84FF' | ||
} | ||
} | ||
|
||
function generatePage ({ message, defaultValue = '', buttons }, id) { | ||
buttons = buttons.map((txt, i) => `<button ${i === 0 ? 'class="default"' : ''} id="${i}">${txt}</button>`) | ||
|
||
if (IS_MAC) { | ||
buttons.reverse() | ||
} | ||
|
||
const page = makePage({ pallette, message, defaultValue, buttons, id }) | ||
return `data:text/html;base64,${Buffer.from(page, 'utf8').toString('base64')}` | ||
} | ||
|
||
module.exports = async function showPrompt (options = {}) { | ||
options.window = options.window || {} | ||
|
||
const window = new BrowserWindow({ | ||
title: options.title, | ||
show: false, | ||
width: 350, | ||
height: 330, | ||
resizable: false, | ||
autoHideMenuBar: true, | ||
fullscreenable: false, | ||
backgroundColor: nativeTheme.shouldUseDarkColors | ||
? pallette.dark.background | ||
: pallette.default.background, | ||
webPreferences: { | ||
nodeIntegration: true | ||
}, | ||
...options.window | ||
}) | ||
|
||
// Generate random id | ||
const id = crypto.randomBytes(16).toString('hex') | ||
|
||
return new Promise(resolve => { | ||
ipcMain.once(id, (_, data) => { | ||
window.destroy() | ||
resolve(data) | ||
}) | ||
|
||
window.on('close', () => { | ||
resolve({ input: '', button: null }) | ||
}) | ||
|
||
window.once('ready-to-show', () => { | ||
window.show() | ||
}) | ||
|
||
window.loadURL(generatePage(options, id)) | ||
}) | ||
} |
Oops, something went wrong.
1