mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat(post): add mobile footer to thread view
Post a Reply, Return/Catalog/Top, Update/Auto buttons, stats row (Replies/Images/Page), and license footer links. Matches mobile board view styling.
This commit is contained in:
@@ -175,6 +175,19 @@
|
||||
padding: 8px 8px;
|
||||
}
|
||||
|
||||
.mobileFooterButtons a {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
.mobileFooterButtons input[type='checkbox'] {
|
||||
margin: 0 3px 0 0;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
border-radius: 0;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.mobileFooterPagination {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -209,3 +222,23 @@
|
||||
.mobileFooterLinks a:hover {
|
||||
color: var(--boardsbar-desktop-link-text-color-hover);
|
||||
}
|
||||
|
||||
.mobileFooterStats {
|
||||
padding: 4px 8px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.threadMobileFooterContent .mobileFooterButtons {
|
||||
padding-top: 0;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.threadMobileFooterContent .mobileFooterButtons:first-child {
|
||||
padding-top: 25px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.threadMobileFooterContent .mobileFooterStats {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
import { useComment } from '@bitsocialhq/pkc-react-hooks';
|
||||
import BoardsBar from '../boards-bar';
|
||||
import SiteLegalMeta from '../site-legal-meta';
|
||||
import StyleSelector from '../style-selector/style-selector';
|
||||
import { ReturnButton, CatalogButton, TopButton, UpdateButton, AutoButton, PostPageStats, RefreshButton } from '../board-buttons/board-buttons';
|
||||
import { isAllView, isSubscriptionsView, isModView } from '../../lib/utils/view-utils';
|
||||
import useReplyModalStore from '../../stores/use-reply-modal-store';
|
||||
import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
|
||||
import { usePostPageNumber } from '../../hooks/use-post-page-number';
|
||||
import { useDirectoryByAddress } from '../../hooks/use-directories';
|
||||
import capitalize from 'lodash/capitalize';
|
||||
import styles from './footer.module.css';
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@@ -165,3 +170,63 @@ export const PageFooterMobile = ({ children }: { children: React.ReactNode }) =>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ThreadFooterMobile
|
||||
* Mobile thread page footer: Post a Reply, Return/Catalog/Top, Update/Auto, stats.
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
export interface ThreadFooterMobileProps {
|
||||
postCid: string;
|
||||
threadNumber: number | undefined;
|
||||
subplebbitAddress: string;
|
||||
isThreadClosed?: boolean;
|
||||
}
|
||||
|
||||
export const ThreadFooterMobile = ({ postCid, threadNumber, subplebbitAddress, isThreadClosed = false }: ThreadFooterMobileProps) => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const params = useParams();
|
||||
const { openReplyModalEmpty } = useReplyModalStore();
|
||||
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInSubscriptionsView = isSubscriptionsView(location.pathname, params);
|
||||
const isInModView = isModView(location.pathname);
|
||||
|
||||
const post = useComment({ commentCid: postCid });
|
||||
const { replyCount } = post || {};
|
||||
const linkCount = useCountLinksInReplies(post);
|
||||
const directoryEntry = useDirectoryByAddress(subplebbitAddress);
|
||||
const requirePostLinkIsMedia = directoryEntry?.features?.requirePostLinkIsMedia === true;
|
||||
const pageNumber = usePostPageNumber({ subplebbitAddress, postCid, enabled: true });
|
||||
|
||||
const handlePostReplyClick = () => {
|
||||
if (isThreadClosed) return;
|
||||
openReplyModalEmpty(postCid, threadNumber, subplebbitAddress);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageFooterMobile>
|
||||
<div className={styles.threadMobileFooterContent}>
|
||||
<div className={styles.mobileFooterButtons}>
|
||||
<button className='button' onClick={handlePostReplyClick} disabled={isThreadClosed}>
|
||||
{t('post_a_reply')}
|
||||
</button>
|
||||
</div>
|
||||
<div className={styles.mobileFooterButtons}>
|
||||
<ReturnButton address={subplebbitAddress} isInAllView={isInAllView} isInSubscriptionsView={isInSubscriptionsView} isInModView={isInModView} />
|
||||
<CatalogButton address={subplebbitAddress} isInAllView={isInAllView} isInSubscriptionsView={isInSubscriptionsView} isInModView={isInModView} />
|
||||
<TopButton />
|
||||
</div>
|
||||
<div className={styles.mobileFooterButtons}>
|
||||
<UpdateButton />
|
||||
<AutoButton />
|
||||
</div>
|
||||
<div className={styles.mobileFooterStats}>
|
||||
{capitalize(t('replies'))}: {replyCount ?? '?'} / {capitalize(requirePostLinkIsMedia ? t('images') : t('links'))}: {linkCount ?? '?'} /{' '}
|
||||
{t('pagination.pageLabel')}: {pageNumber ?? '?'}
|
||||
</div>
|
||||
</div>
|
||||
</PageFooterMobile>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { PageFooterDesktop, PageFooterMobile, CatalogFooterFirstRow, ThreadFooterFirstRow, ThreadFooterStyleRow } from './footer';
|
||||
export type { PageFooterDesktopProps, CatalogFooterFirstRowProps, ThreadFooterFirstRowProps } from './footer';
|
||||
export { PageFooterDesktop, PageFooterMobile, CatalogFooterFirstRow, ThreadFooterFirstRow, ThreadFooterStyleRow, ThreadFooterMobile } from './footer';
|
||||
export type { PageFooterDesktopProps, CatalogFooterFirstRowProps, ThreadFooterFirstRowProps, ThreadFooterMobileProps } from './footer';
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useDirectories } from '../../hooks/use-directories';
|
||||
import { isDirectoryBoard } from '../../lib/utils/route-utils';
|
||||
import useIsMobile from '../../hooks/use-is-mobile';
|
||||
import ErrorDisplay from '../../components/error-display/error-display';
|
||||
import { PageFooterDesktop, ThreadFooterFirstRow, ThreadFooterStyleRow } from '../../components/footer';
|
||||
import { PageFooterDesktop, ThreadFooterFirstRow, ThreadFooterStyleRow, ThreadFooterMobile } from '../../components/footer';
|
||||
import PostDesktop from '../../components/post-desktop';
|
||||
import PostMobile from '../../components/post-mobile';
|
||||
import styles from './post.module.css';
|
||||
@@ -203,10 +203,13 @@ const PostPage = () => {
|
||||
</div>
|
||||
)}
|
||||
{post?.cid && subplebbitAddress ? (
|
||||
<PageFooterDesktop
|
||||
firstRow={<ThreadFooterFirstRow postCid={post.cid} threadNumber={post?.number} subplebbitAddress={subplebbitAddress} isThreadClosed={!!post?.locked} />}
|
||||
styleRow={<ThreadFooterStyleRow />}
|
||||
/>
|
||||
<>
|
||||
<PageFooterDesktop
|
||||
firstRow={<ThreadFooterFirstRow postCid={post.cid} threadNumber={post?.number} subplebbitAddress={subplebbitAddress} isThreadClosed={!!post?.locked} />}
|
||||
styleRow={<ThreadFooterStyleRow />}
|
||||
/>
|
||||
<ThreadFooterMobile postCid={post.cid} threadNumber={post?.number} subplebbitAddress={subplebbitAddress} isThreadClosed={!!post?.locked} />
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user