Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jul 7, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 15 additions & 0 deletions app/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,21 @@ export function resolveName (name) {
return IPFS_CLIENT.name.resolve(name)
}

/**
* Publishes an IPFS hash to IPNS (the PeerID).
*
* Result looks like:
* {
* name:"QmPoXQhVxRAjMXLz7BaAAN1pQyKqHECK3K453oBRGnNvTQ"
* value:"/ipfs/QmPgcYEGLSBPJ8scQTsFRz8sz8X32cdZNQt3dSQb5fMMEQ"
* }
*/
export function publishToIPNS (hash) {
if (!IPFS_CLIENT) return Promise.reject(ERROR_IPFS_UNAVAILABLE)

return IPFS_CLIENT.name.publish(hash)
}

/**
* connectTo allows easily to connect to a node by specifying a str multiaddress
* example: connectTo("/ip4/192.168.0.22/tcp/4001/ipfs/Qm...")
Expand Down
29 changes: 29 additions & 0 deletions app/components/Input.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react'
import styled, { css } from 'styled-components'

const PhotonInput = ({ label, className, button, ...rest }) => {
return (
<div className={`form-group ${className}`}>
<label>{label}</label>
<input
className="form-control"
{...rest}
/>
{button || false}
</div>
)
}

const Input = styled(PhotonInput)`
${props => props.button && css`
.form-control {
width: calc(100% - 37px);
}
button {
margin-left: 5px;
height: 31px;
}
`}
`

export default Input
9 changes: 8 additions & 1 deletion app/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import electron, { BrowserWindow, Menu, app } from 'electron'
import ImportWindow from './windows/Import/window'
import SettingsWindow from './windows/Settings/window'
import ResolveIPNS from './windows/ResolveIPNS/window'
import PublishToIPNS from './windows/PublishToIPNS/window'

const template = [{
label: 'File',
Expand All @@ -18,10 +19,16 @@ const template = [{
}
}, {
label: 'Resolve IPNS',
accelerator: 'CmdOrCtrl+E',
accelerator: 'CmdOrCtrl+F',
click () {
ResolveIPNS.create(app)
}
}, {
label: 'Publish to IPNS',
accelerator: 'CmdOrCtrl+E',
click () {
PublishToIPNS.create(app)
}
}]
}, {
label: 'Edit',
Expand Down
21 changes: 21 additions & 0 deletions app/windows/PublishToIPNS/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>

<head>
<title>Publish to IPNS</title>
<style>
.window-content {
padding: 24px !important;
display: initial !important;
background-color: rgb(236, 236, 236) !important;
}
</style>
</head>

<body>
<div id="host"></div>
</body>

<!-- Electron Javascript -->
<script src="loader.js" charset="utf-8"></script>
</html>
7 changes: 7 additions & 0 deletions app/windows/PublishToIPNS/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Spinner from 'spin.js'

var target = document.getElementById('host')
new Spinner().spin(target)

// After the spinner is rendered, we require the actual component
setTimeout(() => require('./renderer.jsx'), 0)
116 changes: 116 additions & 0 deletions app/windows/PublishToIPNS/renderer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React from 'react'
import ReactDom from 'react-dom'

import { remote } from 'electron'
import { initIPFSClient, publishToIPNS, getPeer } from '../../api'
import { trackEvent } from '../../stats'
import { multihash as isMultiHash } from 'is-ipfs'

// Load Components
import {
Window,
Content,
Toolbar,
Actionbar,
Button
} from 'react-photonkit'
import ProgressOverlay from '../../components/ProgressOverlay'
import CircularProgress from '../../components/CircularProgress'
import Input from '../../components/Input'

class PublishToIPNSWindow extends React.Component {
state = {
loading: false,
hashValue: ''
}

componentDidMount () {
trackEvent('PublishToIPNSWindowOpen')
getPeer().then(peer => this.setState({ peer }))
}

handleCopyToClipboard = (event) => {
event.preventDefault()
const peerIdInput = document.getElementById('peer-id-input')
peerIdInput.select()
document.execCommand('copy')
}

handleSubmit = (event) => {
event.preventDefault()
const hash = this.state.hashValue

if (!isMultiHash(hash)) {
remote.dialog.showErrorBox('Error', 'Please provide a valid hash.')
return
}

this.setState({ loading: true })
publishToIPNS(hash)
.then(result => {
this.setState({ loading: false })
const message = `IPNS ${result.name} has been successfully updated to ${result.value}!`
remote.dialog.showMessageBox({ type: 'info', message, cancelId: 0, buttons: ['Ok'] })
window.close()
})
.catch(err => {
this.setState({ loading: false })
remote.dialog.showErrorBox('Error', err.message)
})
}

handleHashChange = (event) => {
this.setState({ hashValue: event.target.value })
}

render () {
const { loading, peer, hashValue } = this.state

return (
<form onSubmit={this.handleSubmit}>
<Window>
<Content>
<Input
id='peer-id-input'
label="Your peer ID"
type="text"
value={peer ? peer.id : 'Loading...'}
// using onChange instead of readOnly to allow the input to be selected
onChange={() => { }}
button={
<Button
glyph='doc-text'
onClick={this.handleCopyToClipboard}
/>
}
/>
<Input
value={hashValue}
onChange={this.handleHashChange}
label="Hash"
type="text"
placeholder="what would you like to publish?"
/>
<p>Note: this process may take a few minutes!</p>
</Content>
<Toolbar ptType="footer">
<Actionbar>
<Button text="Publish" ptStyle="primary" type="submit" pullRight />
<Button text="Close" ptStyle="default" onClick={window.close} />
</Actionbar>
</Toolbar>
{
loading &&
<ProgressOverlay>
<CircularProgress />
</ProgressOverlay>
}
</Window>
</form>
)
}
}

initIPFSClient()
// Render the ImportWindow
ReactDom.render(<PublishToIPNSWindow />, document.querySelector('#host'))
69 changes: 69 additions & 0 deletions app/windows/PublishToIPNS/window.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* This window will ask the user for a hash to be publish to IPNS under the peer's ID
*/

import path from 'path'
import url from 'url'

import { BrowserWindow, remote } from 'electron'

import isRenderer from 'is-electron-renderer'

// Allow us to use create() in both electron windows and main process
let BrowserWindowClass
if (isRenderer) {
BrowserWindowClass = remote.BrowserWindow
} else {
BrowserWindowClass = BrowserWindow
}

module.exports = {}

module.exports.create = function createResolveIPNSWindow (app) {
// Create the browser modal window.
let thisWindow = new BrowserWindowClass({
title: 'Publish to IPNS',
parent: app.mainWindow,
modal: true,

width: 525,
height: 265,
minWidth: 525,
minHeight: 265,

maximizable: false,
resizable: true,
fullscreenable: false,
icon: path.join(__dirname, '../../../docs/logo.png'),

show: false,
webPreferences: {
preload: path.join(__dirname, '../../report.js')
}
})

// Show menu only on StorageList
thisWindow.setMenu(null)

// Show the window only when ready
thisWindow.once('ready-to-show', () => {
thisWindow.show()
})

// Load the index.html of the app.
thisWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))

// Emitted when the window is closed.
thisWindow.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
thisWindow = null
})

return thisWindow
}
22 changes: 19 additions & 3 deletions app/windows/Settings/Components/ConnectivityPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import Settings from 'electron-settings'
import { observer } from 'mobx-react'
import { trackEvent } from '../../../stats'

import { Pane, Input, CheckBox } from 'react-photonkit'
import { Pane, Button, CheckBox } from 'react-photonkit'
import Input from '../../../components/Input'

const GatewayEnum = {
SIDERUS: 'https://siderus.io',
Expand Down Expand Up @@ -120,6 +121,13 @@ class ConnectivityPanel extends React.Component {
this.setState({ allowUserTracking: nextValue })
}

_handleCopyToClipboard = (event) => {
event.preventDefault()
const peerIdInput = document.getElementById('peer-id-input')
peerIdInput.select()
document.execCommand('copy')
}

render () {
if (this.props.navigationStore.selected !== 0) return null
if (!this.props.informationStore) return null
Expand All @@ -130,10 +138,18 @@ class ConnectivityPanel extends React.Component {
return (
<Pane className="settings">
<Input
id='peer-id-input'
label="Your peer ID"
type="text"
value={data.peer.id || '...'}
placeholder="Hey girl..." readOnly
value={data.peer ? data.peer.id : 'Loading...'}
// using onChange instead of readOnly to allow the input to be selected
onChange={() => { }}
button={
<Button
glyph='doc-text'
onClick={this._handleCopyToClipboard}
/>
}
/>

<Input
Expand Down
15 changes: 14 additions & 1 deletion app/windows/Storage/Components/StorageElement.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { remote } from 'electron'
import React from 'react'
import { Icon } from 'react-photonkit'

import { saveFileToPath } from '../../../api'
import { saveFileToPath, publishToIPNS } from '../../../api'

import {
proptAndRemoveObjects, openInBrowser
Expand Down Expand Up @@ -41,6 +41,19 @@ class StorageElement extends React.Component {
saveFileToPath(this.props.element.hash, dest[0])
}
},
{
label: 'Publish to IPNS',
click: (item) => {
publishToIPNS(this.props.element.hash)
.then(result => {
const message = `IPNS ${result.name} has been successfully updated to ${result.value}!`
remote.dialog.showMessageBox({ type: 'info', message, cancelId: 0, buttons: ['Ok'] })
})
.catch(err => {
remote.dialog.showErrorBox('Error', err.message)
})
}
},
{
label: 'Remove',
click: (item) => {
Expand Down