mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
style(board): show rules under description
This commit is contained in:
@@ -293,19 +293,18 @@ const PostPageStats = () => {
|
|||||||
const params = useParams();
|
const params = useParams();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const isInDescriptionView = isDescriptionView(location.pathname, params);
|
const isInDescriptionView = isDescriptionView(location.pathname, params);
|
||||||
const isInRulesView = isRulesView(location.pathname, params);
|
|
||||||
|
|
||||||
const comment = useComment({ commentCid: params?.commentCid });
|
const comment = useComment({ commentCid: params?.commentCid });
|
||||||
const { closed, pinned, replyCount } = comment || {};
|
const { closed, pinned, replyCount } = comment || {};
|
||||||
const linkCount = useCountLinksInReplies(comment);
|
const linkCount = useCountLinksInReplies(comment);
|
||||||
|
|
||||||
const displayReplyCount = replyCount !== undefined ? replyCount.toString() : '?';
|
const displayReplyCount = replyCount !== undefined ? replyCount.toString() : isInDescriptionView ? 1 : '?';
|
||||||
const replyCountTooltip = replyCount !== undefined ? _.capitalize(t('replies')) : t('loading');
|
const replyCountTooltip = replyCount !== undefined || isInDescriptionView ? _.capitalize(t('replies')) : t('loading');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{(pinned || isInDescriptionView || isInRulesView) && `${_.capitalize(t('sticky'))} / `}
|
{(pinned || isInDescriptionView) && `${_.capitalize(t('sticky'))} / `}
|
||||||
{(closed || isInDescriptionView || isInRulesView) && `${_.capitalize(t('closed'))} / `}
|
{(closed || isInDescriptionView) && `${_.capitalize(t('closed'))} / `}
|
||||||
<Tooltip children={displayReplyCount} content={replyCountTooltip} /> / <Tooltip children={linkCount?.toString()} content={_.capitalize(t('links'))} />
|
<Tooltip children={displayReplyCount} content={replyCountTooltip} /> / <Tooltip children={linkCount?.toString()} content={_.capitalize(t('links'))} />
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||||
import { Comment, useAccount, useAuthorAvatar, useComment, useEditedComment } from '@plebbit/plebbit-react-hooks';
|
import { Comment, useAccount, useAuthorAvatar, useComment, useEditedComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||||
import styles from '../../views/post/post.module.css';
|
import styles from '../../views/post/post.module.css';
|
||||||
import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail, getMediaDimensions } from '../../lib/utils/media-utils';
|
import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail, getMediaDimensions } from '../../lib/utils/media-utils';
|
||||||
@@ -30,6 +30,8 @@ import Tooltip from '../tooltip';
|
|||||||
import { PostProps } from '../../views/post/post';
|
import { PostProps } from '../../views/post/post';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import SubplebbitRules from '../subplebbit-rules';
|
||||||
|
import subplebbitRules from '../subplebbit-rules';
|
||||||
|
|
||||||
interface ShowOmittedRepliesState {
|
interface ShowOmittedRepliesState {
|
||||||
showOmittedReplies: Record<string, boolean>;
|
showOmittedReplies: Record<string, boolean>;
|
||||||
@@ -274,7 +276,7 @@ const PostMedia = ({ post }: PostProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const PostMessage = ({ post }: PostProps) => {
|
const PostMessage = ({ post }: PostProps) => {
|
||||||
const { cid, content, deleted, edit, original, parentCid, postCid, reason, removed, state } = post || {};
|
const { cid, content, deleted, edit, isRules, original, parentCid, postCid, reason, removed, state } = post || {};
|
||||||
// TODO: commentAuthor is not yet available outside of editedComment, wait for API to be updated
|
// TODO: commentAuthor is not yet available outside of editedComment, wait for API to be updated
|
||||||
// const banned = !!post?.commentAuthor?.banExpiresAt;
|
// const banned = !!post?.commentAuthor?.banExpiresAt;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -297,7 +299,7 @@ const PostMessage = ({ post }: PostProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<blockquote className={styles.postMessage}>
|
<blockquote className={`${styles.postMessage} ${isRules && styles.rulesMessage}`}>
|
||||||
{isReply && !(removed || deleted) && state !== 'failed' && isReplyingToReply && <ReplyQuotePreview isQuotelinkReply={true} quotelinkReply={quotelinkReply} />}
|
{isReply && !(removed || deleted) && state !== 'failed' && isReplyingToReply && <ReplyQuotePreview isQuotelinkReply={true} quotelinkReply={quotelinkReply} />}
|
||||||
{removed ? (
|
{removed ? (
|
||||||
reason ? (
|
reason ? (
|
||||||
@@ -433,6 +435,17 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
|
|||||||
|
|
||||||
const stateString = useStateString(post);
|
const stateString = useStateString(post);
|
||||||
|
|
||||||
|
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||||
|
|
||||||
|
const subplebbitRulesReply = {
|
||||||
|
isRules: true,
|
||||||
|
subplebbitAddress,
|
||||||
|
timestamp: subplebbit?.createdAt,
|
||||||
|
author: { displayName: `## ${t('board_mods')}` },
|
||||||
|
content: `${subplebbit?.rules?.map((rule: string, index: number) => `${index + 1}. ${rule}`).join('\n')}`,
|
||||||
|
replyCount: 0,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.postDesktop}>
|
<div className={styles.postDesktop}>
|
||||||
{showReplies ? (
|
{showReplies ? (
|
||||||
@@ -477,8 +490,6 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
|
|||||||
{!isHidden &&
|
{!isHidden &&
|
||||||
!(pinned && !isInPostPageView && !showOmittedReplies[cid]) &&
|
!(pinned && !isInPostPageView && !showOmittedReplies[cid]) &&
|
||||||
!isInPendingPostView &&
|
!isInPendingPostView &&
|
||||||
!isDescription &&
|
|
||||||
!isRules &&
|
|
||||||
replies &&
|
replies &&
|
||||||
showReplies &&
|
showReplies &&
|
||||||
(showAllReplies || showOmittedReplies[cid] ? replies : replies.slice(-5)).map((reply, index) => (
|
(showAllReplies || showOmittedReplies[cid] ? replies : replies.slice(-5)).map((reply, index) => (
|
||||||
@@ -486,6 +497,11 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
|
|||||||
<Reply openReplyModal={openReplyModal} reply={reply} roles={roles} postReplyCount={replyCount} />
|
<Reply openReplyModal={openReplyModal} reply={reply} roles={roles} postReplyCount={replyCount} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
{isDescription && subplebbit?.rules && subplebbit?.rules.length > 0 && (
|
||||||
|
<div className={styles.replyContainer}>
|
||||||
|
<Reply reply={subplebbitRulesReply} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!isInPendingPostView &&
|
{!isInPendingPostView &&
|
||||||
(stateString && stateString !== 'Failed' && state !== 'succeeded' ? (
|
(stateString && stateString !== 'Failed' && state !== 'succeeded' ? (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||||
import { Comment, useAccount, useAuthorAvatar, useComment, useEditedComment } from '@plebbit/plebbit-react-hooks';
|
import { Comment, useAccount, useAuthorAvatar, useComment, useEditedComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||||
import styles from '../../views/post/post.module.css';
|
import styles from '../../views/post/post.module.css';
|
||||||
import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
|
import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
|
||||||
@@ -200,7 +200,7 @@ const ReplyBacklinks = ({ post }: PostProps) => {
|
|||||||
|
|
||||||
const PostMessageMobile = ({ post }: PostProps) => {
|
const PostMessageMobile = ({ post }: PostProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { cid, content, deleted, edit, original, parentCid, postCid, reason, removed, state } = post || {};
|
const { cid, content, deleted, edit, isRules, original, parentCid, postCid, reason, removed, state } = post || {};
|
||||||
// TODO: commentAuthor is not available outside of editedComment, update when available
|
// TODO: commentAuthor is not available outside of editedComment, update when available
|
||||||
// const banned = !!post?.commentAuthor?.banExpiresAt;
|
// const banned = !!post?.commentAuthor?.banExpiresAt;
|
||||||
const [showOriginal, setShowOriginal] = useState(false);
|
const [showOriginal, setShowOriginal] = useState(false);
|
||||||
@@ -223,7 +223,7 @@ const PostMessageMobile = ({ post }: PostProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<blockquote className={`${styles.postMessage} ${!isReply && styles.clampLines}`}>
|
<blockquote className={`${styles.postMessage} ${!isReply && styles.clampLines} ${isRules && styles.rulesMessage}`}>
|
||||||
{isReply && !(removed || deleted) && state !== 'failed' && isReplyingToReply && <ReplyQuotePreview isQuotelinkReply={true} quotelinkReply={quotelinkReply} />}
|
{isReply && !(removed || deleted) && state !== 'failed' && isReplyingToReply && <ReplyQuotePreview isQuotelinkReply={true} quotelinkReply={quotelinkReply} />}
|
||||||
{removed ? (
|
{removed ? (
|
||||||
reason ? (
|
reason ? (
|
||||||
@@ -353,6 +353,17 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
|
|||||||
|
|
||||||
const stateString = useStateString(post);
|
const stateString = useStateString(post);
|
||||||
|
|
||||||
|
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||||
|
const showRules = isDescription && subplebbit?.rules && subplebbit?.rules.length > 0;
|
||||||
|
const subplebbitRulesReply = {
|
||||||
|
isRules: true,
|
||||||
|
subplebbitAddress,
|
||||||
|
timestamp: subplebbit?.createdAt,
|
||||||
|
author: { displayName: `## ${t('board_mods')}` },
|
||||||
|
content: `${subplebbit?.rules?.map((rule: string, index: number) => `${index + 1}. ${rule}`).join('\n')}`,
|
||||||
|
replyCount: 0,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{hidden && !isInPostPageView ? (
|
{hidden && !isInPostPageView ? (
|
||||||
@@ -394,8 +405,6 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
|
|||||||
</div>
|
</div>
|
||||||
{!(pinned && !isInPostView) &&
|
{!(pinned && !isInPostView) &&
|
||||||
!isInPendingPostView &&
|
!isInPendingPostView &&
|
||||||
!isDescription &&
|
|
||||||
!isRules &&
|
|
||||||
replies &&
|
replies &&
|
||||||
showReplies &&
|
showReplies &&
|
||||||
(showAllReplies ? replies : replies.slice(-5)).map((reply, index) => (
|
(showAllReplies ? replies : replies.slice(-5)).map((reply, index) => (
|
||||||
@@ -403,6 +412,11 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
|
|||||||
<Reply openReplyModal={openReplyModal} postReplyCount={replyCount} reply={reply} roles={roles} />
|
<Reply openReplyModal={openReplyModal} postReplyCount={replyCount} reply={reply} roles={roles} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
{showRules && (
|
||||||
|
<div className={styles.replyContainer}>
|
||||||
|
<Reply reply={subplebbitRulesReply} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!isInPendingPostView &&
|
{!isInPendingPostView &&
|
||||||
(stateString && stateString !== 'Failed' && state !== 'succeeded' ? (
|
(stateString && stateString !== 'Failed' && state !== 'succeeded' ? (
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const SubplebbitDescription = ({ avatarUrl, createdAt, description, shortAddress
|
|||||||
author: { displayName: `## ${t('board_mods')}` },
|
author: { displayName: `## ${t('board_mods')}` },
|
||||||
content: isInAllView ? multisubMetadata?.description : description,
|
content: isInAllView ? multisubMetadata?.description : description,
|
||||||
link: avatarUrl,
|
link: avatarUrl,
|
||||||
replyCount: 0,
|
replyCount: 1,
|
||||||
title: t('welcome_to_board', {
|
title: t('welcome_to_board', {
|
||||||
board: isInAllView ? multisubMetadata?.title : title || `p/${shortAddress}`,
|
board: isInAllView ? multisubMetadata?.title : title || `p/${shortAddress}`,
|
||||||
interpolation: { escapeValue: false },
|
interpolation: { escapeValue: false },
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolea
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rules && rules.length > 0) {
|
// rules are shown in description thread if both are set
|
||||||
|
if (rules && rules.length > 0 && !description) {
|
||||||
_feed.unshift({
|
_feed.unshift({
|
||||||
isRules: true,
|
isRules: true,
|
||||||
subplebbitAddress: address,
|
subplebbitAddress: address,
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ const useReplies = (comment: Comment) => {
|
|||||||
});
|
});
|
||||||
}, [flattenedReplies, accountRepliesNotYetPublished]);
|
}, [flattenedReplies, accountRepliesNotYetPublished]);
|
||||||
|
|
||||||
|
// if the comment is a fake comment for description or rules, return an empty array
|
||||||
|
if (comment?.isDescription || comment?.isRules) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
return repliesAndNotYetPublishedReplies;
|
return repliesAndNotYetPublishedReplies;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ const Board = () => {
|
|||||||
)}
|
)}
|
||||||
{feed.length !== 0 ? (
|
{feed.length !== 0 ? (
|
||||||
<>
|
<>
|
||||||
{rules && rules.length > 0 && <SubplebbitRules subplebbitAddress={subplebbitAddress} createdAt={createdAt} rules={rules} />}
|
{rules && !description && rules.length > 0 && <SubplebbitRules subplebbitAddress={subplebbitAddress} createdAt={createdAt} rules={rules} />}
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
increaseViewportBy={{ bottom: 1200, top: 1200 }}
|
increaseViewportBy={{ bottom: 1200, top: 1200 }}
|
||||||
totalCount={combinedFeed.length}
|
totalCount={combinedFeed.length}
|
||||||
|
|||||||
@@ -163,6 +163,10 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rulesMessage {
|
||||||
|
font-weight: 700 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.postDesktop .abbr {
|
.postDesktop .abbr {
|
||||||
color: var(--post-mobile-abbr-text-color);
|
color: var(--post-mobile-abbr-text-color);
|
||||||
font-size: var(--post-mobile-abbr-font-size);
|
font-size: var(--post-mobile-abbr-font-size);
|
||||||
|
|||||||
Reference in New Issue
Block a user