1
0
mirror of https://github.com/fazo96/ipfs-boards synced 2025-03-11 21:38:38 +01:00

eslint fix

This commit is contained in:
Enrico Fasoli 2019-03-10 19:53:18 +01:00
parent bc32ede2b5
commit 4e880f8864
No known key found for this signature in database
GPG Key ID: 1238873C5F27DB4D
28 changed files with 668 additions and 653 deletions

View File

@ -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'
export const ERROR = 'ERROR';

View File

@ -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
}
}
return {
type: CLOSE_BOARD,
address,
};
}

View File

@ -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
}
}
return {
type: HIDE_COMMENT,
address,
postId,
commentId,
replyTo,
};
}

View File

@ -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
}
}
return {
type: HIDE_POST,
address,
postId,
};
}

View File

@ -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 (
<Switch>
<Route path='/b/new' component={OpenBoard} />
<Route path='/b/:hash/:name/' component={withRouter(WithBoard(BoardPage))} />
<Route path='/' component={Boards} />
<Route path="/b/new" component={OpenBoard} />
<Route path="/b/:hash/:name/" component={withRouter(WithBoard(BoardPage))} />
<Route path="/" component={Boards} />
</Switch>
)
);
}
}
export default withRouter(App)
export default withRouter(App);

View File

@ -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 <BoardComponent stats={boardStats} {...boards[address]} />
function Board({
stats, location, match, boards,
}) {
const { hash, name } = match.params;
const address = getBoardAddress(hash, name);
const boardStats = stats.dbs[address] || {};
return <BoardComponent stats={boardStats} {...boards[address]} />;
}
function mapStateToProps(state){
return {
boards: state.boards.boards
}
function mapStateToProps(state) {
return {
boards: state.boards.boards,
};
}
export default connect(
mapStateToProps
)(Board)
mapStateToProps,
)(Board);

View File

@ -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 <BoardEditorForm
board={board}
address={address}
updateBoardMetadata={updateBoardMetadata}
{...board.metadata}
function BoardEditor({
boards, boardEditor, match, updateBoardMetadata,
}) {
const { hash, name } = match.params;
const address = getBoardAddress(hash, name);
const board = boards[address];
return (
<BoardEditorForm
board={board}
address={address}
updateBoardMetadata={updateBoardMetadata}
{...board.metadata}
/>
);
}
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);

View File

@ -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 <WrappedComponent
boards={boards}
createBoard={createBoard}
closeBoard={closeBoard}
return (
<WrappedComponent
boards={boards}
createBoard={createBoard}
closeBoard={closeBoard}
/>
);
}
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);

View File

@ -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 <OpenBoardForm {...props} />
return <OpenBoardForm {...props} />;
}
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);

View File

@ -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 <PostForm post={post} board={board} onSave={p => 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 <PostForm post={post} board={board} onSave={p => 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)
mapStateToProps,
mapDispatchToProps,
)(PostEditor);

View File

@ -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 <WrappedComponent {...board} {...this.props} />
} 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);
}
}
}
render() {
const { boards, match } = this.props;
const address = getBoardAddress(match.params.hash, match.params.name);
const board = boards[address];
if (board) {
return <WrappedComponent {...board} {...this.props} />;
}
return 'Opening this board';
}
}
return connect(
mapStateToProps,
mapDispatchToProps,
)(ToExport);
}

View File

@ -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 <WrappedComponent stats={this.state.stats} {...this.props} />
}
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 <WrappedComponent stats={this.state.stats} {...this.props} />;
}
};
}

View File

@ -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(
</ConnectedRouter>
</Provider>
</AppContainer>,
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(
<AppContainer>
<Provider store={store}>
@ -33,10 +33,10 @@ if (module.hot) {
</ConnectedRouter>
</Provider>
</AppContainer>,
document.getElementById('root')
)
})
document.getElementById('root'),
);
});
}
registerServiceWorker()
start(store.dispatch)
registerServiceWorker();
start(store.dispatch);

View File

@ -5,4 +5,4 @@ module.exports = {
ADD_COMMENT: 'ADD_COMMENT',
UPDATE_COMMENT: 'UPDATE_COMMENT',
UPDATE_METADATA: 'UPDATE_METADATA',
};
};

View File

@ -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,
});
});
}

View File

@ -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;
}
}
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;
}
}

View File

@ -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
})
router: connectRouter(history),
postEditor: postReducer,
boards: boardsReducer,
openBoard: openBoardReducer,
});

View File

@ -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
}
}
switch (action.type) {
case OPEN_BOARD:
return Object.assign({}, state, { opening: true });
case OPENED_BOARD:
return Object.assign({}, state, { opening: false });
default:
return state;
}
}

View File

@ -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
}
}
export default function (state = getInitialState(), action) {
switch (action.type) {
case ADD_POST:
return Object.assign({}, state, { post: action.post });
default:
return state;
}
}

View File

@ -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();
});
}

View File

@ -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()
})
}
return eventChannel((emitter) => {
connectDb(db, emitter);
return () => db.close();
});
}

View File

@ -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()
}
yield openPreviousBoards();
}

View File

@ -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)
}
yield call(save);
}

View File

@ -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
}
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
}

View File

@ -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);

View File

@ -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
}
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;
}

View File

@ -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()
}
const db = window.dbs[address];
delete window.dbs[address];
if (db && db.close) db.close();
}

View File

@ -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 {}
}
}
export function load() {
const str = localStorage.getItem('ipfs-boards-v0');
try {
return JSON.parse(str) || {};
} catch (error) {
return {};
}
}