From 6458c7630d04f18dd07382c051c5b04b7035845a Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Fri, 3 Jan 2025 23:59:10 +0100 Subject: [PATCH] add share button to replies --- package.json | 2 +- src/lib/url-utils.ts | 4 +- src/themes.css | 6 +- src/views/post-page/post-page.module.css | 35 +++++++++- src/views/post-page/post-page.tsx | 87 ++++++++++++++++++++---- yarn.lock | 8 +-- 6 files changed, 116 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 4a57dfd..94171c6 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "GPL-2.0-only", "private": true, "dependencies": { - "@floating-ui/react": "0.26.28", + "@floating-ui/react": "^0.27.2", "@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#be1a1f317db7c4096f0d1c79452e13452bf9df78", "@testing-library/jest-dom": "5.17.0", "@testing-library/react": "13.4.0", diff --git a/src/lib/url-utils.ts b/src/lib/url-utils.ts index aacfae9..e920cfc 100644 --- a/src/lib/url-utils.ts +++ b/src/lib/url-utils.ts @@ -15,8 +15,8 @@ export const isValidURL = (url: string) => { } }; -export const copyShareLinkToClipboard = (subplebbitAddress: string, cid: string) => { - const shareLink = `https://pleb.bz/p/${subplebbitAddress}/c/${cid}`; +export const copyShareLinkToClipboard = (postCid: string) => { + const shareLink = `https://blog.plebbit.eth.limo/#/c/${postCid}`; if (navigator.clipboard) { navigator.clipboard.writeText(shareLink); diff --git a/src/themes.css b/src/themes.css index 5741aef..60be2a1 100644 --- a/src/themes.css +++ b/src/themes.css @@ -1,6 +1,6 @@ :root .dark { --background-color: #000; - --font-family: 'Roboto Mono', monospace; + --button-hover-background-color: #1f1f1f; --color-1: #00ff00; --color-1-opaque: #00ff0020; --color-1-secondary: #03ae03; @@ -9,12 +9,13 @@ --color-2-secondary: #a2a037; --color-info: #808080; --color-post: #fff; + --font-family: 'Roboto Mono', monospace; --hero-image: var(--dark-hero-url); } :root .light { --background-color: #fff; - --font-family: 'Roboto Mono', monospace; + --button-hover-background-color: #f0f0f0; --color-1: #000; --color-1-opaque: #d4d4d4ca; --color-1-secondary: #767676; @@ -23,5 +24,6 @@ --color-2-secondary: #343434; --color-info: #808080; --color-post: #000; + --font-family: 'Roboto Mono', monospace; --hero-image: var(--light-hero-url); } \ No newline at end of file diff --git a/src/views/post-page/post-page.module.css b/src/views/post-page/post-page.module.css index ff2201e..bea35ad 100644 --- a/src/views/post-page/post-page.module.css +++ b/src/views/post-page/post-page.module.css @@ -309,11 +309,11 @@ flex: 1; } -.replyButton { +.replyButtons { float: left; } -.replyButton button { +.replyButtons button { color: var(--color-info); background: none; border: none; @@ -322,6 +322,7 @@ cursor: pointer; font-weight: 700 !important; font-size: 14px; + margin-right: 10px; } .importNotice { @@ -361,4 +362,32 @@ .accountInfo { font-size: 12px; color: var(--color-info); -} \ No newline at end of file +} + +.modal { + z-index: 7; + background-color: var(--background-color); + border: 1px solid var(--color-info); + outline: none; + font-size: 12px; +} + +.menuItem { + color: inherit; + cursor: pointer; + padding: 2px 3px 1px 3px; + display: block; +} + +.menuItem a { + color: inherit; + text-decoration: none; +} + +.menuItem a:focus { + outline: none; +} + +.menuItem:hover { + background-color: var(--button-hover-background-color); +} diff --git a/src/views/post-page/post-page.tsx b/src/views/post-page/post-page.tsx index d24a5a1..a665de8 100644 --- a/src/views/post-page/post-page.tsx +++ b/src/views/post-page/post-page.tsx @@ -1,5 +1,6 @@ import { useEffect, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; +import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react'; import { useComment, Comment, importAccount, useAccounts, setActiveAccount, deleteAccount, useAccount } from '@plebbit/plebbit-react-hooks'; import { useCommentMediaInfo } from '../../hooks/use-comment-media-info'; import { CommentMediaInfo } from '../../lib/media-utils'; @@ -15,6 +16,7 @@ import LoadingEllipsis from '../../components/loading-ellipsis'; import useStateString from '../../hooks/use-state-string'; import useWindowWidth from '../../hooks/use-window-width'; import useAccountImportStore from '../../stores/use-account-import-store'; +import { copyShareLinkToClipboard } from '../../lib/url-utils'; const getReadingTime = (text: string) => { @@ -95,8 +97,30 @@ const Post = ({comment}: {comment: Comment}) => { ) }; +const ShareButton = ({ postCid }: { postCid: string }) => { + const [hasCopied, setHasCopied] = useState(false); + + useEffect(() => { + if (hasCopied) { + setTimeout(() => setHasCopied(false), 2000); + } + }, [hasCopied]); + + return ( +
{ + setHasCopied(true); + copyShareLinkToClipboard(postCid); + }} + > + {hasCopied ? 'link copied' : 'copy link'} +
+ ); +}; + const Reply = ({comment, depth = 0}: {comment: Comment, depth: number}) => { - const { author, deleted, removed } = comment || {}; + const { author, cid, deleted, removed, postCid, subplebbitAddress } = comment || {}; const { displayName, shortAddress } = author || {}; const [isReplying, setIsReplying] = useState(false); const { state } = comment || {}; @@ -110,6 +134,21 @@ const Reply = ({comment, depth = 0}: {comment: Comment, depth: number}) => { const { hasImportedAccount } = useAccountImportStore(); + const [isShareMenuOpen, setIsShareMenuOpen] = useState(false); + + const { refs, floatingStyles, context } = useFloating({ + placement: 'bottom-start', + open: isShareMenuOpen, + onOpenChange: setIsShareMenuOpen, + middleware: [offset(2), flip({ fallbackAxisSideDirection: 'end' }), shift()], + whileElementsMounted: autoUpdate, + }); + const click = useClick(context); + const dismiss = useDismiss(context); + const role = useRole(context); + const { getFloatingProps } = useInteractions([click, dismiss, role]); + const headingId = useId(); + return (
0 ? styles.nestedReply : ''}`}>
@@ -138,22 +177,42 @@ const Reply = ({comment, depth = 0}: {comment: Comment, depth: number}) => { {removed || deleted ? '' : } {state === 'pending' &&
{loadingString}
} {!removed && !deleted && hasImportedAccount && ( -
+
+ +
+ )} + {isShareMenuOpen && ( + + + + )} + {isReplying && ( +
+
+ setIsReplying(false)} + isReplyingToReply={true} + postCid={comment.postCid} + subplebbitAddress={comment.subplebbitAddress} + />
)} - {isReplying && ( -
-
- setIsReplying(false)} - isReplyingToReply={true} - postCid={comment.postCid} - subplebbitAddress={comment.subplebbitAddress} - /> -
- )} {replies.map((reply) => ( diff --git a/yarn.lock b/yarn.lock index e9e51d4..0b0dd5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2009,10 +2009,10 @@ dependencies: "@floating-ui/dom" "^1.0.0" -"@floating-ui/react@^0.26.28": - version "0.26.28" - resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.28.tgz#93f44ebaeb02409312e9df9507e83aab4a8c0dc7" - integrity sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw== +"@floating-ui/react@^0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.27.2.tgz#901a04e93061c427d45b69a29c99f641a8b3a7bc" + integrity sha512-k/yP6a9K9QwhLfIu87iUZxCH6XN5z5j/VUHHq0dEnbZYY2Y9jz68E/LXFtK8dkiaYltS2WYohnyKC0VcwVneVg== dependencies: "@floating-ui/react-dom" "^2.1.2" "@floating-ui/utils" "^0.2.8"