refactor: rename PostPage to Post, export Post component from Post view

This commit is contained in:
Tom (plebeius.eth)
2024-06-11 15:49:26 +02:00
parent 7100030043
commit 8e5a5919fa
30 changed files with 89 additions and 94 deletions
@@ -0,0 +1 @@
export { default } from './post-menu-desktop';
@@ -0,0 +1,116 @@
.postMenu {
position: absolute;
background-color: var(--post-menu-desktop-background-color);
border-bottom: var(--post-menu-desktop-border-bottom);
border-right: var(--post-menu-desktop-border-right);
outline: none;
z-index: 2;
}
.postMenuBtnWrapper {
position: relative;
display: inline-block;
padding-left: 15px;
}
.postMenuBtn {
color: var(--post-menu-desktop-button-color);
transition: transform 0.1s;
transform: rotate(90deg);
position: absolute;
bottom: -4px;
}
.postMenuBtn:hover {
cursor: pointer;
color: var(--post-menu-desktop-button-color-hover);
}
.postMenuItem {
cursor: pointer;
padding: 2px 4px;
border: 1px solid var(--post-menu-desktop-item-border-color);
background-color: var(--post-menu-desktop-item-background-color);
border-bottom: none;
}
.postMenuItem:hover {
background-color: var(--post-menu-desktop-item-hover-background-color);
}
.dropdown {
position: relative;
}
.dropdownMenu {
position: absolute;
left: 100%;
top: -1px;
display: none;
border-bottom: var(--post-menu-desktop-border-bottom);
border-right: var(--post-menu-desktop-border-right);
}
.dropdown a {
text-decoration: none;
color: inherit;
}
.dropdown:hover .dropdownMenu {
display: block;
}
.postMenuBtnCatalogWrapper {
left: 5px;
top: 5px;
position: relative;
}
.postMenuBtnCatalog {
position: absolute;
bottom: 5px;
line-height: 1em;
color: var(--catalog-post-menu-desktop-btn-color);
opacity: var(--catalog-post-menu-desktop-btn-opacity);
transition: transform 0.1s;
}
.postMenuBtnCatalog:hover {
cursor: pointer;
color: var(--catalog-post-menu-desktop-btn-hover-color);
opacity: var(--catalog-post-menu-desktop-btn-hover-opacity);
}
.postMenuBtnCatalog {
/* preserve unicode triangle for button, some browsers will use an emoji */
font-variant: normal;
font-feature-settings: "tnum";
-webkit-font-feature-settings: "tnum"; /* Chrome, Opera, and Safari */
-moz-font-feature-settings: "tnum"; /* Firefox */
font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
.postMenuBtn {
width: 1em;
text-align: center;
font-weight: 700;
font-size: 16px;
}
.postMenuBtnWrapper {
position: relative;
padding-right: 12px;
}
}
@media (min-width: 640px) {
.postMenuBtn {
right: -2px;
opacity: var(--post-menu-desktop-btn-opacity);
}
.stickyIconWrapper {
padding-right: 18px;
}
}
@@ -0,0 +1,182 @@
import { useState } from 'react';
import { createPortal } from 'react-dom';
import { useLocation, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react';
import { Comment, useBlock } from '@plebbit/plebbit-react-hooks';
import styles from './post-menu-desktop.module.css';
import { getCommentMediaInfo } from '../../../lib/utils/media-utils';
import { copyShareLinkToClipboard, isValidURL } from '../../../lib/utils/url-utils';
import { isAllView, isCatalogView, isPostPageView, isSubscriptionsView } from '../../../lib/utils/view-utils';
import _ from 'lodash';
interface PostMenuDesktopProps {
cid: string;
isDescription?: boolean;
isInAllView?: boolean;
isInSubscriptionsView?: boolean;
isRules?: boolean;
subplebbitAddress: string;
onClose: () => void;
}
const CopyLinkButton = ({ cid, subplebbitAddress, onClose }: PostMenuDesktopProps) => {
const { t } = useTranslation();
return (
<div
onClick={() => {
copyShareLinkToClipboard(subplebbitAddress, cid);
onClose();
}}
>
<div className={styles.postMenuItem}>{t('copy_link')}</div>
</div>
);
};
const ImageSearchButton = ({ url, onClose }: { url: string; onClose: () => void }) => {
const { t } = useTranslation();
const [isImageSearchMenuOpen, setIsImageSearchMenuOpen] = useState(false);
const { refs, floatingStyles } = useFloating({
placement: 'right-start',
middleware: [flip(), shift({ padding: 10 })],
});
return (
<div
className={`${styles.postMenuItem} ${styles.dropdown}`}
onMouseOver={() => setIsImageSearchMenuOpen(true)}
onMouseLeave={() => setIsImageSearchMenuOpen(false)}
ref={refs.setReference}
onClick={onClose}
>
{_.capitalize(t('image_search'))} »
{isImageSearchMenuOpen && (
<div ref={refs.setFloating} style={floatingStyles} className={styles.dropdownMenu}>
<a href={`https://lens.google.com/uploadbyurl?url=${url}`} target='_blank' rel='noreferrer'>
<div className={styles.postMenuItem}>Google</div>
</a>
<a href={`https://www.yandex.com/images/search?img_url=${url}&rpt=imageview`} target='_blank' rel='noreferrer'>
<div className={styles.postMenuItem}>Yandex</div>
</a>
<a href={`https://saucenao.com/search.php?url=${url}`} target='_blank' rel='noreferrer'>
<div className={styles.postMenuItem}>SauceNAO</div>
</a>
</div>
)}
</div>
);
};
const ViewOnButton = ({ cid, isDescription, isInAllView, isInSubscriptionsView, isRules, subplebbitAddress, onClose }: PostMenuDesktopProps) => {
const { t } = useTranslation();
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
const viewOnOtherClientLink = `p/${isInAllView ? 'all' : isInSubscriptionsView ? 'subscriptions' : subplebbitAddress}${isDescription || isRules ? '' : `/c/${cid}`}`;
const { refs, floatingStyles } = useFloating({
placement: 'right-start',
middleware: [flip(), shift({ padding: 10 })],
});
return (
<div
className={`${styles.postMenuItem} ${styles.dropdown}`}
onMouseOver={() => setIsClientRedirectMenuOpen(true)}
onMouseLeave={() => setIsClientRedirectMenuOpen(false)}
ref={refs.setReference}
onClick={onClose}
>
{_.capitalize(t('view_on'))} »
{isClientRedirectMenuOpen && (
<div ref={refs.setFloating} style={floatingStyles} className={styles.dropdownMenu}>
<a href={`https://seedit.eth.limo/#/${viewOnOtherClientLink}`} target='_blank' rel='noreferrer'>
<div className={styles.postMenuItem}>Seedit</div>
</a>
<a href={`https://plebones.eth.limo/#/${viewOnOtherClientLink}`} target='_blank' rel='noreferrer'>
<div className={styles.postMenuItem}>Plebones</div>
</a>
</div>
)}
</div>
);
};
const PostMenuDesktop = ({ post }: { post: Comment }) => {
const { t } = useTranslation();
const { cid, isDescription, isRules, link, postCid, subplebbitAddress } = post || {};
const commentMediaInfo = getCommentMediaInfo(post);
const { thumbnail, type, url } = commentMediaInfo || {};
const [menuBtnRotated, setMenuBtnRotated] = useState(false);
const { blocked, unblock, block } = useBlock({ cid });
const location = useLocation();
const params = useParams();
const isInAllView = isAllView(location.pathname);
const isInCatalogView = isCatalogView(location.pathname, params);
const isInPostPageView = isPostPageView(location.pathname, params);
const isInSubscriptionsView = isSubscriptionsView(location.pathname);
const { refs, floatingStyles, context } = useFloating({
placement: 'bottom-start',
open: menuBtnRotated,
onOpenChange: setMenuBtnRotated,
middleware: [offset({ mainAxis: isInCatalogView ? -2 : 6, crossAxis: isInCatalogView ? -1 : 5 }), flip({ fallbackAxisSideDirection: 'end' }), shift({ padding: 10 })],
whileElementsMounted: autoUpdate,
});
const click = useClick(context);
const dismiss = useDismiss(context);
const role = useRole(context);
const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss, role]);
const headingId = useId();
const handleClose = () => setMenuBtnRotated(false);
return (
<>
<span className={isInCatalogView ? styles.postMenuBtnCatalogWrapper : styles.postMenuBtnWrapper} ref={refs.setReference} {...getReferenceProps()}>
<span
className={isInCatalogView ? styles.postMenuBtnCatalog : styles.postMenuBtn}
title='Post menu'
onClick={() => setMenuBtnRotated((prev) => !prev)}
style={{ transform: menuBtnRotated ? 'rotate(90deg)' : 'rotate(0deg)' }}
>
</span>
</span>
{menuBtnRotated &&
createPortal(
<FloatingFocusManager context={context} modal={false}>
<div className={styles.postMenu} ref={refs.setFloating} style={floatingStyles} aria-labelledby={headingId} {...getFloatingProps()}>
{cid && subplebbitAddress && <CopyLinkButton cid={cid} subplebbitAddress={subplebbitAddress} onClose={handleClose} />}
{!isInPostPageView && !isDescription && !isRules && (
<div
className={styles.postMenuItem}
onClick={() => {
blocked ? unblock() : block();
handleClose();
}}
>
{blocked ? (postCid === cid ? t('unhide_thread') : t('unhide_post')) : postCid === cid ? t('hide_thread') : t('hide_post')}
</div>
)}
{link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && url && <ImageSearchButton url={url} onClose={handleClose} />}
<ViewOnButton
cid={cid}
isDescription={isDescription}
isInAllView={isInAllView}
isInSubscriptionsView={isInSubscriptionsView}
isRules={isRules}
subplebbitAddress={subplebbitAddress}
onClose={handleClose}
/>
</div>
</FloatingFocusManager>,
document.body,
)}
</>
);
};
export default PostMenuDesktop;