diff --git a/lib/boards-api.js b/lib/boards-api.js
index 0a80e52..92ae8f4 100644
--- a/lib/boards-api.js
+++ b/lib/boards-api.js
@@ -84,15 +84,57 @@ function BoardsAPI (ipfs) {
}
}
-BoardsAPI.prototype.createProfile = function (profile) {
- console.log('creating profile')
- this.ipfs.add(new Buffer(JSON.stringify(profile)), (err, res) => {
- console.log('added profile to IPFS:', err, res.Hash)
- var profilepath = '/ipfs/' + res.Hash
- this.ipfs.files.mv([profilepath, '/ipns/local/profile.json'], (err, res) => {
- console.log('mv', err, res)
- })
- })
+BoardsAPI.prototype.createProfile = function (profile, done) {
+ console.log('Generating profile:', profile)
+ try {
+ var profile_str = JSON.stringify(profile)
+ } catch (e) {
+ console.log('Error, invalid profile:', e)
+ return done(e)
+ }
+ asyncjs.waterfall([
+ // Create required directories
+ cb => this.ipfs.files.mkdir('/ipfs-boards-profile/boards', { p: true }, cb),
+ (e, cb) => this.ipfs.files.mkdir('/ipfs-boards-profile/comments', { p: true }, cb),
+ (e, cb) => this.ipfs.files.mkdir('/ipfs-boards-profile/posts', { p: true }, cb),
+ (e, cb) => {
+ // Remove old profile files if present
+ console.log('Removing file...')
+ var path = '/ipfs-boards-profile/ipfs-boards-version.txt'
+ this.ipfs.files.rm(path, { r: true }, res => {
+ console.log('Removing file...')
+ var path = '/ipfs-boards-profile/profile.json'
+ this.ipfs.files.rm(path, { r: true }, res => cb())
+ })
+ },
+ cb => {
+ // Add profile version file
+ var path = '/ipfs-boards-profile/ipfs-boards-version.txt'
+ var version_hash = '/ipfs/' + this.version_hash
+ this.ipfs.files.cp([version_hash, path], cb)
+ },
+ (e, cb) => {
+ // Serialize profile and add to IPFS
+ this.ipfs.add(new Buffer(profile_str), cb)
+ },
+ (res, cb) => {
+ // Move profile into mfs
+ console.log('added profile to IPFS:', res.Hash)
+ var profilepath = '/ipfs/' + res.Hash
+ this.ipfs.files.cp([profilepath, '/ipfs-boards-profile/profile.json'], cb)
+ },
+ (e, cb) => this.ipfs.files.stat('/', cb),
+ (res, cb) => {
+ var profile_hash = res.Hash
+ console.log('Publishing profile...')
+ this.ipfs.name.publish(profile_hash, cb)
+ // TODO: cb is probably never called here! Figure out why!
+ },
+ (e, cb) => {
+ console.log('Done')
+ cb()
+ }
+ ], done)
}
BoardsAPI.prototype.backupCache = function () {
@@ -112,6 +154,7 @@ BoardsAPI.prototype.resolveIPNS = function (n, handler) {
if (err) {
// Communicate error
this.ee.emit('error', err)
+ if (handler && handler.apply) handler(undefined, err)
} else {
var url = r.Path
if (url === undefined) {
@@ -527,7 +570,7 @@ BoardsAPI.prototype.init = function (done) {
this.id = res.ID
this.resolveIPNS(res.ID)
console.log('Version is', this.version)
- this.ipfs.add(new Buffer('ipfs:boards:version:' + this.version), {n: true}, (err2, r) => {
+ this.ipfs.add(new Buffer(this.version), (err2, r) => {
if (err2) {
this.ee.emit('error', err2)
console.log('Error while calculating version hash:', err2)
@@ -544,7 +587,7 @@ BoardsAPI.prototype.init = function (done) {
console.log('Error while getting ipfs version:', err)
if (done && done.apply) done(err)
} else {
- this.ipfs_version = res.Version
+ this.ipfs_version = res.Version.split('-')[0]
console.log('IPFS Version is', res.Version)
if (semver.satisfies(this.ipfs_version, '~0.4.0')) {
console.log('IPFS version is supported')
diff --git a/webapp/app.jsx b/webapp/app.jsx
index fa821e9..4ad0185 100644
--- a/webapp/app.jsx
+++ b/webapp/app.jsx
@@ -25,6 +25,7 @@ var Profile = require('profile.jsx')(boards)
var Board = require('board.jsx')(boards)
var PostPage = require('postpage.jsx')(boards)
var CommentPage = require('commentpage.jsx')(boards)
+var ProfileEditor = require('profile-editor.jsx')(boards)
// Define Main Components
@@ -91,6 +92,7 @@ ReactDOM.render(
{this.state.error.Message || this.state.error || 'connection to go-ipfs failed'}
+{this.state.error || 'connection to go-ipfs failed'}
You don't have an IPFS node running at {opt.addr}:{opt.port}
or it is not reachable.
The IPFS Boards prototype requires a full IPFS node. Please start one by following the
diff --git a/webapp/pages/profile-editor.jsx b/webapp/pages/profile-editor.jsx
new file mode 100644
index 0000000..0d7a08c
--- /dev/null
+++ b/webapp/pages/profile-editor.jsx
@@ -0,0 +1,94 @@
+var React = require('react')
+var GetIPFS = require('getipfs.jsx')
+var Icon = require('icon.jsx')
+
+module.exports = function (boardsAPI) {
+ return React.createClass({
+ getInitialState () {
+ return { loading: true }
+ },
+ componentDidMount () {
+ boardsAPI.use(boards => {
+ boards.init()
+ boards.getEventEmitter().on('init', err => {
+ if (!err && this.isMounted()) {
+ this.init(boards)
+ }
+ })
+ if (this.isMounted() && boards.isInit) {
+ this.init(boards)
+ }
+ })
+ },
+ getProfile (boards) {
+ boards.getProfile(boards.getMyID(), (err, p) => {
+ if (!this.isMounted()) return
+ else if (err) this.setState({ loading: false })
+ else if (this.state.loading) {
+ // State isn't set to p directly to avoid XSS.
+ // There is no knowing what's gonna be in a profile
+ // Should also convert to string and check length etc.
+ this.setState({ p: p.name, description: p.description, loading: false })
+ }
+ })
+ },
+ init (boards) {
+ if (this.state.init) return
+ this.setState({ api: boards })
+ this.getProfile(boards)
+ },
+ handleChange (event) {
+ if (event.target.id === 'name') {
+ this.setState({ name: event.target.value })
+ } else {
+ this.setState({ description: event.target.value })
+ }
+ },
+ skip () {
+ this.setState({ loading: false })
+ },
+ save () {
+ var boards = this.state.api
+ var profile = {
+ name: this.state.name,
+ description: this.state.description
+ }
+ boards.createProfile(profile, err => {
+ console.log('CREATE:', err)
+ })
+ },
+ render () {
+ if (this.state.api) {
+ if (this.state.loading) {
+ return
This App uses IPFS to store your profile. When you are offline, + other users or servers that viewed your profile will serve it to + others.
+