flat comments

This commit is contained in:
Jessop Breth 2019-06-12 10:53:27 -04:00 committed by Sean Yesmunt
parent 31178c761f
commit 99c85a2ff7
9 changed files with 542 additions and 591 deletions

View file

@ -1,15 +1,14 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doCommentCreate, makeSelectClaimForUri, selectMyActiveChannelUri } from 'lbry-redux'; import { doCommentCreate, makeSelectClaimForUri } from 'lbry-redux';
import CommentCreate from './view'; import { CommentCreate } from './view';
const select = (state, props) => ({ const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state), claim: makeSelectClaimForUri(props.uri)(state),
channelUri: selectMyActiveChannelUri(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({
createComment: params => dispatch(doCommentCreate(params)), createComment: (comment, claimId, channel) => dispatch(doCommentCreate(comment, claimId, channel)),
}); });
export default connect( export default connect(

View file

@ -3,91 +3,82 @@ import React from 'react';
import { FormField, Form } from 'component/common/form'; import { FormField, Form } from 'component/common/form';
import Button from 'component/button'; import Button from 'component/button';
import ChannelSection from 'component/selectChannel'; import ChannelSection from 'component/selectChannel';
import { parseURI } from 'lbry-redux'; import { COMMENT_ACKNOWLEDGED, COMMENT_ACKNOWLEDGED_TRUE } from 'constants/settings';
import { usePersistedState } from 'util/use-persisted-state'; import { usePersistedState } from 'util/use-persisted-state';
// props: // props:
type Props = { type Props = {
uri: string, uri: string,
channelUri: string, claim: StreamClaim,
createComment: params => {}, createComment: (string, string, string) => void,
}; };
class CommentCreate extends React.PureComponent<Props> { export function CommentCreate(props: Props) {
constructor(props: Props) { const { createComment, claim } = props;
super(props); const { claim_id: claimId } = claim;
this.state = { const [commentValue, setCommentValue] = usePersistedState(`comment-${claimId}`, '');
message: '', const [commentAck, setCommentAck] = usePersistedState(COMMENT_ACKNOWLEDGED, 'no');
}; const [channel, setChannel] = usePersistedState('COMMENT_CHANNEL', 'anonymous');
// set state or props for comment form
(this: any).handleCommentChange = this.handleCommentChange.bind(this); function handleCommentChange(event) {
(this: any).handleChannelChange = this.handleChannelChange.bind(this); setCommentValue(event.target.value);
(this: any).handleSubmit = this.handleSubmit.bind(this);
} }
handleCommentChange(event) { function handleChannelChange(channel) {
this.setState({ message: event.target.value }); setChannel(channel);
} }
handleChannelChange(channelUri) { function handleCommentAck(event) {
this.setState({ channelUri: channelUri }); setCommentAck(COMMENT_ACKNOWLEDGED_TRUE);
}
function handleSubmit() {
if (channel !== 'new' && commentValue.length) createComment(commentValue, claimId, channel);
setCommentValue('');
} }
handleSubmit() { return (
// const { createComment, claim, channelUri } = this.props; <React.Fragment>
const { channelUri, claim } = this.props; // eslint-disable-line react/prop-types {commentAck !== COMMENT_ACKNOWLEDGED_TRUE && (
console.log('claim', claim); <section className="card card--section">
const { claim_id: claimId } = claim;
const { message } = this.state;
let cmt = { message, channelId: parseURI(channelUri).claimId, claimId };
console.log('CMT', cmt);
console.log('PURI', claimId);
console.log('PURI', parseURI(channelUri));
}
render() {
const { channelUri } = this.props;
return (
<section className="card card--section">
{!acksComments && (
<React.Fragment>
<div className="media__title">
<TruncatedText text={channelName || uri} lines={1} />
</div>
<div className="media__subtitle">
{totalItems > 0 && (
<span>
{totalItems} {totalItems === 1 ? 'publish' : 'publishes'}
</span>
)}
{!isResolvingUri && !totalItems && <span>This is an empty channel.</span>}
</div>
</React.Fragment>
)}
<Form onSubmit={this.handleSubmit}>
<div className="card__content"> <div className="card__content">
<FormField <div className="media__title">About comments..</div>
type="textarea"
name="content_description"
label={__('Text')}
placeholder={__('Your comment')}
value={this.state.message}
onChange={this.handleCommentChange}
/>
</div> </div>
<div className="card__actions--between"> <div className="card__content">
<div className="media__subtitle">Seriously, don&apos;t comment.</div>
</div>
<div className="card__content">
<Button button="primary" onClick={handleCommentAck} label={__('Got it!')} />
</div>
</section>
)}
{commentAck === COMMENT_ACKNOWLEDGED_TRUE && (
<section className="card card--section">
<Form onSubmit={handleSubmit}>
<div className="card__content"> <div className="card__content">
<ChannelSection channel={channelUri} /> <ChannelSection channel={channel} onChannelChange={handleChannelChange} />
</div> </div>
<Button button="primary" type="submit" label={__('Post')} /> <div className="card__content">
</div> <FormField
</Form> disabled={channel === 'new'}
</section> type="textarea"
); name="content_description"
} label={__('Text')}
placeholder={__('Your comment')}
value={commentValue}
onChange={handleCommentChange}
/>
</div>
<div className="card__content">
<Button
button="primary"
disabled={channel === 'new' || !commentValue.length}
type="submit"
label={__('Post')}
/>
</div>
</Form>
</section>
)}
</React.Fragment>
);
} }
export default CommentCreate;

View file

@ -3,7 +3,7 @@ import * as React from 'react';
import relativeDate from 'tiny-relative-date'; import relativeDate from 'tiny-relative-date';
type CommentListProps = { type CommentListProps = {
comments: {}, comments: Array<any>,
fetchList: string => void, fetchList: string => void,
uri: string, uri: string,
isLoading: boolean, isLoading: boolean,
@ -23,7 +23,7 @@ class CommentList extends React.PureComponent<CommentListProps> {
this.fetchComments(this.props); this.fetchComments(this.props);
} }
fetchComments = (props: Props) => { fetchComments = (props: CommentListProps) => {
const { fetchList, uri } = props; const { fetchList, uri } = props;
fetchList(uri); fetchList(uri);
}; };
@ -36,22 +36,23 @@ class CommentList extends React.PureComponent<CommentListProps> {
} }
return ( return (
<ul className="comments"> <section>
{comments['comments'].map(comment => { <ul className="comments">
console.log(comment.message); {comments.map(comment => {
return ( return (
<Comment <Comment
author={comment.author} author={comment.channel_name}
claimId={comment.claim_id} claimId={comment.channel_id}
commentId={comment.comment_id} commentId={comment.comment_id}
key={comment.author + comment.comment_id} key={comment.channel_id + comment.comment_id}
message={comment.message} message={comment.comment}
parentId={comment.parent_id} parentId={comment.parent_id || null}
timePosted={comment.time_posted} timePosted={comment.timestamp * 1000}
/> />
); );
})} })}
</ul> </ul>
</section>
); );
} }
} }
@ -61,20 +62,22 @@ class Comment extends React.PureComponent<CommentProps> {
return ( return (
<li className={this.props.parentId ? 'comment reply' : 'comment'}> <li className={this.props.parentId ? 'comment reply' : 'comment'}>
<div className="comment__meta card__actions--between"> <div className="comment__meta card__actions--between">
<strong>{this.props.author}</strong> {this.props.author && <strong>{this.props.author}</strong>}
{!this.props.author && <strong>Anonymous</strong>}
<time dateTime={this.props.timePosted}>{relativeDate(this.props.timePosted)}</time> <time dateTime={this.props.timePosted}>{relativeDate(this.props.timePosted)}</time>
</div> </div>
<div className="comment__content">{this.props.message}</div> <div className="comment__content">{this.props.message}</div>
{/* The following is for adding threaded replies, upvoting and downvoting */}
{/* <div className="comment__actions card__actions--between"> */}
{/* <button className={'button button--primary'}>Reply</button> */}
<div className="comment__actions card__actions--between"> {/* <span className="comment__actions-wrap"> */}
<button className={'button button--primary'}>Reply</button> {/* <button className="comment__action upvote">Up</button> */}
{/* <button className="comment__action downvote">Down</button> */}
<span className="comment__actions-wrap"> {/* </span> */}
<button className="comment__action upvote">Up</button> {/* </div> */}
<button className="comment__action downvote">Down</button>
</span>
</div>
</li> </li>
); );
} }

View file

@ -76,7 +76,7 @@ class FileViewer extends React.PureComponent<Props> {
} }
this.handleAutoplay(this.props); this.handleAutoplay(this.props);
window.addEventListener('keydown', this.handleKeyDown); // window.addEventListener('keydown', this.handleKeyDown);
} }
componentDidUpdate(prev: Props) { componentDidUpdate(prev: Props) {

View file

@ -331,7 +331,6 @@ class PublishForm extends React.PureComponent<Props> {
const shortUri = buildURI({ contentName: name }); const shortUri = buildURI({ contentName: name });
console.log('URI', uri);
return ( return (
<React.Fragment> <React.Fragment>
{IS_WEB && <UnsupportedOnWeb />} {IS_WEB && <UnsupportedOnWeb />}

View file

@ -4,23 +4,19 @@ import {
selectBalance, selectBalance,
selectMyChannelClaims, selectMyChannelClaims,
selectFetchingMyChannels, selectFetchingMyChannels,
selectMyActiveChannelUri,
doFetchChannelListMine, doFetchChannelListMine,
doCreateChannel, doCreateChannel,
doSetMyActiveChannelUri,
} from 'lbry-redux'; } from 'lbry-redux';
const select = state => ({ const select = state => ({
channels: selectMyChannelClaims(state), channels: selectMyChannelClaims(state),
fetchingChannels: selectFetchingMyChannels(state), fetchingChannels: selectFetchingMyChannels(state),
balance: selectBalance(state), balance: selectBalance(state),
activeChannelUri: selectMyActiveChannelUri(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({
createChannel: (name, amount) => dispatch(doCreateChannel(name, amount)), createChannel: (name, amount) => dispatch(doCreateChannel(name, amount)),
fetchChannelListMine: () => dispatch(doFetchChannelListMine()), fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
setMyActiveChannelUri: activeChannelUri => dispatch(doSetMyActiveChannelUri(activeChannelUri)),
}); });
export default connect( export default connect(

View file

@ -7,16 +7,13 @@ import Button from 'component/button';
import { CHANNEL_NEW, CHANNEL_ANONYMOUS } from 'constants/claim'; import { CHANNEL_NEW, CHANNEL_ANONYMOUS } from 'constants/claim';
type Props = { type Props = {
channelUri: string,
channel: string, // currently selected channel channel: string, // currently selected channel
channels: Array<{ name: string }>, channels: Array<{ name: string }>,
balance: number, balance: number,
onChannelChange?: string => void, onChannelChange: string => void,
createChannel: (string, number) => Promise<any>, createChannel: (string, number) => Promise<any>,
fetchChannelListMine: () => void, fetchChannelListMine: () => void,
fetchingChannels: boolean, fetchingChannels: boolean,
activeChannelUri: string,
setMyActiveChannelUri: string => void,
}; };
type State = { type State = {
@ -56,27 +53,18 @@ class ChannelSection extends React.PureComponent<Props, State> {
} }
} }
onChannelChangeProxy(channelUri) {
const { onChannelChange } = this.props;
if (onChannelChange) {
onChannelChange(channelUri);
}
}
handleChannelChange(event: SyntheticInputEvent<*>) { handleChannelChange(event: SyntheticInputEvent<*>) {
const { setMyActiveChannelUri } = this.props; const { onChannelChange } = this.props;
const { newChannelBid } = this.state; const { newChannelBid } = this.state;
const channelUri = event.target.value; const channel = event.target.value;
console.log('HCC', channelUri);
if (channelUri === CHANNEL_NEW) { if (channel === CHANNEL_NEW) {
this.setState({ addingChannel: true }); this.setState({ addingChannel: true });
this.onChannelChangeProxy(channelUri); onChannelChange(channel);
this.handleNewChannelBidChange(newChannelBid); this.handleNewChannelBidChange(newChannelBid);
} else { } else {
this.setState({ addingChannel: false }); this.setState({ addingChannel: false });
setMyActiveChannelUri(channelUri); onChannelChange(channel);
this.onChannelChangeProxy(channelUri);
} }
} }
@ -116,7 +104,7 @@ class ChannelSection extends React.PureComponent<Props, State> {
} }
handleCreateChannelClick() { handleCreateChannelClick() {
const { balance, createChannel } = this.props; const { balance, createChannel, onChannelChange } = this.props;
const { newChannelBid, newChannelName } = this.state; const { newChannelBid, newChannelName } = this.state;
const channelName = `@${newChannelName}`; const channelName = `@${newChannelName}`;
@ -135,7 +123,8 @@ class ChannelSection extends React.PureComponent<Props, State> {
creatingChannel: false, creatingChannel: false,
addingChannel: false, addingChannel: false,
}); });
this.onChannelChangeProxy(channelName);
onChannelChange(channelName);
}; };
const failure = () => { const failure = () => {
@ -149,7 +138,7 @@ class ChannelSection extends React.PureComponent<Props, State> {
} }
render() { render() {
const channelUri = this.state.addingChannel ? 'new' : this.props.channelUri; const channel = this.state.addingChannel ? 'new' : this.props.channel;
const { fetchingChannels, channels = [] } = this.props; const { fetchingChannels, channels = [] } = this.props;
const { const {
newChannelName, newChannelName,
@ -168,10 +157,10 @@ class ChannelSection extends React.PureComponent<Props, State> {
<BusyIndicator message="Updating channels" /> <BusyIndicator message="Updating channels" />
) : ( ) : (
<fieldset-section> <fieldset-section>
<FormField name="channel" type="select" onChange={this.handleChannelChange} value={channelUri}> <FormField name="channel" type="select" onChange={this.handleChannelChange} value={channel}>
<option value={CHANNEL_ANONYMOUS}>{__('Anonymous')}</option> <option value={CHANNEL_ANONYMOUS}>{__('Anonymous')}</option>
{channels.map(({ name, permanent_url: channelUri }) => ( {channels.map(({ name }) => (
<option key={name} value={channelUri}> <option key={name} value={name}>
{name} {name}
</option> </option>
))} ))}

View file

@ -16,3 +16,5 @@ export const AUTOPLAY = 'autoplay';
export const RESULT_COUNT = 'resultCount'; export const RESULT_COUNT = 'resultCount';
export const OS_NOTIFICATIONS_ENABLED = 'osNotificationsEnabled'; export const OS_NOTIFICATIONS_ENABLED = 'osNotificationsEnabled';
export const AUTO_DOWNLOAD = 'autoDownload'; export const AUTO_DOWNLOAD = 'autoDownload';
export const COMMENT_ACKNOWLEDGED = 'comment_acknowledged';
export const COMMENT_ACKNOWLEDGED_TRUE = 'comment_acknowledged_true';

892
yarn.lock

File diff suppressed because it is too large Load diff