This commit is contained in:
Sean Yesmunt 2019-06-26 19:59:27 -04:00
parent 42a632eb88
commit a4d103c1d6
15 changed files with 147 additions and 149 deletions

View file

@ -0,0 +1,7 @@
import { connect } from 'react-redux';
import Comment from './view';
export default connect(
null,
null
)(Comment);

View file

@ -0,0 +1,36 @@
// @flow
import React from 'react';
import relativeDate from 'tiny-relative-date';
type Props = {
author: string,
message: string,
timePosted: number,
};
function Comment(props: Props) {
const { author, timePosted, message } = props;
return (
<li className="comment">
<div className="comment__meta card__actions--between">
<strong>{author || __('Anonymous')}</strong>
<time dateTime={timePosted}>{relativeDate(timePosted)}</time>
</div>
<p>{message}</p>
{/* The following is for adding threaded replies, upvoting and downvoting */}
{/* <div className="comment__actions card__actions--between"> */}
{/* <button className={'button button--primary'}>Reply</button> */}
{/* <span className="comment__actions-wrap"> */}
{/* <button className="comment__action upvote">Up</button> */}
{/* <button className="comment__action downvote">Down</button> */}
{/* </span> */}
{/* </div> */}
</li>
);
}
export default Comment;

View file

@ -1,11 +1,11 @@
// @flow
import { CHANNEL_NEW } from 'constants/claim';
import React from 'react';
import { FormField, Form } from 'component/common/form';
import Button from 'component/button';
import ChannelSection from 'component/selectChannel';
import usePersistedState from 'util/use-persisted-state';
// props:
type Props = {
uri: string,
claim: StreamClaim,
@ -13,12 +13,11 @@ type Props = {
};
export function CommentCreate(props: Props) {
const COMMENT_ACKNOWLEDGED = 'COMMENT_ACKNOWLEDGED';
const { createComment, claim } = props;
const { claim_id: claimId } = claim;
const [commentValue, setCommentValue] = usePersistedState(`comment-${claimId}`, '');
const [commentAck, setCommentAck] = usePersistedState(COMMENT_ACKNOWLEDGED, false);
const [channel, setChannel] = usePersistedState('COMMENT_CHANNEL', 'anonymous');
const [commentAck, setCommentAck] = usePersistedState('comment-acknowledge', false);
const [channel, setChannel] = usePersistedState('comment-channel', 'anonymous');
function handleCommentChange(event) {
setCommentValue(event.target.value);
@ -32,19 +31,19 @@ export function CommentCreate(props: Props) {
setCommentAck(true);
}
function handleSubmit() {
if (channel !== 'new' && commentValue.length) createComment(commentValue, claimId, channel);
if (channel !== CHANNEL_NEW && commentValue.length) createComment(commentValue, claimId, channel);
setCommentValue('');
}
return (
<React.Fragment>
{commentAck !== true && (
<section className="card card--section">
<section>
<div className="card__content">
<div className="media__title">About comments..</div>
</div>
<div className="card__content">
<div className="media__subtitle">Seriously, don&apos;t comment.</div>
<div className="media__subtitle">I acknowledge something.</div>
</div>
<div className="card__content">
<Button button="primary" onClick={handleCommentAck} label={__('Got it!')} />
@ -52,26 +51,26 @@ export function CommentCreate(props: Props) {
</section>
)}
{commentAck === true && (
<section className="card card--section">
<section>
<Form onSubmit={handleSubmit}>
<div className="card__content">
<ChannelSection channel={channel} onChannelChange={handleChannelChange} />
</div>
<div className="card__content">
<FormField
disabled={channel === 'new'}
disabled={channel === CHANNEL_NEW}
type="textarea"
name="content_description"
label={__('Text')}
label={__('Comment')}
placeholder={__('Your comment')}
value={commentValue}
onChange={handleCommentChange}
/>
</div>
<div className="card__content">
<div className="card__actions">
<Button
button="primary"
disabled={channel === 'new' || !commentValue.length}
disabled={channel === CHANNEL_NEW || !commentValue.length}
type="submit"
label={__('Post')}
/>

View file

@ -1,15 +1,15 @@
import { connect } from 'react-redux';
import { makeSelectCommentsForUri, makeSelectClaimForUri, doCommentList } from 'lbry-redux';
import { makeSelectCommentsForUri, doCommentList } from 'lbry-redux';
import CommentsList from './view';
const select = (state, props) => ({
comments: makeSelectCommentsForUri(props.uri)(state),
claim: makeSelectClaimForUri(props.uri)(state),
});
const perform = dispatch => ({
fetchList: uri => dispatch(doCommentList(uri)),
fetchComments: uri => dispatch(doCommentList(uri)),
});
export default connect(
select,
perform

View file

@ -1,44 +1,24 @@
// @flow
import * as React from 'react';
import relativeDate from 'tiny-relative-date';
import React, { useEffect } from 'react';
import Comment from 'component/comment';
type CommentListProps = {
type Props = {
comments: Array<any>,
fetchList: string => void,
fetchComments: string => void,
uri: string,
isLoading: boolean,
};
type CommentProps = {
commentId: string,
claimId: string,
author: string,
message: string,
parentId: number,
timePosted: number,
};
function CommentList(props: Props) {
const { fetchComments, uri, comments } = props;
class CommentList extends React.PureComponent<CommentListProps> {
componentDidMount() {
this.fetchComments(this.props);
}
fetchComments = (props: CommentListProps) => {
const { fetchList, uri } = props;
fetchList(uri);
};
render() {
const { comments } = this.props;
if (!comments) {
return null;
}
useEffect(() => {
fetchComments(uri);
}, [fetchComments, uri]);
return (
<section>
<ul className="comments">
{comments.map(comment => {
{comments &&
comments.map(comment => {
return (
<Comment
author={comment.channel_name}
@ -52,35 +32,7 @@ class CommentList extends React.PureComponent<CommentListProps> {
);
})}
</ul>
</section>
);
}
}
class Comment extends React.PureComponent<CommentProps> {
render() {
return (
<li className={this.props.parentId ? 'comment reply' : 'comment'}>
<div className="comment__meta card__actions--between">
{this.props.author && <strong>{this.props.author}</strong>}
{!this.props.author && <strong>Anonymous</strong>}
<time dateTime={this.props.timePosted}>{relativeDate(this.props.timePosted)}</time>
</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> */}
{/* <span className="comment__actions-wrap"> */}
{/* <button className="comment__action upvote">Up</button> */}
{/* <button className="comment__action downvote">Down</button> */}
{/* </span> */}
{/* </div> */}
</li>
);
}
}
export default CommentList;

View file

@ -154,6 +154,7 @@ export class FormField extends React.PureComponent<Props> {
} else if (type === 'textarea') {
input = (
<fieldset-section>
<label htmlFor={name}>{label}</label>
<textarea type={type} id={name} {...inputProps} />
</fieldset-section>
);

View file

@ -76,6 +76,8 @@ class FileViewer extends React.PureComponent<Props> {
}
this.handleAutoplay(this.props);
// Commented out because it would play/pause if you were typing in the comment field
// Need a way to check if you are typing
// window.addEventListener('keydown', this.handleKeyDown);
}

View file

@ -157,7 +157,13 @@ class ChannelSection extends React.PureComponent<Props, State> {
<BusyIndicator message="Updating channels" />
) : (
<fieldset-section>
<FormField name="channel" type="select" onChange={this.handleChannelChange} value={channel}>
<FormField
name="channel"
label={__('Channel')}
type="select"
onChange={this.handleChannelChange}
value={channel}
>
<option value={CHANNEL_ANONYMOUS}>{__('Anonymous')}</option>
{channels.map(({ name }) => (
<option key={name} value={name}>

View file

@ -287,9 +287,8 @@ class FilePage extends React.Component<Props> {
</div>
<div className="media__info--large">
<FileDetails uri={uri} />
<header className="card__header">
<h2 className="card__header">Comments</h2>
</header>
<div className="media__info-title">{__('Comments')}</div>
<CommentCreate uri={uri} />
<CommentsList uri={uri} />
</div>

View file

@ -373,7 +373,7 @@ export function doChangeVolume(volume) {
});
};
}
// HERE
export function doClickCommentButton() {
return {
type: ACTIONS.ADD_COMMENT,

View file

@ -195,7 +195,6 @@ reducers[ACTIONS.CLEAR_UPGRADE_TIMER] = state =>
Object.assign({}, state, {
checkUpgradeTimer: undefined,
});
// HERE
reducers[ACTIONS.ADD_COMMENT] = state =>
Object.assign({}, state, {

View file

@ -25,10 +25,6 @@
.card--section {
position: relative;
padding: var(--spacing-large);
.card__content:not(:last-of-type) {
margin-bottom: var(--spacing-large);
}
}
.card--space-between {
@ -100,6 +96,10 @@
// C O N T E N T
.card__content {
&:not(:last-of-type) {
margin-bottom: var(--spacing-medium);
}
p:not(:last-child) {
margin-bottom: var(--spacing-medium);
}

View file

@ -1,16 +1,9 @@
.comments {
margin-top: var(--spacing-large);
}
.comment {
padding-bottom: var(--spacing-vertical-large);
&.reply {
border-left: 3px solid var(--lbry-teal-5);
padding-left: var(--spacing-vertical-large);
position: relative;
top: -1px;
}
&:not(:first-of-type) {
padding-top: var(--spacing-vertical-large);
}
padding: var(--spacing-medium) 0;
&:not(:last-of-type) {
border-bottom: 1px solid var(--lbry-gray-1);
@ -21,44 +14,39 @@
}
}
.comment__actions-wrap {
align-items: center;
display: flex;
justify-content: space-between;
width: 4.5rem;
}
// .comment__actions-wrap {
// align-items: center;
// display: flex;
// justify-content: space-between;
// width: 4.5rem;
// }
.comment__action {
@include hide-text;
width: 0; height: 0;
transition: border-color 0.2s;
// .comment__action {
// @include hide-text;
// width: 0;
// height: 0;
// transition: border-color 0.2s;
&.downvote {
border-top: 2rem solid var(--lbry-orange-3);
border-right: 1rem solid transparent;
border-left: 1rem solid transparent;
// &.downvote {
// border-top: 2rem solid var(--lbry-orange-3);
// border-right: 1rem solid transparent;
// border-left: 1rem solid transparent;
&:hover {
border-top-color: var(--lbry-yellow-3);
}
}
// &:hover {
// border-top-color: var(--lbry-yellow-3);
// }
// }
&.upvote {
border-right: 1rem solid transparent;
border-bottom: 2rem solid var(--lbry-teal-4);
border-left: 1rem solid transparent;
// &.upvote {
// border-right: 1rem solid transparent;
// border-bottom: 2rem solid var(--lbry-teal-4);
// border-left: 1rem solid transparent;
&:hover {
border-bottom-color: var(--lbry-green-2);
}
}
}
.comment__content {
font-size: 1.15rem;
padding-top: var(--spacing-vertical-medium);
padding-bottom: var(--spacing-vertical-large);
}
// &:hover {
// border-bottom-color: var(--lbry-green-2);
// }
// }
// }
.comment__meta {
time {

View file

@ -4,7 +4,12 @@ export default function usePersistedState(key, firstTimeDefault) {
// If no key is passed in, act as a normal `useState`
let defaultValue;
if (key) {
defaultValue = localStorage.getItem(key);
const item = localStorage.getItem(key);
if (item === 'true') {
defaultValue = true;
} else if (item === 'false') {
defaultValue = false;
}
}
if (!defaultValue) {

View file

@ -311,6 +311,10 @@
"Uh oh. The flux in our Retro Encabulator must be out of whack. Try refreshing to fix it.": "Uh oh. The flux in our Retro Encabulator must be out of whack. Try refreshing to fix it.",
"If you still have issues, your anti-virus software or firewall may be preventing startup.": "If you still have issues, your anti-virus software or firewall may be preventing startup.",
"Reach out to hello@lbry.com for help, or check out": "Reach out to hello@lbry.com for help, or check out",
"Got it!": "Got it!"
}
>>>>>>> comments cleanup
"Got it!": "Got it!",
"URI does not include name.": "URI does not include name.",
"Invalid claim ID %s.": "Invalid claim ID %s.",
"Comment": "Comment",
"Channel": "Channel",
"Comments": "Comments"
}>>>>>>> comments cleanup