diff --git a/src/components/board-header/board-header.module.css b/src/components/board-header/board-header.module.css index 466bede7..1b76f807 100644 --- a/src/components/board-header/board-header.module.css +++ b/src/components/board-header/board-header.module.css @@ -20,7 +20,6 @@ } .boardSubtitle { - margin-top: 3px; font-size: var(--board-address-font-size); color: var(--board-address-text-color); } diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index 66173dff..9a2e3ff1 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -8,6 +8,7 @@ import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '. import { getFormattedDate, getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { isValidURL } from '../../lib/utils/url-utils'; import { isAllView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; +import useAuthorAddressClick from '../../hooks/use-author-address-click'; import useEditCommentPrivileges from '../../hooks/use-author-privileges'; import useCountLinksInReplies from '../../hooks/use-count-links-in-replies'; import useHide from '../../hooks/use-hide'; @@ -47,6 +48,9 @@ const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => { const { isCommentAuthorMod, isAccountMod, isAccountCommentAuthor } = useEditCommentPrivileges({ commentAuthorAddress: address, subplebbitAddress }); + const handleUserAddressClick = useAuthorAddressClick(); + const numberOfPostsByAuthor = document.querySelectorAll(`.${shortAddress}`).length; + return (
{!isHidden && } @@ -75,7 +79,24 @@ const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => { )} {authorRole && ` ## Board ${authorRole}`}{' '} - {!(isDescription || isRules) && (u/{shortAddress || accountShortAddress}) } + {!(isDescription || isRules) && ( + <> + (u/ + handleUserAddressClick(shortAddress || accountShortAddress)} + > + {shortAddress || accountShortAddress} + + } + content={`${numberOfPostsByAuthor} ${numberOfPostsByAuthor === 1 ? 'post' : 'posts'} by this user address`} + /> + ){' '} + + )} {getFormattedDate(timestamp)}} content={getFormattedTimeAgo(timestamp)} /> @@ -272,7 +293,15 @@ const Reply = ({ openReplyModal, reply, roles }: PostProps) => { return (
{'>>'}
-
+
{link && !hidden && isValidURL(link) && } {content && !hidden && } diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index 5fa9f885..98e5d8fe 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -7,6 +7,7 @@ import styles from '../../views/post/post.module.css'; import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils'; import { getFormattedDate, getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { isAllView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; +import useAuthorAddressClick from '../../hooks/use-author-address-click'; import useCountLinksInReplies from '../../hooks/use-count-links-in-replies'; import useHide from '../../hooks/use-hide'; import useReplies from '../../hooks/use-replies'; @@ -45,6 +46,9 @@ const PostInfoAndMedia = ({ openReplyModal, post, roles }: PostProps) => { const stateString = useStateString(post); + const handleUserAddressClick = useAuthorAddressClick(); + const numberOfPostsByAuthor = document.querySelectorAll(`.${shortAddress}`).length; + return ( <>
@@ -65,7 +69,24 @@ const PostInfoAndMedia = ({ openReplyModal, post, roles }: PostProps) => { )} {authorRole && ` ## Board ${authorRole}`}{' '} - {!(isDescription || isRules) && (u/{shortAddress || accountShortAddress})} + {!(isDescription || isRules) && ( + <> + (u/ + handleUserAddressClick(shortAddress || accountShortAddress)} + > + {shortAddress || accountShortAddress} + + } + content={`${numberOfPostsByAuthor} ${numberOfPostsByAuthor === 1 ? 'post' : 'posts'} by this user address`} + /> + ){' '} + + )} {pinned && ( @@ -224,7 +245,15 @@ const Reply = ({ openReplyModal, reply, roles }: PostProps) => { return (
-
+
{content && !hidden && } diff --git a/src/components/reply-quote-preview/reply-quote-preview.tsx b/src/components/reply-quote-preview/reply-quote-preview.tsx index 488531e5..7edf16ee 100644 --- a/src/components/reply-quote-preview/reply-quote-preview.tsx +++ b/src/components/reply-quote-preview/reply-quote-preview.tsx @@ -15,9 +15,9 @@ interface ReplyQuotePreviewProps { } const handleQuoteHover = (cid: string, onElementOutOfView: () => void) => { - const targetElement = document.getElementById(cid); + const targetElements = document.querySelectorAll(`.${cid}`); - if (!targetElement) return; + if (targetElements.length === 0) return; const isInViewport = (element: HTMLElement) => { const bounding = element.getBoundingClientRect(); @@ -29,10 +29,19 @@ const handleQuoteHover = (cid: string, onElementOutOfView: () => void) => { ); }; - if (isInViewport(targetElement)) { - targetElement.classList.add('highlight'); - } else { - targetElement.classList.remove('highlight'); + let anyInView = false; + + targetElements.forEach((element) => { + const htmlElement = element as HTMLElement; + if (isInViewport(htmlElement)) { + htmlElement.classList.add('highlight'); + anyInView = true; + } else { + htmlElement.classList.remove('highlight'); + } + }); + + if (!anyInView) { onElementOutOfView(); } }; @@ -88,10 +97,10 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i const handleMouseLeave = (cid: string | null) => { if (cid) { - const targetElement = document.getElementById(cid); - if (targetElement) { - targetElement.classList.remove('highlight'); - } + const targetElements = document.querySelectorAll(`.${cid}`); + targetElements.forEach((element) => { + element.classList.remove('highlight'); + }); } setHoveredCid(null); setOutOfViewCid(null); @@ -174,10 +183,10 @@ const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, is const handleMouseLeave = (cid: string | null) => { if (cid) { - const targetElement = document.getElementById(cid); - if (targetElement) { - targetElement.classList.remove('highlight'); - } + const targetElements = document.querySelectorAll(`.${cid}`); + targetElements.forEach((element) => { + element.classList.remove('highlight'); + }); } setHoveredCid(null); setOutOfViewCid(null); diff --git a/src/components/tooltip/tooltip.tsx b/src/components/tooltip/tooltip.tsx index 12572c9a..346ce278 100644 --- a/src/components/tooltip/tooltip.tsx +++ b/src/components/tooltip/tooltip.tsx @@ -24,7 +24,7 @@ const Tooltip = ({ content, children }: TooltipProps) => { ], }); - const hover = useHover(context, { move: false, delay: { open: 250, close: 0 } }); + const hover = useHover(context, { move: false, delay: { open: 500, close: 0 } }); const focus = useFocus(context); const dismiss = useDismiss(context); const role = useRole(context, { role: 'tooltip' }); diff --git a/src/hooks/use-author-address-click.ts b/src/hooks/use-author-address-click.ts new file mode 100644 index 00000000..c8d50949 --- /dev/null +++ b/src/hooks/use-author-address-click.ts @@ -0,0 +1,29 @@ +const useAuthorAddressClick = () => { + const handleUserAddressClick = (shortAddress: string | undefined) => { + if (!shortAddress) return; + + // Select the elements corresponding to the clicked short address + const elements = document.querySelectorAll(`.${shortAddress}`); + + // Check if the clicked address is already highlighted + const isAlreadyHighlighted = Array.from(elements).some((element) => element.classList.contains('highlight')); + + // Remove highlight from all elements with the .highlight class + const prevElements = document.querySelectorAll('.highlight'); + prevElements.forEach((element) => { + element.classList.remove('highlight'); + }); + + // If the clicked address was already highlighted, don't add the highlight back + if (isAlreadyHighlighted) return; + + // Highlight the new elements + elements.forEach((element) => { + element.classList.add('highlight'); + }); + }; + + return handleUserAddressClick; +}; + +export default useAuthorAddressClick; diff --git a/src/views/home/home.tsx b/src/views/home/home.tsx index f314d16d..fc99129b 100644 --- a/src/views/home/home.tsx +++ b/src/views/home/home.tsx @@ -143,10 +143,23 @@ const Footer = () => { {t('about')} + {downloadAppLink && ( +
  • + + {t('download_app')} + +
  • + )}
  • - - Twitter - + { + e.preventDefault(); + alert('work in progress'); + }} + > + FAQ +
  • @@ -163,13 +176,6 @@ const Footer = () => { GitHub
  • - {downloadAppLink && ( -
  • - - {t('download_app')} - -
  • - )}
  • {t('token')} diff --git a/src/views/post/post.module.css b/src/views/post/post.module.css index b4a4f564..184954ab 100644 --- a/src/views/post/post.module.css +++ b/src/views/post/post.module.css @@ -66,6 +66,14 @@ width: 100%; } +.userAddress { + cursor: pointer; +} + +.postDesktop .userAddress:hover { + color: var(--button-desktop-text-color-hover); +} + .postDesktop .subject { color: var(--post-subject-text-color); font-weight: var(--post-subject-font-weight);