mirror of https://gitlab.com/ecentrics/concordia
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
5.3 KiB
189 lines
5.3 KiB
import React, { Component } from 'react';
|
|
import { bindActionCreators } from 'redux';
|
|
import { push } from 'connected-react-router';
|
|
import { connect } from 'react-redux';
|
|
import { drizzle } from '../index';
|
|
|
|
import PostList from '../components/PostList';
|
|
import NewPost from '../components/NewPost';
|
|
import FloatingButton from '../components/FloatingButton';
|
|
|
|
import { setNavBarTitle } from '../redux/actions/userInterfaceActions.js';
|
|
|
|
const contract = 'Forum';
|
|
const getTopicMethod = 'getTopic';
|
|
|
|
class TopicContainer extends Component {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
// Topic ID should be a positive integer
|
|
if (!/^[0-9]+$/.test(this.props.match.params.topicId)) {
|
|
this.props.navigateTo('/404');
|
|
}
|
|
|
|
this.getBlockchainData = this.getBlockchainData.bind(this);
|
|
this.fetchTopicSubject = this.fetchTopicSubject.bind(this);
|
|
this.togglePostingState = this.togglePostingState.bind(this);
|
|
this.postCreated = this.postCreated.bind(this);
|
|
|
|
this.state = {
|
|
pageStatus: 'initialized',
|
|
topicID: parseInt(this.props.match.params.topicId),
|
|
topicSubject: null,
|
|
postFocus: this.props.match.params.postId
|
|
&& /^[0-9]+$/.test(this.props.match.params.postId)
|
|
? this.props.match.params.postId
|
|
: null,
|
|
fetchTopicSubjectStatus: 'pending',
|
|
posting: false
|
|
};
|
|
}
|
|
|
|
getBlockchainData() {
|
|
if (this.state.pageStatus === 'initialized'
|
|
&& this.props.drizzleStatus.initialized) {
|
|
this.dataKey = drizzle.contracts[contract].methods[getTopicMethod].cacheCall(
|
|
this.state.topicID,
|
|
);
|
|
this.setState({
|
|
pageStatus: 'loading'
|
|
});
|
|
}
|
|
if (this.state.pageStatus === 'loading'
|
|
&& this.props.contracts[contract][getTopicMethod][this.dataKey]) {
|
|
this.setState({
|
|
pageStatus: 'loaded'
|
|
});
|
|
if (this.props.orbitDB.orbitdb !== null) {
|
|
this.fetchTopicSubject(
|
|
this.props.contracts[contract][getTopicMethod][this.dataKey].value[0],
|
|
);
|
|
this.setState({
|
|
fetchTopicSubjectStatus: 'fetching'
|
|
});
|
|
}
|
|
}
|
|
if (this.state.pageStatus === 'loaded'
|
|
&& this.state.fetchTopicSubjectStatus === 'pending'
|
|
&& this.props.orbitDB.orbitdb !== null) {
|
|
this.fetchTopicSubject(
|
|
this.props.contracts[contract][getTopicMethod][this.dataKey].value[0],
|
|
);
|
|
this.setState({
|
|
fetchTopicSubjectStatus: 'fetching'
|
|
});
|
|
}
|
|
}
|
|
|
|
async fetchTopicSubject(orbitDBAddress) {
|
|
let orbitData;
|
|
if (this.props.contracts[contract][getTopicMethod][this.dataKey].value[1]
|
|
=== this.props.user.address) {
|
|
orbitData = this.props.orbitDB.topicsDB.get(this.state.topicID);
|
|
} else {
|
|
const fullAddress = `/orbitdb/${orbitDBAddress}/topics`;
|
|
const store = await this.props.orbitDB.orbitdb.keyvalue(fullAddress);
|
|
await store.load();
|
|
|
|
const localOrbitData = store.get(this.state.topicID);
|
|
if (localOrbitData) {
|
|
orbitData = localOrbitData;
|
|
} else {
|
|
// Wait until we have received something from the network
|
|
store.events.on('replicated', () => {
|
|
orbitData = store.get(this.state.topicID);
|
|
});
|
|
}
|
|
}
|
|
|
|
this.props.setNavBarTitle(orbitData.subject);
|
|
this.setState({
|
|
topicSubject: orbitData.subject,
|
|
fetchTopicSubjectStatus: 'fetched'
|
|
});
|
|
}
|
|
|
|
togglePostingState(event) {
|
|
if (event) {
|
|
event.preventDefault();
|
|
}
|
|
this.setState(prevState => ({
|
|
posting: !prevState.posting
|
|
}));
|
|
}
|
|
|
|
postCreated() {
|
|
this.setState(prevState => ({
|
|
posting: false
|
|
}));
|
|
}
|
|
|
|
render() {
|
|
let topicContents;
|
|
if (this.state.pageStatus === 'loaded') {
|
|
topicContents = (
|
|
(
|
|
<div>
|
|
<PostList
|
|
postIDs={this.props.contracts[contract][getTopicMethod][this.dataKey].value[4]}
|
|
focusOnPost={this.state.postFocus
|
|
? this.state.postFocus
|
|
: null}
|
|
/>
|
|
{this.state.posting
|
|
&& (
|
|
<NewPost
|
|
topicID={this.state.topicID}
|
|
subject={this.state.topicSubject}
|
|
postIndex={this.props.contracts[contract][getTopicMethod][this.dataKey].value[4].length}
|
|
onCancelClick={() => { this.togglePostingState(); }}
|
|
onPostCreated={() => { this.postCreated(); }}
|
|
/>
|
|
)
|
|
}
|
|
<div className="posts-list-spacer" />
|
|
{this.props.user.hasSignedUp && !this.state.posting
|
|
&& <FloatingButton onClick={this.togglePostingState} />
|
|
}
|
|
</div>
|
|
)
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="fill">
|
|
{topicContents}
|
|
{!this.state.posting
|
|
&& <div className="bottom-overlay-pad" />
|
|
}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.getBlockchainData();
|
|
}
|
|
|
|
componentDidUpdate() {
|
|
this.getBlockchainData();
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.props.setNavBarTitle('');
|
|
}
|
|
}
|
|
|
|
const mapDispatchToProps = dispatch => bindActionCreators({
|
|
navigateTo: location => push(location),
|
|
setNavBarTitle: navBarTitle => setNavBarTitle(navBarTitle)
|
|
}, dispatch);
|
|
|
|
const mapStateToProps = state => ({
|
|
user: state.user,
|
|
contracts: state.contracts,
|
|
drizzleStatus: state.drizzleStatus,
|
|
orbitDB: state.orbit
|
|
});
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(TopicContainer);
|
|
|