diff --git a/src/actions/actionTypes.js b/src/actions/actionTypes.js index e74a2fd..ac16145 100644 --- a/src/actions/actionTypes.js +++ b/src/actions/actionTypes.js @@ -1,23 +1,23 @@ -export const ADD_POST = 'ADD_POST' -export const EDIT_POST = 'EDIT_POST' -export const HIDE_POST = 'HIDE_POST' -export const UPDATE_BOARD_METADATA = 'UPDATE_BOARD_METADATA' +export const ADD_POST = 'ADD_POST'; +export const EDIT_POST = 'EDIT_POST'; +export const HIDE_POST = 'HIDE_POST'; +export const UPDATE_BOARD_METADATA = 'UPDATE_BOARD_METADATA'; -export const ADD_COMMENT = 'ADD_COMMENT' -export const EDIT_COMMENT = 'EDIT_COMMENT' -export const HIDE_COMMENT = 'HIDE_COMMENT' +export const ADD_COMMENT = 'ADD_COMMENT'; +export const EDIT_COMMENT = 'EDIT_COMMENT'; +export const HIDE_COMMENT = 'HIDE_COMMENT'; -export const OPEN_BOARD = 'OPEN_BOARD' -export const OPENED_BOARD = 'OPENED_BOARD' -export const CLOSE_BOARD = 'CLOSE_BOARD' +export const OPEN_BOARD = 'OPEN_BOARD'; +export const OPENED_BOARD = 'OPENED_BOARD'; +export const CLOSE_BOARD = 'CLOSE_BOARD'; -export const UPDATE_BOARD = 'UPDATE_BOARD' +export const UPDATE_BOARD = 'UPDATE_BOARD'; -export const ORBITDB_WRITE = 'ORBITDB_WRITE' +export const ORBITDB_WRITE = 'ORBITDB_WRITE'; -export const ORBITDB_REPLICATE = 'ORBITDB_REPLICATE' -export const ORBITDB_REPLICATE_PROGRESS = 'ORBITDB_REPLICATE_PROGRESS' -export const ORBITDB_REPLICATED = 'ORBITDB_REPLICATED' +export const ORBITDB_REPLICATE = 'ORBITDB_REPLICATE'; +export const ORBITDB_REPLICATE_PROGRESS = 'ORBITDB_REPLICATE_PROGRESS'; +export const ORBITDB_REPLICATED = 'ORBITDB_REPLICATED'; -export const ERROR = 'ERROR' \ No newline at end of file +export const ERROR = 'ERROR'; diff --git a/src/actions/board.js b/src/actions/board.js index 74102df..c36968b 100644 --- a/src/actions/board.js +++ b/src/actions/board.js @@ -1,35 +1,35 @@ import { - OPEN_BOARD, - CLOSE_BOARD, - OPENED_BOARD, - UPDATE_BOARD_METADATA -} from './actionTypes' + OPEN_BOARD, + CLOSE_BOARD, + OPENED_BOARD, + UPDATE_BOARD_METADATA, +} from './actionTypes'; export function openBoard(board) { - return { - type: OPEN_BOARD, - board - } + return { + type: OPEN_BOARD, + board, + }; } export function createdBoard(board) { - return { - type: OPENED_BOARD, - board - } + return { + type: OPENED_BOARD, + board, + }; } export function updateBoardMetadata(address, metadata) { - return { - type: UPDATE_BOARD_METADATA, - address, - metadata - } + return { + type: UPDATE_BOARD_METADATA, + address, + metadata, + }; } export function closeBoard(address) { - return { - type: CLOSE_BOARD, - address - } -} \ No newline at end of file + return { + type: CLOSE_BOARD, + address, + }; +} diff --git a/src/actions/comment.js b/src/actions/comment.js index 0732da6..51aa552 100644 --- a/src/actions/comment.js +++ b/src/actions/comment.js @@ -1,32 +1,32 @@ -import { HIDE_COMMENT, ADD_COMMENT, EDIT_COMMENT } from './actionTypes' +import { HIDE_COMMENT, ADD_COMMENT, EDIT_COMMENT } from './actionTypes'; export function addComment(address, postId, comment, replyTo = 'post') { - return { - type: ADD_COMMENT, - address, - postId, - comment, - replyTo - } + return { + type: ADD_COMMENT, + address, + postId, + comment, + replyTo, + }; } export function editComment(address, postId, commentId, comment, replyTo = 'post') { - return { - type: EDIT_COMMENT, - address, - postId, - commentId, - comment, - replyTo - } + return { + type: EDIT_COMMENT, + address, + postId, + commentId, + comment, + replyTo, + }; } export function hideComment(address, postId, commentId, replyTo = 'post') { - return { - type: HIDE_COMMENT, - address, - postId, - commentId, - replyTo - } -} \ No newline at end of file + return { + type: HIDE_COMMENT, + address, + postId, + commentId, + replyTo, + }; +} diff --git a/src/actions/post.js b/src/actions/post.js index 31f9c48..c80214f 100644 --- a/src/actions/post.js +++ b/src/actions/post.js @@ -1,26 +1,26 @@ -import { ADD_POST, EDIT_POST, HIDE_POST } from './actionTypes' +import { ADD_POST, EDIT_POST, HIDE_POST } from './actionTypes'; export function addPost(address, post) { - return { - type: ADD_POST, - post, - address - } + return { + type: ADD_POST, + post, + address, + }; } export function editPost(address, postId, post) { - return { - type: EDIT_POST, - address, - postId, - post, - } + return { + type: EDIT_POST, + address, + postId, + post, + }; } export function hidePost(address, postId) { - return { - type: HIDE_POST, - address, - postId - } -} \ No newline at end of file + return { + type: HIDE_POST, + address, + postId, + }; +} diff --git a/src/components/App.js b/src/components/App.js index a08e8eb..ed72ed2 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,20 +1,20 @@ import React, { Component } from 'react'; -import { Switch, Route, withRouter } from 'react-router-dom' -import Boards from '../containers/Boards' -import OpenBoard from '../containers/OpenBoard' -import WithBoard from '../containers/WithBoard' -import BoardPage from '../components/BoardPage' +import { Switch, Route, withRouter } from 'react-router-dom'; +import Boards from '../containers/Boards'; +import OpenBoard from '../containers/OpenBoard'; +import WithBoard from '../containers/WithBoard'; +import BoardPage from './BoardPage'; class App extends Component { render() { return ( - - - + + + - ) + ); } } -export default withRouter(App) +export default withRouter(App); diff --git a/src/containers/Board.js b/src/containers/Board.js index 6a714c9..f915744 100644 --- a/src/containers/Board.js +++ b/src/containers/Board.js @@ -1,21 +1,23 @@ -import React from 'react' -import { connect } from 'react-redux' -import BoardComponent from '../components/Board' -import { getBoardAddress } from '../utils/orbitdb' +import React from 'react'; +import { connect } from 'react-redux'; +import BoardComponent from '../components/Board'; +import { getBoardAddress } from '../utils/orbitdb'; -function Board({ stats, location, match, boards }) { - const { hash, name } = match.params - const address = getBoardAddress(hash, name) - const boardStats = stats.dbs[address] || {} - return +function Board({ + stats, location, match, boards, +}) { + const { hash, name } = match.params; + const address = getBoardAddress(hash, name); + const boardStats = stats.dbs[address] || {}; + return ; } -function mapStateToProps(state){ - return { - boards: state.boards.boards - } +function mapStateToProps(state) { + return { + boards: state.boards.boards, + }; } export default connect( - mapStateToProps -)(Board) + mapStateToProps, +)(Board); diff --git a/src/containers/BoardEditor.js b/src/containers/BoardEditor.js index f8b0dc6..beab548 100644 --- a/src/containers/BoardEditor.js +++ b/src/containers/BoardEditor.js @@ -1,35 +1,39 @@ -import React from 'react' -import { connect } from 'react-redux' -import BoardEditorForm from '../components/BoardEditorForm' -import { updateBoardMetadata } from '../actions/board' -import { getBoardAddress } from '../utils/orbitdb' +import React from 'react'; +import { connect } from 'react-redux'; +import BoardEditorForm from '../components/BoardEditorForm'; +import { updateBoardMetadata } from '../actions/board'; +import { getBoardAddress } from '../utils/orbitdb'; -function BoardEditor({ boards, boardEditor, match, updateBoardMetadata }) { - const { hash, name } = match.params - const address = getBoardAddress(hash, name) - const board = boards[address] - return + ); } -function mapStateToProps(state){ - return { - boards: state.boards.boards - } +function mapStateToProps(state) { + return { + boards: state.boards.boards, + }; } function mapDispatchToProps(dispatch) { - return { - updateBoardMetadata: (address, metadata) => dispatch(updateBoardMetadata(address, metadata)) - } + return { + updateBoardMetadata: (address, metadata) => dispatch(updateBoardMetadata(address, metadata)), + }; } export default connect( - mapStateToProps, - mapDispatchToProps -)(BoardEditor) + mapStateToProps, + mapDispatchToProps, +)(BoardEditor); diff --git a/src/containers/Boards.js b/src/containers/Boards.js index 74a99e0..2596103 100644 --- a/src/containers/Boards.js +++ b/src/containers/Boards.js @@ -1,34 +1,36 @@ -import React from 'react' -import { connect } from 'react-redux' -import { push } from 'connected-react-router' -import BoardsComponent from '../components/Boards' -import WithStats from './WithStats' -import { closeBoard } from '../actions/board' +import React from 'react'; +import { connect } from 'react-redux'; +import { push } from 'connected-react-router'; +import BoardsComponent from '../components/Boards'; +import WithStats from './WithStats'; +import { closeBoard } from '../actions/board'; -const WrappedComponent = WithStats(BoardsComponent) +const WrappedComponent = WithStats(BoardsComponent); function Boards({ boards, createBoard, closeBoard }) { - return + ); } -function mapStateToProps(state){ - return { - boards: state.boards.boards - } +function mapStateToProps(state) { + return { + boards: state.boards.boards, + }; } -function mapDispatchToProps(dispatch){ - return { - createBoard: () => dispatch(push('/b/new')), - closeBoard: address => dispatch(closeBoard(address)), - } +function mapDispatchToProps(dispatch) { + return { + createBoard: () => dispatch(push('/b/new')), + closeBoard: address => dispatch(closeBoard(address)), + }; } export default connect( - mapStateToProps, - mapDispatchToProps -)(Boards) + mapStateToProps, + mapDispatchToProps, +)(Boards); diff --git a/src/containers/OpenBoard.js b/src/containers/OpenBoard.js index 393d5f6..5280850 100644 --- a/src/containers/OpenBoard.js +++ b/src/containers/OpenBoard.js @@ -1,25 +1,25 @@ -import React from 'react' -import { connect } from 'react-redux' -import OpenBoardForm from '../components/OpenBoardForm' -import { openBoard } from '../actions/board' +import React from 'react'; +import { connect } from 'react-redux'; +import OpenBoardForm from '../components/OpenBoardForm'; +import { openBoard } from '../actions/board'; function OpenBoard(props) { - return + return ; } -function mapStateToProps(state){ - return { - opening: state.openBoard.opening - } +function mapStateToProps(state) { + return { + opening: state.openBoard.opening, + }; } function mapDispatchToProps(dispatch) { - return { - openBoard: board => dispatch(openBoard(board)) - } + return { + openBoard: board => dispatch(openBoard(board)), + }; } export default connect( - mapStateToProps, - mapDispatchToProps -)(OpenBoard) + mapStateToProps, + mapDispatchToProps, +)(OpenBoard); diff --git a/src/containers/PostEditor.js b/src/containers/PostEditor.js index 6585aab..cf09a71 100644 --- a/src/containers/PostEditor.js +++ b/src/containers/PostEditor.js @@ -1,32 +1,34 @@ -import React, { Component } from 'react' -import { connect } from 'react-redux' -import PostForm from '../components/PostForm' -import { addPost } from '../actions/post' +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import PostForm from '../components/PostForm'; +import { addPost } from '../actions/post'; import { getBoardAddress } from '../utils/orbitdb'; class PostEditor extends Component { - render() { - const { post, addPost, match, boards } = this.props - const address = getBoardAddress(match.params.hash, match.params.name) - const board = boards[address] - return addPost(address, p)} /> - } + render() { + const { + post, addPost, match, boards, + } = this.props; + const address = getBoardAddress(match.params.hash, match.params.name); + const board = boards[address]; + return addPost(address, p)} />; + } } -function mapStateToProps(state){ - return { - post: state.postEditor.post, - boards: state.boards.boards - } +function mapStateToProps(state) { + return { + post: state.postEditor.post, + boards: state.boards.boards, + }; } function mapDispatchToProps(dispatch) { - return { - addPost: (address, post) => dispatch(addPost(address, post)) - } + return { + addPost: (address, post) => dispatch(addPost(address, post)), + }; } export default connect( - mapStateToProps, - mapDispatchToProps -)(PostEditor) \ No newline at end of file + mapStateToProps, + mapDispatchToProps, +)(PostEditor); diff --git a/src/containers/WithBoard.js b/src/containers/WithBoard.js index f79f83d..157b009 100644 --- a/src/containers/WithBoard.js +++ b/src/containers/WithBoard.js @@ -1,53 +1,50 @@ -import React, { Component } from 'react' -import { connect } from 'react-redux' -import { openBoard } from '../actions/board' -import { getBoardAddress } from '../utils/orbitdb' +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { openBoard } from '../actions/board'; +import { getBoardAddress } from '../utils/orbitdb'; -function mapStateToProps(state){ - return { - boards: state.boards.boards - } +function mapStateToProps(state) { + return { + boards: state.boards.boards, + }; } -function mapDispatchToProps(dispatch){ - return { - openBoard: address => dispatch(openBoard({ address, redirect: false })) - } +function mapDispatchToProps(dispatch) { + return { + openBoard: address => dispatch(openBoard({ address, redirect: false })), + }; } export default function WithBoard(WrappedComponent) { - class ToExport extends Component { - - componentDidMount() { - const { boards, match } = this.props - const address = getBoardAddress(match.params.hash, match.params.name) - if (!boards[address]) { - this.props.openBoard(address) - } - } - - componentWillReceiveProps({ match, boards }) { - const address = getBoardAddress(match.params.hash, match.params.name) - if (!boards[address]) { - this.props.openBoard(address) - } - } - - render() { - const { boards, match } = this.props - const address = getBoardAddress(match.params.hash, match.params.name) - const board = boards[address] - if (board) { - return - } else { - return "Opening this board" - } - } + class ToExport extends Component { + componentDidMount() { + const { boards, match } = this.props; + const address = getBoardAddress(match.params.hash, match.params.name); + if (!boards[address]) { + this.props.openBoard(address); + } } - return connect( - mapStateToProps, - mapDispatchToProps - )(ToExport) + componentWillReceiveProps({ match, boards }) { + const address = getBoardAddress(match.params.hash, match.params.name); + if (!boards[address]) { + this.props.openBoard(address); + } + } -} \ No newline at end of file + render() { + const { boards, match } = this.props; + const address = getBoardAddress(match.params.hash, match.params.name); + const board = boards[address]; + if (board) { + return ; + } + return 'Opening this board'; + } + } + + return connect( + mapStateToProps, + mapDispatchToProps, + )(ToExport); +} diff --git a/src/containers/WithStats.js b/src/containers/WithStats.js index 80b55e4..fe01a7e 100644 --- a/src/containers/WithStats.js +++ b/src/containers/WithStats.js @@ -1,43 +1,43 @@ -import React, { Component } from 'react' -import { getStats } from '../utils/ipfs' +import React, { Component } from 'react'; +import { getStats } from '../utils/ipfs'; -export default function(WrappedComponent) { - return class extends Component { - constructor(props) { - super(props) - this.state = { - stats: { - id: '?', - peers: [], - pubKey: '?', - dbs: {} - }, - timeout: null - } - } - - async refresh(loop = true) { - const newStats = await getStats() - const stats = Object.assign({}, this.state.stats, newStats) - this.setState({ stats }, loop ? this.refreshDelayed.bind(this) : undefined) - } - - refreshDelayed() { - this.timeout = setTimeout(() => { - this.refresh() - }, 2000) - } - - componentDidMount() { - this.refresh() - } - - componentWillUnmount() { - if (this.timeout) clearTimeout(this.timeout) - } - - render() { - return - } +export default function (WrappedComponent) { + return class extends Component { + constructor(props) { + super(props); + this.state = { + stats: { + id: '?', + peers: [], + pubKey: '?', + dbs: {}, + }, + timeout: null, + }; } -} \ No newline at end of file + + async refresh(loop = true) { + const newStats = await getStats(); + const stats = Object.assign({}, this.state.stats, newStats); + this.setState({ stats }, loop ? this.refreshDelayed.bind(this) : undefined); + } + + refreshDelayed() { + this.timeout = setTimeout(() => { + this.refresh(); + }, 2000); + } + + componentDidMount() { + this.refresh(); + } + + componentWillUnmount() { + if (this.timeout) clearTimeout(this.timeout); + } + + render() { + return ; + } + }; +} diff --git a/src/index.js b/src/index.js index d36ed9f..d1d9a56 100644 --- a/src/index.js +++ b/src/index.js @@ -1,13 +1,13 @@ -import 'react-hot-loader/patch' -import React from 'react' -import { render } from 'react-dom' -import { AppContainer } from 'react-hot-loader' -import configureStore, { history } from './store/configureStore' -import App from './components/App' -import registerServiceWorker from './registerServiceWorker' -import { Provider } from 'react-redux' -import { ConnectedRouter } from 'connected-react-router' -import { start } from './orbitdb' +import 'react-hot-loader/patch'; +import React from 'react'; +import { render } from 'react-dom'; +import { AppContainer } from 'react-hot-loader'; +import { Provider } from 'react-redux'; +import { ConnectedRouter } from 'connected-react-router'; +import configureStore, { history } from './store/configureStore'; +import App from './components/App'; +import registerServiceWorker from './registerServiceWorker'; +import { start } from './orbitdb'; const store = configureStore(); @@ -19,12 +19,12 @@ render( , - document.getElementById('root') + document.getElementById('root'), ); if (module.hot) { module.hot.accept('./components/App', () => { - const NewApp = require('./components/App').default + const NewApp = require('./components/App').default; render( @@ -33,10 +33,10 @@ if (module.hot) { , - document.getElementById('root') - ) - }) + document.getElementById('root'), + ); + }); } -registerServiceWorker() -start(store.dispatch) \ No newline at end of file +registerServiceWorker(); +start(store.dispatch); diff --git a/src/orbitdb/constants.js b/src/orbitdb/constants.js index 6509427..a56107b 100644 --- a/src/orbitdb/constants.js +++ b/src/orbitdb/constants.js @@ -5,4 +5,4 @@ module.exports = { ADD_COMMENT: 'ADD_COMMENT', UPDATE_COMMENT: 'UPDATE_COMMENT', UPDATE_METADATA: 'UPDATE_METADATA', -}; \ No newline at end of file +}; diff --git a/src/orbitdb/index.js b/src/orbitdb/index.js index 7d8a1a2..dbc72f5 100644 --- a/src/orbitdb/index.js +++ b/src/orbitdb/index.js @@ -1,15 +1,15 @@ -import IPFS from 'ipfs' -import OrbitDB from 'orbit-db' -import BoardStore from 'orbit-db-discussion-board' -import multihashes from 'multihashes' +import IPFS from 'ipfs'; +import OrbitDB from 'orbit-db'; +import BoardStore from 'orbit-db-discussion-board'; +import multihashes from 'multihashes'; export function isValidID(id) { try { - if (typeof id === 'string' && multihashes.fromB58String(id)) return true + if (typeof id === 'string' && multihashes.fromB58String(id)) return true; } catch (error) { - return false + return false; } - return false + return false; } export async function start() { @@ -17,96 +17,96 @@ export async function start() { window.ipfs = new IPFS({ repo: 'ipfs-v6-boards-v0', EXPERIMENTAL: { - pubsub: true - } + pubsub: true, + }, + }); + await new Promise((resolve) => { + window.ipfs.on('ready', () => resolve()); }); - await new Promise(resolve => { - window.ipfs.on('ready', () => resolve()) - }) } if (!window.orbitDb) { - OrbitDB.addDatabaseType(BoardStore.type, BoardStore) - window.orbitDb = new OrbitDB(window.ipfs) + OrbitDB.addDatabaseType(BoardStore.type, BoardStore); + window.orbitDb = new OrbitDB(window.ipfs); } } export async function open(address, metadata) { - if (window.dbs && window.dbs[address]) return window.dbs[address] - await start() + if (window.dbs && window.dbs[address]) return window.dbs[address]; + await start(); const options = { type: BoardStore.type, create: true, - write: ['*'] - } - const db = await window.orbitDb.open(address, options) - await db.load() + write: ['*'], + }; + const db = await window.orbitDb.open(address, options); + await db.load(); if (metadata) { - await db.updateMetadata(metadata) + await db.updateMetadata(metadata); } - if (!window.dbs) window.dbs = {} - window.dbs[db.address.toString()] = db - return db + if (!window.dbs) window.dbs = {}; + window.dbs[db.address.toString()] = db; + return db; } export function connectDb(db, dispatch) { db.events.on('write', (dbname, hash, entry) => { dispatch({ - type: 'ORBITDB_WRITE', - time: Date.now(), - address: db.address.toString(), - hash, - entry - }) - }) - db.events.on('replicated', address => { + type: 'ORBITDB_WRITE', + time: Date.now(), + address: db.address.toString(), + hash, + entry, + }); + }); + db.events.on('replicated', (address) => { dispatch({ - type: 'ORBITDB_REPLICATED', - time: Date.now(), - address: db.address.toString() - }) - }) + type: 'ORBITDB_REPLICATED', + time: Date.now(), + address: db.address.toString(), + }); + }); db.events.on('replicate.progress', (address, hash, entry, progress, have) => { dispatch({ - type: 'ORBITDB_REPLICATE_PROGRESS', - address: db.address.toString(), - hash, - entry, - progress, - have, - time: Date.now(), - replicationInfo: Object.assign({}, db._replicationInfo) - }) - }) - db.events.on('replicate', address => { + type: 'ORBITDB_REPLICATE_PROGRESS', + address: db.address.toString(), + hash, + entry, + progress, + have, + time: Date.now(), + replicationInfo: Object.assign({}, db._replicationInfo), + }); + }); + db.events.on('replicate', (address) => { dispatch({ - type: 'ORBITDB_REPLICATE', - time: Date.now(), - address: db.address.toString() - }) - }) - db.events.on('close', address => { + type: 'ORBITDB_REPLICATE', + time: Date.now(), + address: db.address.toString(), + }); + }); + db.events.on('close', (address) => { dispatch({ - type: 'ORBITDB_CLOSE', - time: Date.now(), - address: db.address.toString() - }) - }) - db.events.on('load', address => { + type: 'ORBITDB_CLOSE', + time: Date.now(), + address: db.address.toString(), + }); + }); + db.events.on('load', (address) => { dispatch({ - type: 'ORBITDB_LOAD', - time: Date.now(), - address: db.address.toString() - }) - }) + type: 'ORBITDB_LOAD', + time: Date.now(), + address: db.address.toString(), + }); + }); db.events.on('load.progress', (address, hash, entry, progress, total) => { dispatch({ - type: 'ORBITDB_LOAD_PROGRESS', - time: Date.now(), - address: db.address.toString(), - hash, - entry, - progress, - total - }) - }) + type: 'ORBITDB_LOAD_PROGRESS', + time: Date.now(), + address: db.address.toString(), + hash, + entry, + progress, + total, + }); + }); } diff --git a/src/reducers/boards.js b/src/reducers/boards.js index 16b4474..95e1b8e 100644 --- a/src/reducers/boards.js +++ b/src/reducers/boards.js @@ -1,63 +1,69 @@ import { - OPENED_BOARD, - CLOSE_BOARD, - UPDATE_BOARD, - ORBITDB_REPLICATE_PROGRESS, - ORBITDB_REPLICATED, - ORBITDB_REPLICATE -} from '../actions/actionTypes' + OPENED_BOARD, + CLOSE_BOARD, + UPDATE_BOARD, + ORBITDB_REPLICATE_PROGRESS, + ORBITDB_REPLICATED, + ORBITDB_REPLICATE, +} from '../actions/actionTypes'; function getInitialState() { - return { - boards: {} - } + return { + boards: {}, + }; } function updateBoard(existingBoards, address, value) { - return Object.assign({}, existingBoards, { - [address]: Object.assign({}, existingBoards[address] || {}, value) - }) + return Object.assign({}, existingBoards, { + [address]: Object.assign({}, existingBoards[address] || {}, value), + }); } function deleteBoard(existingBoards, address) { - const boards = Object.assign({}, existingBoards) - delete boards[address] - return boards + const boards = Object.assign({}, existingBoards); + delete boards[address]; + return boards; } export default function BoardsReducer(state = getInitialState(), action) { - let address - switch (action.type) { - case OPENED_BOARD: - address = action.board.address - return Object.assign({}, state, { boards: updateBoard(state.boards, address, Object.assign({}, action.board, { open: true })) }) - case UPDATE_BOARD: - address = action.address - let { posts, metadata } = action - return Object.assign({}, state, { boards: updateBoard(state.boards, address, { posts, metadata })}) - case ORBITDB_REPLICATE: - address = action.address - return Object.assign({}, state, { boards: updateBoard(state.boards, address, { - replicating: true - })}) - case ORBITDB_REPLICATE_PROGRESS: - address = action.address - return Object.assign({}, state, { boards: updateBoard(state.boards, address, { - replicating: true, - replicationInfo: action.replicationInfo - })}) - case ORBITDB_REPLICATED: - address = action.address - return Object.assign({}, state, { boards: updateBoard(state.boards, address, { - replicating: false, - lastReplicated: action.time - })}) - case CLOSE_BOARD: - address = action.address - return Object.assign({}, state, { - boards: deleteBoard(state.boards, address) - }) - default: - return state; - } -} \ No newline at end of file + let address; + switch (action.type) { + case OPENED_BOARD: + address = action.board.address; + return Object.assign({}, state, { boards: updateBoard(state.boards, address, Object.assign({}, action.board, { open: true })) }); + case UPDATE_BOARD: + address = action.address; + const { posts, metadata } = action; + return Object.assign({}, state, { boards: updateBoard(state.boards, address, { posts, metadata }) }); + case ORBITDB_REPLICATE: + address = action.address; + return Object.assign({}, state, { + boards: updateBoard(state.boards, address, { + replicating: true, + }), + }); + case ORBITDB_REPLICATE_PROGRESS: + address = action.address; + return Object.assign({}, state, { + boards: updateBoard(state.boards, address, { + replicating: true, + replicationInfo: action.replicationInfo, + }), + }); + case ORBITDB_REPLICATED: + address = action.address; + return Object.assign({}, state, { + boards: updateBoard(state.boards, address, { + replicating: false, + lastReplicated: action.time, + }), + }); + case CLOSE_BOARD: + address = action.address; + return Object.assign({}, state, { + boards: deleteBoard(state.boards, address), + }); + default: + return state; + } +} diff --git a/src/reducers/index.js b/src/reducers/index.js index 305946a..fa88cce 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,12 +1,12 @@ -import { combineReducers } from 'redux' -import { connectRouter} from 'connected-react-router' -import postReducer from './post' -import boardsReducer from './boards' -import openBoardReducer from './openboard' +import { combineReducers } from 'redux'; +import { connectRouter } from 'connected-react-router'; +import postReducer from './post'; +import boardsReducer from './boards'; +import openBoardReducer from './openboard'; export default history => combineReducers({ - router: connectRouter(history), - postEditor: postReducer, - boards: boardsReducer, - openBoard: openBoardReducer -}) \ No newline at end of file + router: connectRouter(history), + postEditor: postReducer, + boards: boardsReducer, + openBoard: openBoardReducer, +}); diff --git a/src/reducers/openboard.js b/src/reducers/openboard.js index b81919d..aef1ff6 100644 --- a/src/reducers/openboard.js +++ b/src/reducers/openboard.js @@ -1,21 +1,21 @@ import { - OPEN_BOARD, - OPENED_BOARD -} from '../actions/actionTypes' + OPEN_BOARD, + OPENED_BOARD, +} from '../actions/actionTypes'; function getInitialState() { - return { - opening: false - } + return { + opening: false, + }; } export default function openBoardReducer(state = getInitialState(), action) { - switch (action.type) { - case OPEN_BOARD: - return Object.assign({}, state, { opening: true }) - case OPENED_BOARD: - return Object.assign({}, state, { opening: false }) - default: - return state - } -} \ No newline at end of file + switch (action.type) { + case OPEN_BOARD: + return Object.assign({}, state, { opening: true }); + case OPENED_BOARD: + return Object.assign({}, state, { opening: false }); + default: + return state; + } +} diff --git a/src/reducers/post.js b/src/reducers/post.js index 73b8819..9b6b502 100644 --- a/src/reducers/post.js +++ b/src/reducers/post.js @@ -1,19 +1,19 @@ -import { ADD_POST } from '../actions/actionTypes' +import { ADD_POST } from '../actions/actionTypes'; -function getInitialState(){ - return { - post: { - title: '', - content: '' - } - } +function getInitialState() { + return { + post: { + title: '', + content: '', + }, + }; } -export default function(state = getInitialState(), action) { - switch (action.type) { - case ADD_POST: - return Object.assign({}, state, { post: action.post }) - default: - return state - } -} \ No newline at end of file +export default function (state = getInitialState(), action) { + switch (action.type) { + case ADD_POST: + return Object.assign({}, state, { post: action.post }); + default: + return state; + } +} diff --git a/src/registerServiceWorker.js b/src/registerServiceWorker.js index a3e6c0c..df360c3 100644 --- a/src/registerServiceWorker.js +++ b/src/registerServiceWorker.js @@ -9,13 +9,13 @@ // This link also includes instructions on opting out of this behavior. const isLocalhost = Boolean( - window.location.hostname === 'localhost' || + window.location.hostname === 'localhost' // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || + || window.location.hostname === '[::1]' // 127.0.0.1/8 is considered localhost for IPv4. - window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) + || window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/, + ), ); export default function register() { @@ -40,8 +40,8 @@ export default function register() { // service worker/PWA documentation. navigator.serviceWorker.ready.then(() => { console.log( - 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://goo.gl/SC7cgQ' + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://goo.gl/SC7cgQ', ); }); } else { @@ -55,7 +55,7 @@ export default function register() { function registerValidSW(swUrl) { navigator.serviceWorker .register(swUrl) - .then(registration => { + .then((registration) => { registration.onupdatefound = () => { const installingWorker = registration.installing; installingWorker.onstatechange = () => { @@ -76,7 +76,7 @@ function registerValidSW(swUrl) { }; }; }) - .catch(error => { + .catch((error) => { console.error('Error during service worker registration:', error); }); } @@ -84,14 +84,14 @@ function registerValidSW(swUrl) { function checkValidServiceWorker(swUrl) { // Check if the service worker can be found. If it can't reload the page. fetch(swUrl) - .then(response => { + .then((response) => { // Ensure service worker exists, and that we really are getting a JS file. if ( - response.status === 404 || - response.headers.get('content-type').indexOf('javascript') === -1 + response.status === 404 + || response.headers.get('content-type').indexOf('javascript') === -1 ) { // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { + navigator.serviceWorker.ready.then((registration) => { registration.unregister().then(() => { window.location.reload(); }); @@ -103,14 +103,14 @@ function checkValidServiceWorker(swUrl) { }) .catch(() => { console.log( - 'No internet connection found. App is running in offline mode.' + 'No internet connection found. App is running in offline mode.', ); }); } export function unregister() { if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready.then(registration => { + navigator.serviceWorker.ready.then((registration) => { registration.unregister(); }); } diff --git a/src/sagas/boards.js b/src/sagas/boards.js index 4944423..2b96395 100644 --- a/src/sagas/boards.js +++ b/src/sagas/boards.js @@ -1,79 +1,81 @@ -import { put, call, fork, take } from 'redux-saga/effects' -import { eventChannel } from 'redux-saga' -import { push } from 'connected-react-router' -import { open, connectDb } from '../orbitdb' -import { createdBoard } from '../actions/board' -import { shortenAddress, closeBoard as closeOrbitDBBoard } from '../utils/orbitdb' -import { UPDATE_BOARD } from '../actions/actionTypes' -import { saveSaga } from './persistence' +import { + put, call, fork, take, +} from 'redux-saga/effects'; +import { eventChannel } from 'redux-saga'; +import { push } from 'connected-react-router'; +import { open, connectDb } from '../orbitdb'; +import { createdBoard } from '../actions/board'; +import { shortenAddress, closeBoard as closeOrbitDBBoard } from '../utils/orbitdb'; +import { UPDATE_BOARD } from '../actions/actionTypes'; +import { saveSaga } from './persistence'; -export function* goToBoard({ board }){ - if (board.redirect) { - yield put(push(shortenAddress(board.address))) - } +export function* goToBoard({ board }) { + if (board.redirect) { + yield put(push(shortenAddress(board.address))); + } } -export function* updateBoard({ address }){ - const db = window.dbs[address] - yield put({ - type: UPDATE_BOARD, - address, - posts: db.posts, - metadata: Object.assign({}, db._index._index.metadata) // TODO: fix in lib and use db.metadata - }) +export function* updateBoard({ address }) { + const db = window.dbs[address]; + yield put({ + type: UPDATE_BOARD, + address, + posts: db.posts, + metadata: Object.assign({}, db._index._index.metadata), // TODO: fix in lib and use db.metadata + }); } -export function* closeBoard({ address }){ - yield call(closeOrbitDBBoard, address) - yield saveSaga() +export function* closeBoard({ address }) { + yield call(closeOrbitDBBoard, address); + yield saveSaga(); } -export function* updateBoardMetadata({ address, metadata }){ - const db = window.dbs[address] - if (db) { - yield call([db, db.updateMetadata], [metadata]) - yield goToBoard({ board: { address } }); - } else { - yield put({ type: 'ERROR', error: address + ' not found' }) - } +export function* updateBoardMetadata({ address, metadata }) { + const db = window.dbs[address]; + if (db) { + yield call([db, db.updateMetadata], [metadata]); + yield goToBoard({ board: { address } }); + } else { + yield put({ type: 'ERROR', error: `${address} not found` }); + } } export function* openBoard({ board }) { - let db + let db; + try { + const metadata = board.title ? { title: board.title } : null; + db = yield call(open, board.address, metadata); + } catch (error) { + yield put({ type: 'ERROR', error }); + } + if (db) { + const address = db.address.toString(); + const dbInfo = { address }; + dbInfo.posts = db.posts; + dbInfo.metadata = Object.assign({}, db._index._index.metadata); // TODO: fix in lib and use db.metadata + dbInfo.name = db.dbname; try { - const metadata = board.title ? { title: board.title } : null - db = yield call(open, board.address, metadata) + const channel = yield call(createDbEventChannel, db); + yield fork(watchDb, channel); + yield put(createdBoard(Object.assign({ redirect: !!board.redirect }, board, dbInfo))); } catch (error) { - yield put({ type: 'ERROR', error }) - } - if (db) { - const address = db.address.toString() - const dbInfo = { address } - dbInfo.posts = db.posts - dbInfo.metadata = Object.assign({}, db._index._index.metadata) // TODO: fix in lib and use db.metadata - dbInfo.name = db.dbname - try { - const channel = yield call(createDbEventChannel, db) - yield fork(watchDb, channel) - yield put(createdBoard(Object.assign({ redirect: !!board.redirect }, board, dbInfo))) - } catch (error) { - yield put({ type: 'ERROR', error }) - } + yield put({ type: 'ERROR', error }); } + } } function* watchDb(channel) { - // Dispatches action coming from the channel, terminates when ORBITDB_CLOSE arrives - let action - while(!action || action.type !== 'ORBITDB_CLOSE') { - action = yield take(channel) - yield put(action) - } + // Dispatches action coming from the channel, terminates when ORBITDB_CLOSE arrives + let action; + while (!action || action.type !== 'ORBITDB_CLOSE') { + action = yield take(channel); + yield put(action); + } } function createDbEventChannel(db) { - return eventChannel(emitter => { - connectDb(db, emitter) - return () => db.close() - }) -} \ No newline at end of file + return eventChannel((emitter) => { + connectDb(db, emitter); + return () => db.close(); + }); +} diff --git a/src/sagas/index.js b/src/sagas/index.js index 5c0766a..3ef874a 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -1,28 +1,30 @@ -import { takeEvery, put, call } from 'redux-saga/effects' +import { takeEvery, put, call } from 'redux-saga/effects'; import { - OPEN_BOARD, - OPENED_BOARD, - CLOSE_BOARD, - ADD_POST, - ORBITDB_REPLICATED, - ORBITDB_WRITE, - UPDATE_BOARD_METADATA -} from '../actions/actionTypes' -import { openBoard, updateBoard, goToBoard, updateBoardMetadata, closeBoard } from './boards' -import { addPost } from './posts' -import { openPreviousBoards, saveSaga } from './persistence' + OPEN_BOARD, + OPENED_BOARD, + CLOSE_BOARD, + ADD_POST, + ORBITDB_REPLICATED, + ORBITDB_WRITE, + UPDATE_BOARD_METADATA, +} from '../actions/actionTypes'; +import { + openBoard, updateBoard, goToBoard, updateBoardMetadata, closeBoard, +} from './boards'; +import { addPost } from './posts'; +import { openPreviousBoards, saveSaga } from './persistence'; -export default function* saga(){ - yield takeEvery(OPEN_BOARD, openBoard) - yield takeEvery(OPENED_BOARD, goToBoard) - yield takeEvery(OPENED_BOARD, saveSaga) - yield takeEvery(CLOSE_BOARD, closeBoard) +export default function* saga() { + yield takeEvery(OPEN_BOARD, openBoard); + yield takeEvery(OPENED_BOARD, goToBoard); + yield takeEvery(OPENED_BOARD, saveSaga); + yield takeEvery(CLOSE_BOARD, closeBoard); - yield takeEvery(ADD_POST, addPost) - yield takeEvery(UPDATE_BOARD_METADATA, updateBoardMetadata) + yield takeEvery(ADD_POST, addPost); + yield takeEvery(UPDATE_BOARD_METADATA, updateBoardMetadata); - yield takeEvery(ORBITDB_WRITE, updateBoard) - yield takeEvery(ORBITDB_REPLICATED, updateBoard) + yield takeEvery(ORBITDB_WRITE, updateBoard); + yield takeEvery(ORBITDB_REPLICATED, updateBoard); - yield openPreviousBoards() -} \ No newline at end of file + yield openPreviousBoards(); +} diff --git a/src/sagas/persistence.js b/src/sagas/persistence.js index f0df9a5..d196f7c 100644 --- a/src/sagas/persistence.js +++ b/src/sagas/persistence.js @@ -1,16 +1,16 @@ -import { call, put } from 'redux-saga/effects' -import { openBoard } from '../actions/board' -import { save, load } from '../utils/persistence' +import { call, put } from 'redux-saga/effects'; +import { openBoard } from '../actions/board'; +import { save, load } from '../utils/persistence'; export function* openPreviousBoards() { - const data = yield call(load) - if (Array.isArray(data.addresses)) { - for (const address of data.addresses) { - yield put(openBoard({ address, redirect: false })) - } + const data = yield call(load); + if (Array.isArray(data.addresses)) { + for (const address of data.addresses) { + yield put(openBoard({ address, redirect: false })); } + } } export function* saveSaga() { - yield call(save) -} \ No newline at end of file + yield call(save); +} diff --git a/src/sagas/posts.js b/src/sagas/posts.js index 60d9f85..f880a9b 100644 --- a/src/sagas/posts.js +++ b/src/sagas/posts.js @@ -1,18 +1,18 @@ -import { call } from 'redux-saga/effects' +import { call } from 'redux-saga/effects'; import { goToBoard } from './boards'; export function* addPost({ address, post }) { - const db = window.dbs[address] - const { title, text } = post - yield call([db, db.addPost], { title, text }) - yield goToBoard({ board: { address, redirect: true } }); - // TODO: goto post + const db = window.dbs[address]; + const { title, text } = post; + yield call([db, db.addPost], { title, text }); + yield goToBoard({ board: { address, redirect: true } }); + // TODO: goto post } export function* editPost({ address, postId, post }) { - const db = window.dbs[address] - const { title, text } = post - yield call([db, db.updatePost], postId, { title, text }) - yield goToBoard({ board: { address, redirect: true } }); - // TODO: goto post -} \ No newline at end of file + const db = window.dbs[address]; + const { title, text } = post; + yield call([db, db.updatePost], postId, { title, text }); + yield goToBoard({ board: { address, redirect: true } }); + // TODO: goto post +} diff --git a/src/store/configureStore.js b/src/store/configureStore.js index 09d2560..f097bd3 100644 --- a/src/store/configureStore.js +++ b/src/store/configureStore.js @@ -1,9 +1,9 @@ -import {createStore, compose, applyMiddleware} from 'redux'; +import { createStore, compose, applyMiddleware } from 'redux'; import reduxImmutableStateInvariant from 'redux-immutable-state-invariant'; import createSagaMiddleware from 'redux-saga'; -import saga from '../sagas'; import createHistory from 'history/createHashHistory'; import { routerMiddleware } from 'connected-react-router'; +import saga from '../sagas'; import createRootReducer from '../reducers'; const sagaMiddleware = createSagaMiddleware(); @@ -17,9 +17,8 @@ function configureStoreProd(initialState) { ]; const store = createStore(createRootReducer(history), initialState, compose( - applyMiddleware(...middlewares) - ) - ); + applyMiddleware(...middlewares), + )); sagaMiddleware.run(saga); @@ -36,9 +35,8 @@ function configureStoreDev(initialState) { const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // add support for Redux dev tools const store = createStore(createRootReducer(history), initialState, composeEnhancers( - applyMiddleware(...middlewares) - ) - ); + applyMiddleware(...middlewares), + )); let sagaTask = sagaMiddleware.run(saga); diff --git a/src/utils/ipfs.js b/src/utils/ipfs.js index 4b5de1d..5457c0b 100644 --- a/src/utils/ipfs.js +++ b/src/utils/ipfs.js @@ -1,55 +1,55 @@ export async function ipfsPut(content) { - const obj = { - content: Buffer.from(content), - path: '/' - } - const response = await window.ipfs.files.add(obj) - return response[0].hash + const obj = { + content: Buffer.from(content), + path: '/', + }; + const response = await window.ipfs.files.add(obj); + return response[0].hash; } export async function readText(multihash) { - const buffer = await window.ipfs.object.get(multihash) - return buffer.toString('utf-8') + const buffer = await window.ipfs.object.get(multihash); + return buffer.toString('utf-8'); } export async function getStats() { - const ipfs = window.ipfs; - const orbitDb = window.orbitDb - const dbs = {} - const stats = {} - if (ipfs && ipfs.isOnline()) { - stats.ipfsLoaded = true - const peers = await ipfs.swarm.peers() - const id = await ipfs.id() - stats.peers = peers.map(p => p.peer.id._idB58String) - stats.id = id.id - } else { - stats.ipfsLoaded = false - } - if (stats.ipfsLoaded && orbitDb) { - stats.orbitDbLoaded = true - stats.pubKey = await orbitDb.key.getPublic('hex') - Object.values(window.dbs || {}).forEach(db => { - let writeable = db.access.write.indexOf('*') >= 0 || db.access.write.indexOf(stats.pubKey) >= 0 - const dbInfo = { - opLogLength: db._oplog.length, - access: { - admin: db.access.admin, - read: db.access.read, - write: db.access.write, - writeable - }, - peers: [] - } - const subscription = orbitDb._pubsub._subscriptions[db.address] - if (subscription && subscription.room) { - dbInfo.peers = [...(subscription.room._peers || [])] - } - dbs[db.address] = dbInfo - }) - } else { - stats.orbitDbLoaded = false - } - stats.dbs = dbs - return stats -} \ No newline at end of file + const ipfs = window.ipfs; + const orbitDb = window.orbitDb; + const dbs = {}; + const stats = {}; + if (ipfs && ipfs.isOnline()) { + stats.ipfsLoaded = true; + const peers = await ipfs.swarm.peers(); + const id = await ipfs.id(); + stats.peers = peers.map(p => p.peer.id._idB58String); + stats.id = id.id; + } else { + stats.ipfsLoaded = false; + } + if (stats.ipfsLoaded && orbitDb) { + stats.orbitDbLoaded = true; + stats.pubKey = await orbitDb.key.getPublic('hex'); + Object.values(window.dbs || {}).forEach((db) => { + const writeable = db.access.write.indexOf('*') >= 0 || db.access.write.indexOf(stats.pubKey) >= 0; + const dbInfo = { + opLogLength: db._oplog.length, + access: { + admin: db.access.admin, + read: db.access.read, + write: db.access.write, + writeable, + }, + peers: [], + }; + const subscription = orbitDb._pubsub._subscriptions[db.address]; + if (subscription && subscription.room) { + dbInfo.peers = [...(subscription.room._peers || [])]; + } + dbs[db.address] = dbInfo; + }); + } else { + stats.orbitDbLoaded = false; + } + stats.dbs = dbs; + return stats; +} diff --git a/src/utils/orbitdb.js b/src/utils/orbitdb.js index a8abc62..43b7bf2 100644 --- a/src/utils/orbitdb.js +++ b/src/utils/orbitdb.js @@ -1,14 +1,14 @@ export function getBoardAddress(hash, name) { - return '/orbitdb/' + hash + '/' + name + return `/orbitdb/${hash}/${name}`; } export function shortenAddress(address) { - return address.replace(/^\/orbitdb/, '/b') + return address.replace(/^\/orbitdb/, '/b'); } export function closeBoard(address) { - const db = window.dbs[address] - delete window.dbs[address] - if (db && db.close) db.close() -} \ No newline at end of file + const db = window.dbs[address]; + delete window.dbs[address]; + if (db && db.close) db.close(); +} diff --git a/src/utils/persistence.js b/src/utils/persistence.js index 5a38b41..14db7dd 100644 --- a/src/utils/persistence.js +++ b/src/utils/persistence.js @@ -1,16 +1,16 @@ -export function save(){ - const obj = { - addresses: Object.keys(window.dbs || {}) - } - localStorage.setItem('ipfs-boards-v0', JSON.stringify(obj)) +export function save() { + const obj = { + addresses: Object.keys(window.dbs || {}), + }; + localStorage.setItem('ipfs-boards-v0', JSON.stringify(obj)); } -export function load(){ - const str = localStorage.getItem('ipfs-boards-v0') - try { - return JSON.parse(str) || {}; - } catch (error) { - return {} - } -} \ No newline at end of file +export function load() { + const str = localStorage.getItem('ipfs-boards-v0'); + try { + return JSON.parse(str) || {}; + } catch (error) { + return {}; + } +}