cleanup
This commit is contained in:
parent
42a632eb88
commit
a4d103c1d6
15 changed files with 147 additions and 149 deletions
7
src/ui/component/comment/index.js
Normal file
7
src/ui/component/comment/index.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import Comment from './view';
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)(Comment);
|
36
src/ui/component/comment/view.jsx
Normal file
36
src/ui/component/comment/view.jsx
Normal 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;
|
|
@ -1,11 +1,11 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import { CHANNEL_NEW } from 'constants/claim';
|
||||||
import React from 'react';
|
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 usePersistedState from 'util/use-persisted-state';
|
import usePersistedState from 'util/use-persisted-state';
|
||||||
|
|
||||||
// props:
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: StreamClaim,
|
claim: StreamClaim,
|
||||||
|
@ -13,12 +13,11 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function CommentCreate(props: Props) {
|
export function CommentCreate(props: Props) {
|
||||||
const COMMENT_ACKNOWLEDGED = 'COMMENT_ACKNOWLEDGED';
|
|
||||||
const { createComment, claim } = props;
|
const { createComment, claim } = props;
|
||||||
const { claim_id: claimId } = claim;
|
const { claim_id: claimId } = claim;
|
||||||
const [commentValue, setCommentValue] = usePersistedState(`comment-${claimId}`, '');
|
const [commentValue, setCommentValue] = usePersistedState(`comment-${claimId}`, '');
|
||||||
const [commentAck, setCommentAck] = usePersistedState(COMMENT_ACKNOWLEDGED, false);
|
const [commentAck, setCommentAck] = usePersistedState('comment-acknowledge', false);
|
||||||
const [channel, setChannel] = usePersistedState('COMMENT_CHANNEL', 'anonymous');
|
const [channel, setChannel] = usePersistedState('comment-channel', 'anonymous');
|
||||||
|
|
||||||
function handleCommentChange(event) {
|
function handleCommentChange(event) {
|
||||||
setCommentValue(event.target.value);
|
setCommentValue(event.target.value);
|
||||||
|
@ -32,19 +31,19 @@ export function CommentCreate(props: Props) {
|
||||||
setCommentAck(true);
|
setCommentAck(true);
|
||||||
}
|
}
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
if (channel !== 'new' && commentValue.length) createComment(commentValue, claimId, channel);
|
if (channel !== CHANNEL_NEW && commentValue.length) createComment(commentValue, claimId, channel);
|
||||||
setCommentValue('');
|
setCommentValue('');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{commentAck !== true && (
|
{commentAck !== true && (
|
||||||
<section className="card card--section">
|
<section>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<div className="media__title">About comments..</div>
|
<div className="media__title">About comments..</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<div className="media__subtitle">Seriously, don't comment.</div>
|
<div className="media__subtitle">I acknowledge something.</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<Button button="primary" onClick={handleCommentAck} label={__('Got it!')} />
|
<Button button="primary" onClick={handleCommentAck} label={__('Got it!')} />
|
||||||
|
@ -52,26 +51,26 @@ export function CommentCreate(props: Props) {
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
{commentAck === true && (
|
{commentAck === true && (
|
||||||
<section className="card card--section">
|
<section>
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<ChannelSection channel={channel} onChannelChange={handleChannelChange} />
|
<ChannelSection channel={channel} onChannelChange={handleChannelChange} />
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<FormField
|
<FormField
|
||||||
disabled={channel === 'new'}
|
disabled={channel === CHANNEL_NEW}
|
||||||
type="textarea"
|
type="textarea"
|
||||||
name="content_description"
|
name="content_description"
|
||||||
label={__('Text')}
|
label={__('Comment')}
|
||||||
placeholder={__('Your comment')}
|
placeholder={__('Your comment')}
|
||||||
value={commentValue}
|
value={commentValue}
|
||||||
onChange={handleCommentChange}
|
onChange={handleCommentChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__actions">
|
||||||
<Button
|
<Button
|
||||||
button="primary"
|
button="primary"
|
||||||
disabled={channel === 'new' || !commentValue.length}
|
disabled={channel === CHANNEL_NEW || !commentValue.length}
|
||||||
type="submit"
|
type="submit"
|
||||||
label={__('Post')}
|
label={__('Post')}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectCommentsForUri, makeSelectClaimForUri, doCommentList } from 'lbry-redux';
|
import { makeSelectCommentsForUri, doCommentList } from 'lbry-redux';
|
||||||
import CommentsList from './view';
|
import CommentsList from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
comments: makeSelectCommentsForUri(props.uri)(state),
|
comments: makeSelectCommentsForUri(props.uri)(state),
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchList: uri => dispatch(doCommentList(uri)),
|
fetchComments: uri => dispatch(doCommentList(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
select,
|
select,
|
||||||
perform
|
perform
|
||||||
|
|
|
@ -1,44 +1,24 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import relativeDate from 'tiny-relative-date';
|
import Comment from 'component/comment';
|
||||||
|
|
||||||
type CommentListProps = {
|
type Props = {
|
||||||
comments: Array<any>,
|
comments: Array<any>,
|
||||||
fetchList: string => void,
|
fetchComments: string => void,
|
||||||
uri: string,
|
uri: string,
|
||||||
isLoading: boolean,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type CommentProps = {
|
function CommentList(props: Props) {
|
||||||
commentId: string,
|
const { fetchComments, uri, comments } = props;
|
||||||
claimId: string,
|
|
||||||
author: string,
|
|
||||||
message: string,
|
|
||||||
parentId: number,
|
|
||||||
timePosted: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
class CommentList extends React.PureComponent<CommentListProps> {
|
useEffect(() => {
|
||||||
componentDidMount() {
|
fetchComments(uri);
|
||||||
this.fetchComments(this.props);
|
}, [fetchComments, uri]);
|
||||||
}
|
|
||||||
|
|
||||||
fetchComments = (props: CommentListProps) => {
|
|
||||||
const { fetchList, uri } = props;
|
|
||||||
fetchList(uri);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { comments } = this.props;
|
|
||||||
|
|
||||||
if (!comments) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
|
||||||
<ul className="comments">
|
<ul className="comments">
|
||||||
{comments.map(comment => {
|
{comments &&
|
||||||
|
comments.map(comment => {
|
||||||
return (
|
return (
|
||||||
<Comment
|
<Comment
|
||||||
author={comment.channel_name}
|
author={comment.channel_name}
|
||||||
|
@ -52,35 +32,7 @@ class CommentList extends React.PureComponent<CommentListProps> {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ul>
|
</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;
|
export default CommentList;
|
||||||
|
|
|
@ -154,6 +154,7 @@ export class FormField extends React.PureComponent<Props> {
|
||||||
} else if (type === 'textarea') {
|
} else if (type === 'textarea') {
|
||||||
input = (
|
input = (
|
||||||
<fieldset-section>
|
<fieldset-section>
|
||||||
|
<label htmlFor={name}>{label}</label>
|
||||||
<textarea type={type} id={name} {...inputProps} />
|
<textarea type={type} id={name} {...inputProps} />
|
||||||
</fieldset-section>
|
</fieldset-section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -76,6 +76,8 @@ class FileViewer extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleAutoplay(this.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);
|
// window.addEventListener('keydown', this.handleKeyDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,13 @@ 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={channel}>
|
<FormField
|
||||||
|
name="channel"
|
||||||
|
label={__('Channel')}
|
||||||
|
type="select"
|
||||||
|
onChange={this.handleChannelChange}
|
||||||
|
value={channel}
|
||||||
|
>
|
||||||
<option value={CHANNEL_ANONYMOUS}>{__('Anonymous')}</option>
|
<option value={CHANNEL_ANONYMOUS}>{__('Anonymous')}</option>
|
||||||
{channels.map(({ name }) => (
|
{channels.map(({ name }) => (
|
||||||
<option key={name} value={name}>
|
<option key={name} value={name}>
|
||||||
|
|
|
@ -287,9 +287,8 @@ class FilePage extends React.Component<Props> {
|
||||||
</div>
|
</div>
|
||||||
<div className="media__info--large">
|
<div className="media__info--large">
|
||||||
<FileDetails uri={uri} />
|
<FileDetails uri={uri} />
|
||||||
<header className="card__header">
|
|
||||||
<h2 className="card__header">Comments</h2>
|
<div className="media__info-title">{__('Comments')}</div>
|
||||||
</header>
|
|
||||||
<CommentCreate uri={uri} />
|
<CommentCreate uri={uri} />
|
||||||
<CommentsList uri={uri} />
|
<CommentsList uri={uri} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -373,7 +373,7 @@ export function doChangeVolume(volume) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// HERE
|
|
||||||
export function doClickCommentButton() {
|
export function doClickCommentButton() {
|
||||||
return {
|
return {
|
||||||
type: ACTIONS.ADD_COMMENT,
|
type: ACTIONS.ADD_COMMENT,
|
||||||
|
|
|
@ -195,7 +195,6 @@ reducers[ACTIONS.CLEAR_UPGRADE_TIMER] = state =>
|
||||||
Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
checkUpgradeTimer: undefined,
|
checkUpgradeTimer: undefined,
|
||||||
});
|
});
|
||||||
// HERE
|
|
||||||
|
|
||||||
reducers[ACTIONS.ADD_COMMENT] = state =>
|
reducers[ACTIONS.ADD_COMMENT] = state =>
|
||||||
Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
|
|
|
@ -25,10 +25,6 @@
|
||||||
.card--section {
|
.card--section {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: var(--spacing-large);
|
padding: var(--spacing-large);
|
||||||
|
|
||||||
.card__content:not(:last-of-type) {
|
|
||||||
margin-bottom: var(--spacing-large);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card--space-between {
|
.card--space-between {
|
||||||
|
@ -100,6 +96,10 @@
|
||||||
// C O N T E N T
|
// C O N T E N T
|
||||||
|
|
||||||
.card__content {
|
.card__content {
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
margin-bottom: var(--spacing-medium);
|
||||||
|
}
|
||||||
|
|
||||||
p:not(:last-child) {
|
p:not(:last-child) {
|
||||||
margin-bottom: var(--spacing-medium);
|
margin-bottom: var(--spacing-medium);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
|
.comments {
|
||||||
|
margin-top: var(--spacing-large);
|
||||||
|
}
|
||||||
|
|
||||||
.comment {
|
.comment {
|
||||||
padding-bottom: var(--spacing-vertical-large);
|
padding: var(--spacing-medium) 0;
|
||||||
|
|
||||||
&.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:last-of-type) {
|
&:not(:last-of-type) {
|
||||||
border-bottom: 1px solid var(--lbry-gray-1);
|
border-bottom: 1px solid var(--lbry-gray-1);
|
||||||
|
@ -21,44 +14,39 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment__actions-wrap {
|
// .comment__actions-wrap {
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
display: flex;
|
// display: flex;
|
||||||
justify-content: space-between;
|
// justify-content: space-between;
|
||||||
width: 4.5rem;
|
// width: 4.5rem;
|
||||||
}
|
// }
|
||||||
|
|
||||||
.comment__action {
|
// .comment__action {
|
||||||
@include hide-text;
|
// @include hide-text;
|
||||||
width: 0; height: 0;
|
// width: 0;
|
||||||
transition: border-color 0.2s;
|
// height: 0;
|
||||||
|
// transition: border-color 0.2s;
|
||||||
|
|
||||||
&.downvote {
|
// &.downvote {
|
||||||
border-top: 2rem solid var(--lbry-orange-3);
|
// border-top: 2rem solid var(--lbry-orange-3);
|
||||||
border-right: 1rem solid transparent;
|
// border-right: 1rem solid transparent;
|
||||||
border-left: 1rem solid transparent;
|
// border-left: 1rem solid transparent;
|
||||||
|
|
||||||
&:hover {
|
// &:hover {
|
||||||
border-top-color: var(--lbry-yellow-3);
|
// border-top-color: var(--lbry-yellow-3);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
&.upvote {
|
// &.upvote {
|
||||||
border-right: 1rem solid transparent;
|
// border-right: 1rem solid transparent;
|
||||||
border-bottom: 2rem solid var(--lbry-teal-4);
|
// border-bottom: 2rem solid var(--lbry-teal-4);
|
||||||
border-left: 1rem solid transparent;
|
// border-left: 1rem solid transparent;
|
||||||
|
|
||||||
&:hover {
|
// &:hover {
|
||||||
border-bottom-color: var(--lbry-green-2);
|
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
.comment__meta {
|
.comment__meta {
|
||||||
time {
|
time {
|
||||||
|
|
|
@ -4,7 +4,12 @@ export default function usePersistedState(key, firstTimeDefault) {
|
||||||
// If no key is passed in, act as a normal `useState`
|
// If no key is passed in, act as a normal `useState`
|
||||||
let defaultValue;
|
let defaultValue;
|
||||||
if (key) {
|
if (key) {
|
||||||
defaultValue = localStorage.getItem(key);
|
const item = localStorage.getItem(key);
|
||||||
|
if (item === 'true') {
|
||||||
|
defaultValue = true;
|
||||||
|
} else if (item === 'false') {
|
||||||
|
defaultValue = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!defaultValue) {
|
if (!defaultValue) {
|
||||||
|
|
|
@ -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.",
|
"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.",
|
"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",
|
"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!"
|
"Got it!": "Got it!",
|
||||||
}
|
"URI does not include name.": "URI does not include name.",
|
||||||
>>>>>>> comments cleanup
|
"Invalid claim ID %s.": "Invalid claim ID %s.",
|
||||||
|
"Comment": "Comment",
|
||||||
|
"Channel": "Channel",
|
||||||
|
"Comments": "Comments"
|
||||||
|
}>>>>>>> comments cleanup
|
||||||
|
|
Loading…
Reference in a new issue