mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat(post menu): add copy link button (share link)
This commit is contained in:
@@ -3,13 +3,86 @@ import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDis
|
||||
import { Comment } from '@plebbit/plebbit-react-hooks';
|
||||
import styles from './post-menu.module.css';
|
||||
import { getCommentMediaInfo } from '../../../lib/utils/media-utils';
|
||||
import { isValidURL } from '../../../lib/utils/url-utils';
|
||||
import { copyShareLinkToClipboard, isValidURL } from '../../../lib/utils/url-utils';
|
||||
|
||||
const PostMenu = ({ post }: Comment) => {
|
||||
const { cid, isDescription, isRules, link, subplebbitAddress } = post;
|
||||
const [menuBtnRotated, setMenuBtnRotated] = useState(false);
|
||||
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
|
||||
interface PostMenuProps {
|
||||
cid: string;
|
||||
isDescription?: boolean;
|
||||
isRules?: boolean;
|
||||
subplebbitAddress: string;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const CopyLinkButton = ({ cid, subplebbitAddress, onClose }: PostMenuProps) => {
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
copyShareLinkToClipboard(subplebbitAddress, cid);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<div className={styles.postMenuItem}>Copy link</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ImageSearchButton = ({ url, onClose }: { url: string; onClose: () => void }) => {
|
||||
const [isImageSearchMenuOpen, setIsImageSearchMenuOpen] = useState(false);
|
||||
return (
|
||||
<div
|
||||
className={`${styles.postMenuItem} ${styles.dropdown}`}
|
||||
onMouseOver={() => setIsImageSearchMenuOpen(true)}
|
||||
onMouseLeave={() => setIsImageSearchMenuOpen(false)}
|
||||
onClick={onClose}
|
||||
>
|
||||
Image search »
|
||||
{isImageSearchMenuOpen && (
|
||||
<div 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, isRules, subplebbitAddress, onClose }: PostMenuProps) => {
|
||||
const [isClientRedirectMenuOpen, setIsClientRedirectMenuOpen] = useState(false);
|
||||
const viewOnOtherClientLink = `p/${subplebbitAddress}${isDescription || isRules ? '' : `/c/${cid}`}`;
|
||||
return (
|
||||
<div
|
||||
className={`${styles.postMenuItem} ${styles.dropdown}`}
|
||||
onMouseOver={() => setIsClientRedirectMenuOpen(true)}
|
||||
onMouseLeave={() => setIsClientRedirectMenuOpen(false)}
|
||||
onClick={onClose}
|
||||
>
|
||||
View on »
|
||||
{isClientRedirectMenuOpen && (
|
||||
<div className={styles.dropdownMenu}>
|
||||
<a href={`https://seedit.app/#/${viewOnOtherClientLink}`} target='_blank' rel='noreferrer'>
|
||||
<div className={styles.postMenuItem}>Seedit</div>
|
||||
</a>
|
||||
<a href={`https://plebones.netlify.app/#/${viewOnOtherClientLink}`} target='_blank' rel='noreferrer'>
|
||||
<div className={styles.postMenuItem}>Plebones</div>
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const PostMenu = ({ post }: { post: Comment }) => {
|
||||
const { cid, isDescription, isRules, link, subplebbitAddress } = post;
|
||||
const commentMediaInfo = getCommentMediaInfo(post);
|
||||
const { thumbnail, type, url } = commentMediaInfo || {};
|
||||
const [menuBtnRotated, setMenuBtnRotated] = useState(false);
|
||||
|
||||
const { refs, floatingStyles, context } = useFloating({
|
||||
placement: 'bottom-start',
|
||||
@@ -18,19 +91,13 @@ const PostMenu = ({ post }: Comment) => {
|
||||
middleware: [offset({ mainAxis: 10, crossAxis: 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 viewOnOtherClientLink = `p/${subplebbitAddress}${isDescription || isRules ? '' : `/c/${cid}`}`;
|
||||
|
||||
const commentMediaInfo = getCommentMediaInfo(post);
|
||||
const { thumbnail, type, url } = commentMediaInfo || {};
|
||||
const handleClose = () => setMenuBtnRotated(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -47,55 +114,9 @@ const PostMenu = ({ post }: Comment) => {
|
||||
{menuBtnRotated && (
|
||||
<FloatingFocusManager context={context} modal={false}>
|
||||
<div className={styles.postMenu} ref={refs.setFloating} style={floatingStyles} aria-labelledby={headingId} {...getFloatingProps()}>
|
||||
{link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && (
|
||||
<div
|
||||
className={`${styles.postMenuItem} ${styles.dropdown}`}
|
||||
onMouseOver={() => setIsImageSearchMenuOpen(true)}
|
||||
onMouseLeave={() => setIsImageSearchMenuOpen(false)}
|
||||
>
|
||||
Image search »
|
||||
{isImageSearchMenuOpen && (
|
||||
<div className={styles.dropdownMenu}>
|
||||
<div className={styles.postMenuItem}>
|
||||
<a href={`https://lens.google.com/uploadbyurl?url=${url}`} target='_blank' rel='noreferrer'>
|
||||
Google
|
||||
</a>
|
||||
</div>
|
||||
<div className={styles.postMenuItem}>
|
||||
<a href={`https://www.yandex.com/images/search?img_url=${url}&rpt=imageview`} target='_blank' rel='noreferrer'>
|
||||
Yandex
|
||||
</a>
|
||||
</div>
|
||||
<div className={styles.postMenuItem}>
|
||||
<a href={`https://saucenao.com/search.php?url=${url}`} target='_blank' rel='noreferrer'>
|
||||
SauceNAO
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={`${styles.postMenuItem} ${styles.dropdown}`}
|
||||
onMouseOver={() => setIsClientRedirectMenuOpen(true)}
|
||||
onMouseLeave={() => setIsClientRedirectMenuOpen(false)}
|
||||
>
|
||||
View on »
|
||||
{isClientRedirectMenuOpen && (
|
||||
<div className={styles.dropdownMenu}>
|
||||
<div className={styles.postMenuItem}>
|
||||
<a href={`https://seedit.app/#/${viewOnOtherClientLink}`} target='_blank' rel='noreferrer'>
|
||||
Seedit
|
||||
</a>
|
||||
</div>
|
||||
<div className={styles.postMenuItem}>
|
||||
<a href={`https://plebones.netlify.app/#/${viewOnOtherClientLink}`} target='_blank' rel='noreferrer'>
|
||||
Plebones
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{cid && subplebbitAddress && <CopyLinkButton cid={cid} subplebbitAddress={subplebbitAddress} onClose={handleClose} />}
|
||||
{link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && url && <ImageSearchButton url={url} onClose={handleClose} />}
|
||||
<ViewOnButton cid={cid} isDescription={isDescription} isRules={isRules} subplebbitAddress={subplebbitAddress} onClose={handleClose} />
|
||||
</div>
|
||||
</FloatingFocusManager>
|
||||
)}
|
||||
|
||||
@@ -16,7 +16,7 @@ export const isValidURL = (url: string) => {
|
||||
};
|
||||
|
||||
export const copyShareLinkToClipboard = (subplebbitAddress: string, cid: string) => {
|
||||
const shareLink = `https://pleb.bz/p/${subplebbitAddress}/c/${cid}`;
|
||||
const shareLink = `https://pleb.bz/p/${subplebbitAddress}/c/${cid}?redirect=plebchan.eth.limo`;
|
||||
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(shareLink);
|
||||
|
||||
Reference in New Issue
Block a user