mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(reply-quote-preview): keep floating OP previews at desktop width
This commit is contained in:
@@ -4,6 +4,7 @@ import { createRoot, type Root } from 'react-dom/client';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import ExternalNumberQuoteLink from '../external-number-quote-link';
|
||||
import postStyles from '../../../views/post/post.module.css';
|
||||
|
||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise<void> }).act as (cb: () => void | Promise<void>) => void | Promise<void>;
|
||||
@@ -146,4 +147,41 @@ describe('ExternalNumberQuoteLink', () => {
|
||||
|
||||
expect(document.body.querySelector('[data-testid="post-preview"]')?.textContent).toBe('cid-77');
|
||||
});
|
||||
|
||||
it('uses the OP preview width class for resolved external OP previews', async () => {
|
||||
testState.resolveExternalQuoteTargetMock.mockResolvedValue({
|
||||
boardPath: 'fit',
|
||||
cid: 'cid-77',
|
||||
comment: { cid: 'cid-77' },
|
||||
isUnavailable: false,
|
||||
route: '/fit/thread/cid-77',
|
||||
communityAddress: 'fit',
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
root.render(
|
||||
createElement(
|
||||
MemoryRouter,
|
||||
{},
|
||||
createElement(ExternalNumberQuoteLink, {
|
||||
reference: {
|
||||
boardIdentifier: 'fit',
|
||||
kind: 'cross-board',
|
||||
number: 77,
|
||||
raw: '>>>/fit/77',
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
container.querySelector('a')?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
||||
await Promise.resolve();
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
});
|
||||
|
||||
const preview = document.body.querySelector(`.${postStyles.replyQuotePreview}`);
|
||||
expect(preview?.classList.contains(postStyles.replyQuotePreviewOp)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -260,6 +260,10 @@ const ExternalNumberQuoteLink = ({ reference }: ExternalNumberQuoteLinkProps) =>
|
||||
) : (
|
||||
<div className={`${styles.externalQuotePreviewState} ${styles.externalQuotePreviewError}`}>{previewState.message}</div>
|
||||
);
|
||||
const previewClassName =
|
||||
previewState.kind === 'resolved' && previewState.target.comment && !previewState.target.comment.parentCid
|
||||
? `${postStyles.replyQuotePreview} ${postStyles.replyQuotePreviewOp}`
|
||||
: postStyles.replyQuotePreview;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -280,7 +284,7 @@ const ExternalNumberQuoteLink = ({ reference }: ExternalNumberQuoteLinkProps) =>
|
||||
previewContent &&
|
||||
createPortal(
|
||||
<div
|
||||
className={postStyles.replyQuotePreview}
|
||||
className={previewClassName}
|
||||
data-thread-scroll-preview='true'
|
||||
ref={previewRef}
|
||||
style={{ left: previewPosition.left, position: 'fixed', top: previewPosition.top, zIndex: 1000 }}
|
||||
|
||||
@@ -401,6 +401,36 @@ describe('ReplyQuotePreview', () => {
|
||||
outOfView.remove();
|
||||
});
|
||||
|
||||
it('uses the OP preview width class for floating desktop OP quotelinks', async () => {
|
||||
const outOfView = appendReplyElement({ cid: 'thread-cid', inViewport: false, isThreadCard: true });
|
||||
|
||||
await renderPreview({
|
||||
isOP: true,
|
||||
isQuotelinkReply: true,
|
||||
quotelinkReply: {
|
||||
cid: 'thread-cid',
|
||||
number: 1,
|
||||
communityAddress: 'music-posting.eth',
|
||||
},
|
||||
});
|
||||
|
||||
const link = queryAnchorByText('>>1 (OP)');
|
||||
expect(link).toBeTruthy();
|
||||
|
||||
await act(async () => {
|
||||
link?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
||||
});
|
||||
|
||||
const preview = document.querySelector(`.${styles.replyQuotePreview}`);
|
||||
expect(preview?.classList.contains(styles.replyQuotePreviewOp)).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
link?.dispatchEvent(new MouseEvent('mouseout', { bubbles: true }));
|
||||
});
|
||||
|
||||
outOfView.remove();
|
||||
});
|
||||
|
||||
it('marks quotelinks as your own via the direct account comment lookup before author fallback', async () => {
|
||||
testState.account = {
|
||||
id: 'account-1',
|
||||
|
||||
@@ -24,6 +24,9 @@ interface ReplyQuotePreviewProps {
|
||||
showTrailingBreak?: boolean;
|
||||
}
|
||||
|
||||
const getQuotePreviewClassName = (previewPost?: Comment) =>
|
||||
!previewPost?.parentCid ? `${styles.replyQuotePreview} ${styles.replyQuotePreviewOp}` : styles.replyQuotePreview;
|
||||
|
||||
const handleQuoteHover = (cid: string, onElementOutOfView: () => void) => {
|
||||
const targetElements = document.querySelectorAll(`[data-cid="${cid}"]`);
|
||||
const isOpElement = (element: HTMLElement) => element.getAttribute('data-post-cid') === cid;
|
||||
@@ -209,7 +212,7 @@ const DesktopQuotePreview = ({
|
||||
{hoveredCid === normalizedBacklinkReply?.cid &&
|
||||
outOfViewCid === normalizedBacklinkReply?.cid &&
|
||||
createPortal(
|
||||
<div className={styles.replyQuotePreview} data-thread-scroll-preview='true' ref={refs.setFloating} style={floatingStyles}>
|
||||
<div className={getQuotePreviewClassName(normalizedBacklinkReply)} data-thread-scroll-preview='true' ref={refs.setFloating} style={floatingStyles}>
|
||||
<Post post={normalizedBacklinkReply} showReplies={false} />
|
||||
</div>,
|
||||
document.body,
|
||||
@@ -265,7 +268,7 @@ const DesktopQuotePreview = ({
|
||||
{showTrailingBreak && <br />}
|
||||
{shouldShowQuotelinkPreview &&
|
||||
createPortal(
|
||||
<div className={styles.replyQuotePreview} data-thread-scroll-preview='true' ref={refs.setFloating} style={floatingStyles}>
|
||||
<div className={getQuotePreviewClassName(normalizedQuotelinkReply)} data-thread-scroll-preview='true' ref={refs.setFloating} style={floatingStyles}>
|
||||
<Post post={normalizedQuotelinkReply} showReplies={false} />
|
||||
</div>,
|
||||
document.body,
|
||||
@@ -373,7 +376,7 @@ const MobileQuotePreview = ({
|
||||
{hoveredCid === normalizedBacklinkReply?.cid &&
|
||||
outOfViewCid === normalizedBacklinkReply?.cid &&
|
||||
createPortal(
|
||||
<div className={styles.replyQuotePreview} data-thread-scroll-preview='true' ref={refs.setFloating} style={floatingStyles}>
|
||||
<div className={getQuotePreviewClassName(normalizedBacklinkReply)} data-thread-scroll-preview='true' ref={refs.setFloating} style={floatingStyles}>
|
||||
<Post post={normalizedBacklinkReply} showReplies={false} />
|
||||
</div>,
|
||||
document.body,
|
||||
@@ -427,7 +430,7 @@ const MobileQuotePreview = ({
|
||||
{showTrailingBreak && <br />}
|
||||
{shouldShowQuotelinkPreview &&
|
||||
createPortal(
|
||||
<div className={styles.replyQuotePreview} data-thread-scroll-preview='true' ref={refs.setFloating} style={floatingStyles}>
|
||||
<div className={getQuotePreviewClassName(normalizedQuotelinkReply)} data-thread-scroll-preview='true' ref={refs.setFloating} style={floatingStyles}>
|
||||
<Post post={normalizedQuotelinkReply} showReplies={false} />
|
||||
</div>,
|
||||
document.body,
|
||||
|
||||
@@ -672,6 +672,8 @@
|
||||
border: var(--quote-preview-border);
|
||||
border-right: var(--quote-preview-border-right);
|
||||
border-bottom: var(--quote-preview-border-bottom);
|
||||
box-sizing: border-box;
|
||||
max-width: calc(100vw - 20px);
|
||||
}
|
||||
|
||||
.postDesktop .replyQuotePreviewSpacer {
|
||||
@@ -724,6 +726,10 @@
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.replyQuotePreviewOp {
|
||||
width: min(520px, calc(100vw - 20px));
|
||||
}
|
||||
|
||||
.postMobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user