Skip to content

Commit

Permalink
List own comments (#7171)
Browse files Browse the repository at this point in the history
* Add option to pass in url-search params.

Impetus: allow linked comment ID and setting the discussion tab when clicking on the `ClaimPreview`.

* comment.list: fix typos and renamed variables

- Switch from 'author' to 'creator' to disambiguate between comment author and content author. For comment author, we'll use 'commenter' from now on.
- Corrected 'commenterClaimId' to 'creatorClaimId' (just a typo, no functional change).

* doCommentReset: change param from uri to claimId

This reduces one lookup as clients will always have the claimID ready, but might not have the full URI.

It was using URI previously just to match the other APIs.

* Add doCommentListOwn -- command to fetch own comments

Since the redux slice is set up based on content or channel ID (for Channel Discussion page), re-use the channel ID for the case of "own comments". We always clear each ID when fetching page-0, so no worries of conflict when actually browsing the Channel Discussion page.

* Comment: add option to hide the actions section

* Implement own-comments page

* Use new param to remove sort-pins-first.

comment.List currently always pushes pins to the top to support pagination. This new param removes this behavior.
  • Loading branch information
infinite-persistence authored Oct 1, 2021
1 parent d3be872 commit de6c6f9
Show file tree
Hide file tree
Showing 17 changed files with 472 additions and 39 deletions.
4 changes: 2 additions & 2 deletions flow-typed/Comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,14 @@ declare type ReactionListResponse = {
declare type CommentListParams = {
page: number, // pagination: which page of results
page_size: number, // pagination: nr of comments to show in a page (max 200)
claim_id: string, // claim id of claim being commented on
claim_id?: string, // claim id of claim being commented on
channel_name?: string, // signing channel name of claim (enables 'commentsEnabled' check)
channel_id?: string, // signing channel claim id of claim (enables 'commentsEnabled' check)
author_claim_id?: string, // filters comments to just this author
parent_id?: string, // filters comments to those under this thread
top_level?: boolean, // filters to only top level comments
hidden?: boolean, // if true, will show hidden comments as well
sort_by?: number, // NEWEST=0, OLDEST=1, CONTROVERSY=2, POPULARITY=3,
sort_by?: number, // @see: ui/constants/comments.js::SORT_BY
};

declare type CommentListResponse = {
Expand Down
4 changes: 4 additions & 0 deletions static/app-strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@
"Failed to copy.": "Failed to copy.",
"The publisher has chosen to charge %lbc% to view this content. Your balance is currently too low to view it. Check out %reward_link% for free %lbc% or send more %lbc% to your wallet. You can also %buy_link% more %lbc%.": "The publisher has chosen to charge %lbc% to view this content. Your balance is currently too low to view it. Check out %reward_link% for free %lbc% or send more %lbc% to your wallet. You can also %buy_link% more %lbc%.",
"Connecting...": "Connecting...",
"Your comments": "Your comments",
"View your past comments.": "View your past comments.",
"Content or channel was deleted.": "Content or channel was deleted.",
"Comments": "Comments",
"Comment": "Comment",
"Comment --[button to submit something]--": "Comment",
Expand Down Expand Up @@ -1460,6 +1463,7 @@
"Staked LBRY Credits": "Staked LBRY Credits",
"1 comment": "1 comment",
"%total_comments% comments": "%total_comments% comments",
"No comments": "No comments",
"Upvote": "Upvote",
"Downvote": "Downvote",
"You loved this": "You loved this",
Expand Down
7 changes: 7 additions & 0 deletions ui/component/claimPreview/view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type Props = {
streamingUrl: ?string,
getFile: (string) => void,
customShouldHide?: (Claim) => boolean,
searchParams?: { [string]: string },
showUnresolvedClaim?: boolean,
showNullPlaceholder?: boolean,
includeSupportAction?: boolean,
Expand Down Expand Up @@ -125,6 +126,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
// modifiers
active,
customShouldHide,
searchParams,
showNullPlaceholder,
// value from show mature content user setting
// true if the user doesn't wanna see nsfw content
Expand Down Expand Up @@ -221,6 +223,11 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
if (listId) {
navigateSearch.set(COLLECTIONS_CONSTS.COLLECTION_ID, listId);
}
if (searchParams) {
Object.keys(searchParams).forEach((key) => {
navigateSearch.set(key, searchParams[key]);
});
}

const handleNavLinkClick = (e) => {
if (onClick) {
Expand Down
28 changes: 16 additions & 12 deletions ui/component/comment/view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type Props = {
doToast: ({ message: string }) => void,
isTopLevel?: boolean,
threadDepth: number,
hideActions?: boolean,
isPinned: boolean,
othersReacts: ?{
like: number,
Expand Down Expand Up @@ -95,6 +96,7 @@ function Comment(props: Props) {
doToast,
isTopLevel,
threadDepth,
hideActions,
isPinned,
othersReacts,
playingUri,
Expand Down Expand Up @@ -348,18 +350,20 @@ function Comment(props: Props) {
)}
</div>

<div className="comment__actions">
{threadDepth !== 0 && (
<Button
requiresAuth={IS_WEB}
label={commentingEnabled ? __('Reply') : __('Log in to reply')}
className="comment__action"
onClick={handleCommentReply}
icon={ICONS.REPLY}
/>
)}
{ENABLE_COMMENT_REACTIONS && <CommentReactions uri={uri} commentId={commentId} />}
</div>
{!hideActions && (
<div className="comment__actions">
{threadDepth !== 0 && (
<Button
requiresAuth={IS_WEB}
label={commentingEnabled ? __('Reply') : __('Log in to reply')}
className="comment__action"
onClick={handleCommentReply}
icon={ICONS.REPLY}
/>
)}
{ENABLE_COMMENT_REACTIONS && <CommentReactions uri={uri} commentId={commentId} />}
</div>
)}

{numDirectReplies > 0 && !showReplies && (
<div className="comment__actions">
Expand Down
2 changes: 1 addition & 1 deletion ui/component/commentsList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const perform = (dispatch) => ({
fetchTopLevelComments: (uri, page, pageSize, sortBy) => dispatch(doCommentList(uri, '', page, pageSize, sortBy)),
fetchComment: (commentId) => dispatch(doCommentById(commentId)),
fetchReacts: (commentIds) => dispatch(doCommentReactList(commentIds)),
resetComments: (uri) => dispatch(doCommentReset(uri)),
resetComments: (claimId) => dispatch(doCommentReset(claimId)),
});

export default connect(select, perform)(CommentsList);
7 changes: 5 additions & 2 deletions ui/component/commentsList/view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,13 @@ function CommentList(props: Props) {
// Reset comments
useEffect(() => {
if (page === 0) {
resetComments(uri);
if (claim) {
resetComments(claim.claim_id);
}
setPage(1);
}
}, [page, uri, resetComments]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [page, uri, resetComments]); // 'claim' is derived from 'uri'

// Fetch top-level comments
useEffect(() => {
Expand Down
2 changes: 2 additions & 0 deletions ui/component/router/view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const ListBlockedPage = lazyImport(() => import('page/listBlocked' /* webpackChu
const ListsPage = lazyImport(() => import('page/lists' /* webpackChunkName: "secondary" */));
const LiveStreamSetupPage = lazyImport(() => import('page/livestreamSetup' /* webpackChunkName: "secondary" */));
const LivestreamCurrentPage = lazyImport(() => import('page/livestreamCurrent' /* webpackChunkName: "secondary" */));
const OwnComments = lazyImport(() => import('page/ownComments' /* webpackChunkName: "ownComments" */));
const PasswordResetPage = lazyImport(() => import('page/passwordReset' /* webpackChunkName: "secondary" */));
const PasswordSetPage = lazyImport(() => import('page/passwordSet' /* webpackChunkName: "secondary" */));
const PublishPage = lazyImport(() => import('page/publish' /* webpackChunkName: "secondary" */));
Expand Down Expand Up @@ -329,6 +330,7 @@ function AppRouter(props: Props) {
<PrivateRoute {...props} path={`/$/${PAGES.SWAP}`} component={SwapPage} />
<PrivateRoute {...props} path={`/$/${PAGES.NOTIFICATIONS}`} component={NotificationsPage} />
<PrivateRoute {...props} path={`/$/${PAGES.AUTH_WALLET_PASSWORD}`} component={SignInWalletPasswordPage} />
<PrivateRoute {...props} path={`/$/${PAGES.SETTINGS_OWN_COMMENTS}`} component={OwnComments} />

<Route path={`/$/${PAGES.EMBED}/:claimName`} exact component={EmbedWrapperPage} />
<Route path={`/$/${PAGES.EMBED}/:claimName/:claimId`} exact component={EmbedWrapperPage} />
Expand Down
3 changes: 2 additions & 1 deletion ui/component/settingAccount/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { doWalletStatus, selectWalletIsEncrypted } from 'lbry-redux';
import { doWalletStatus, selectMyChannelClaims, selectWalletIsEncrypted } from 'lbry-redux';
import { selectUser, selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectLanguage } from 'redux/selectors/settings';

Expand All @@ -9,6 +9,7 @@ const select = (state) => ({
isAuthenticated: selectUserVerifiedEmail(state),
walletEncrypted: selectWalletIsEncrypted(state),
user: selectUser(state),
myChannels: selectMyChannelClaims(state),
language: selectLanguage(state),
});

Expand Down
14 changes: 13 additions & 1 deletion ui/component/settingAccount/view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ type Props = {
isAuthenticated: boolean,
walletEncrypted: boolean,
user: User,
myChannels: ?Array<ChannelClaim>,
// --- perform ---
doWalletStatus: () => void,
};

export default function SettingAccount(props: Props) {
const { isAuthenticated, walletEncrypted, user, doWalletStatus } = props;
const { isAuthenticated, walletEncrypted, user, myChannels, doWalletStatus } = props;
const [storedPassword, setStoredPassword] = React.useState(false);

// Determine if password is stored.
Expand Down Expand Up @@ -92,6 +93,17 @@ export default function SettingAccount(props: Props) {
</SettingsRow>
)}
{/* @endif */}

{myChannels && (
<SettingsRow title={__('Comments')} subtitle={__('View your past comments.')}>
<Button
button="inverse"
label={__('Manage')}
icon={ICONS.ARROW_RIGHT}
navigate={`/$/${PAGES.SETTINGS_OWN_COMMENTS}`}
/>
</SettingsRow>
)}
</>
}
/>
Expand Down
1 change: 1 addition & 0 deletions ui/constants/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const SORT_BY = {
OLDEST: 1,
CONTROVERSY: 2,
POPULARITY: 3,
NEWEST_NO_PINS: 4,
};

export const BLOCK_LEVEL = {
Expand Down
1 change: 1 addition & 0 deletions ui/constants/pageTitles.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const PAGE_TITLE = {
[PAGES.SETTINGS_STRIPE_ACCOUNT]: 'Bank Accounts',
[PAGES.SETTINGS_STRIPE_CARD]: 'Payment Methods',
[PAGES.SETTINGS_UPDATE_PWD]: 'Update password',
[PAGES.SETTINGS_OWN_COMMENTS]: 'Your comments',
[PAGES.SWAP]: 'Swap Credits',
[PAGES.TAGS_FOLLOWING]: 'Tags',
[PAGES.TAGS_FOLLOWING_MANAGE]: 'Manage tags',
Expand Down
1 change: 1 addition & 0 deletions ui/constants/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ exports.SETTINGS_NOTIFICATIONS = 'settings/notifications';
exports.SETTINGS_BLOCKED_MUTED = 'settings/block_and_mute';
exports.SETTINGS_CREATOR = 'settings/creator';
exports.SETTINGS_UPDATE_PWD = 'settings/update_password';
exports.SETTINGS_OWN_COMMENTS = 'settings/ownComments';
exports.SHOW = 'show';
exports.ACCOUNT = 'account';
exports.SEARCH = 'search';
Expand Down
33 changes: 33 additions & 0 deletions ui/page/ownComments/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { connect } from 'react-redux';
import { doCommentListOwn, doCommentReset } from 'redux/actions/comments';
import { selectActiveChannelClaim } from 'redux/selectors/app';
import {
selectIsFetchingComments,
makeSelectCommentsForUri,
makeSelectTotalCommentsCountForUri,
makeSelectTopLevelTotalPagesForUri,
} from 'redux/selectors/comments';
import { selectClaimsById } from 'lbry-redux';

import OwnComments from './view';

const select = (state) => {
const activeChannelClaim = selectActiveChannelClaim(state);
const uri = activeChannelClaim && activeChannelClaim.canonical_url;

return {
activeChannelClaim,
allComments: makeSelectCommentsForUri(uri)(state),
totalComments: makeSelectTotalCommentsCountForUri(uri)(state),
topLevelTotalPages: makeSelectTopLevelTotalPagesForUri(uri)(state),
isFetchingComments: selectIsFetchingComments(state),
claimsById: selectClaimsById(state),
};
};

const perform = (dispatch) => ({
doCommentReset: (a) => dispatch(doCommentReset(a)),
doCommentListOwn: (a, b, c) => dispatch(doCommentListOwn(a, b, c)),
});

export default connect(select, perform)(OwnComments);
Loading

0 comments on commit de6c6f9

Please sign in to comment.