Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion public/locales/en/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@
"save": "Save",
"cancel": "Cancel",
"enable": "Enable",
"disable": "Disable"
"disable": "Disable",
"import": "Import Key",
"export": "Export Key"
},
"edit": "Edit",
"visitService": "Visit service",
Expand Down
28 changes: 24 additions & 4 deletions src/bundles/ipns.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,12 @@ const ipnsBundle = {
doRemoveIpnsKey: (name) => async ({ getIpfs, store }) => {
const ipfs = getIpfs()
await ipfs.key.rm(name)

store.doFetchIpnsKeys()
},

doRenameIpnsKey: (oldName, newName) => async ({ getIpfs, store }) => {
const ipfs = getIpfs()
await ipfs.key.rename(oldName, newName)

store.doFetchIpnsKeys()
},

Expand All @@ -63,9 +61,31 @@ const ipnsBundle = {
await ipfs.name.publish(cid, { key })
},

doImportIpnsKey: (file) => async ({ getIpfs, store }) => {
const ipfs = getIpfs()
const reader = new FileReader()
reader.onload = async (event) => {
const key = event.target.result
await ipfs.key.import(file.name, key)
store.doFetchIpnsKeys()
}
reader.readAsText(file)
},

doExportIpnsKey: (name) => async ({ getIpfs }) => {
const ipfs = getIpfs()
const key = await ipfs.key.export(name)
const blob = new Blob([key], { type: 'text/plain' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `${name}.key`
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
},

doUpdateExpectedPublishTime: (time) => async ({ store, dispatch }) => {
// moderate expectation: publishing should take no longer than average
// between old expectation and the length of the last publish + some buffer
const oldExpectedTime = store.selectExpectedPublishTime()
const avg = Math.floor((time * 1.5 + oldExpectedTime) / 2)
await writeSetting('expectedPublishTime', avg)
Expand Down
32 changes: 26 additions & 6 deletions src/components/ipns-manager/IpnsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import Overlay from '../overlay/Overlay.js'
import GenerateKeyModal from './generate-key-modal/GenerateKeyModal.js'
import RenameKeyModal from './rename-key-modal/RenameKeyModal.js'
import RemoveKeyModal from './remove-key-modal/RemoveKeyModal.js'

import ContextMenu from '../context-menu/ContextMenu.js'
import ContextMenuItem from '../context-menu/ContextMenuItem.js'
import GlyphDots from '../../icons/GlyphDots.js'
Expand All @@ -19,14 +18,14 @@ import StrokeCancel from '../../icons/StrokeCancel.js'
const ROW_HEIGHT = 50
const HEADER_HEIGHT = 32

const AutoOptionsCell = ({ t, name, showRenameKeyModal, showRemoveKeyModal }) => (
const AutoOptionsCell = ({ t, name, showRenameKeyModal, showRemoveKeyModal, doExportIpnsKey }) => (
<div className='flex justify-end'>
{ name !== 'self' && <OptionsCell
name={name} t={t} showRenameKeyModal={showRenameKeyModal} showRemoveKeyModal={showRemoveKeyModal} /> }
name={name} t={t} showRenameKeyModal={showRenameKeyModal} showRemoveKeyModal={showRemoveKeyModal} doExportIpnsKey={doExportIpnsKey} /> }
</div>
)

const OptionsCell = ({ t, name, showRenameKeyModal, showRemoveKeyModal }) => {
const OptionsCell = ({ t, name, showRenameKeyModal, showRemoveKeyModal, doExportIpnsKey }) => {
const buttonRef = useRef()
const [isContextVisible, setContextVisibility] = useState(false)

Expand All @@ -48,12 +47,15 @@ const OptionsCell = ({ t, name, showRenameKeyModal, showRemoveKeyModal }) => {
<ContextMenuItem className='pv2 ph1' onClick={handle(showRemoveKeyModal)}>
<StrokeCancel width="28" className='fill-aqua'/> <span className="ph1">{t('app:actions.remove')}</span>
</ContextMenuItem>
<ContextMenuItem className='pv2 ph1' onClick={handle(doExportIpnsKey)}>
<StrokeCancel width="28" className='fill-aqua'/> <span className="ph1">{t('app:actions.export')}</span>
</ContextMenuItem>
</ContextMenu>
</div>
)
}

export const IpnsManager = ({ t, ipfsReady, doFetchIpnsKeys, doGenerateIpnsKey, doRenameIpnsKey, doRemoveIpnsKey, availableGateway, ipnsKeys }) => {
export const IpnsManager = ({ t, ipfsReady, doFetchIpnsKeys, doGenerateIpnsKey, doRenameIpnsKey, doRemoveIpnsKey, doImportIpnsKey, doExportIpnsKey, availableGateway, ipnsKeys }) => {
const [isGenerateKeyModalOpen, setGenerateKeyModalOpen] = useState(false)
const showGenerateKeyModal = () => setGenerateKeyModalOpen(true)
const hideGenerateKeyModal = () => setGenerateKeyModalOpen(false)
Expand Down Expand Up @@ -81,6 +83,13 @@ export const IpnsManager = ({ t, ipfsReady, doFetchIpnsKeys, doGenerateIpnsKey,
(ipnsKeys || []).sort(sortByProperty(sortSettings.sortBy, sortSettings.sortDirection === SortDirection.ASC ? 1 : -1)),
[ipnsKeys, sortSettings.sortBy, sortSettings.sortDirection])

const handleImportKey = (event) => {
const file = event.target.files[0]
if (file) {
doImportIpnsKey(file)
}
}

return (
<Fragment>
<div className="mv4 pinningManager">
Expand Down Expand Up @@ -125,7 +134,7 @@ export const IpnsManager = ({ t, ipfsReady, doFetchIpnsKeys, doGenerateIpnsKey,
dataKey='options'
width={width * 0.1}
flexShrink={1}
cellRenderer={({ rowData }) => <AutoOptionsCell t={t} name={rowData.name} showRenameKeyModal={showRenameKeyModal} showRemoveKeyModal={showRemoveKeyModal} />}
cellRenderer={({ rowData }) => <AutoOptionsCell t={t} name={rowData.name} showRenameKeyModal={showRenameKeyModal} showRemoveKeyModal={showRemoveKeyModal} doExportIpnsKey={() => doExportIpnsKey(rowData.name)} />}
className='pinningManagerColumn charcoal truncate f6 pl2' />
</Table>
)}
Expand All @@ -136,6 +145,15 @@ export const IpnsManager = ({ t, ipfsReady, doFetchIpnsKeys, doGenerateIpnsKey,
<Button className="tc mt2" bg='bg-navy' onClick={showGenerateKeyModal}>
<span><span className="aqua">+</span> {t('actions.generateKey')}</span>
</Button>
<input
type="file"
onChange={handleImportKey}
style={{ display: 'none' }}
id="ipns-key-import-input"
/>
<label htmlFor="ipns-key-import-input" className="button ma2">
{t('app:actions.import')}
</label>
</div>
</div>

Expand Down Expand Up @@ -189,5 +207,7 @@ export default connect(
'doGenerateIpnsKey',
'doRemoveIpnsKey',
'doRenameIpnsKey',
'doImportIpnsKey',
'doExportIpnsKey',
IpnsManager
)