mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(feed): measure expanded reply media height
This commit is contained in:
@@ -128,6 +128,29 @@ describe('CommentMedia', () => {
|
||||
expect(container.textContent).toContain('640x480');
|
||||
});
|
||||
|
||||
it('marks expanded reply images so virtualized feed rows use live height', async () => {
|
||||
await renderMedia({
|
||||
commentMediaInfo: {
|
||||
linkHeight: 300,
|
||||
linkWidth: 600,
|
||||
type: 'image',
|
||||
url: 'https://cdn.example.com/reply-image.jpg',
|
||||
},
|
||||
parentCid: 'parent-cid',
|
||||
setShowThumbnail: setShowThumbnailMock,
|
||||
showThumbnail: true,
|
||||
});
|
||||
|
||||
expect(container.querySelector('[data-expanded-media="true"]')).toBeNull();
|
||||
|
||||
const image = container.querySelector('img[src="https://cdn.example.com/reply-image.jpg"]');
|
||||
await act(async () => {
|
||||
image?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(container.querySelector('[data-expanded-media="true"]')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('falls back to the deleted-file placeholder when an image fails to load', async () => {
|
||||
await renderMedia({
|
||||
commentMediaInfo: {
|
||||
|
||||
@@ -210,7 +210,7 @@ const Media = ({ commentMediaInfo, disableToggle, isReply, setShowThumbnail }: M
|
||||
const mediaDimensions = getMediaDimensions(commentMediaInfo);
|
||||
|
||||
return (
|
||||
<span className={mediaClass}>
|
||||
<span className={mediaClass} data-expanded-media='true'>
|
||||
{type === 'iframe' && url ? (
|
||||
<Embed url={url} />
|
||||
) : type === 'gif' ? (
|
||||
@@ -307,6 +307,8 @@ const Image = ({ commentMediaInfo, disableToggle = false, displayHeight, display
|
||||
}`;
|
||||
const thumbnailSmallPadding = isMobile ? styles.thumbnailMobile : styles.thumbnailReplyDesktop;
|
||||
const thumbnailDimensions = { '--width': displayWidth, '--height': displayHeight } as React.CSSProperties;
|
||||
const expandedMediaAttribute = isImageExpanded ? 'true' : undefined;
|
||||
const imageMediaStyle = isImageExpanded ? undefined : thumbnailDimensions;
|
||||
|
||||
const [hasError, setHasError] = useState(false);
|
||||
const handleError = () => setHasError(true);
|
||||
@@ -340,7 +342,8 @@ const Image = ({ commentMediaInfo, disableToggle = false, displayHeight, display
|
||||
<span className={`${styles.thumbnail} ${isImageExpanded && isMobile ? styles.removeFloat : ''}`}>
|
||||
<span
|
||||
className={isImageExpanded ? mediaClass : `${isOutOfFeed ? styles.communityAvatar : styles.thumbnailSmall} ${thumbnailSmallPadding}`}
|
||||
style={isImageExpanded ? {} : thumbnailDimensions}
|
||||
data-expanded-media={expandedMediaAttribute}
|
||||
style={imageMediaStyle}
|
||||
>
|
||||
{hasError ? (
|
||||
<img src='assets/filedeleted-res.gif' alt='File deleted' />
|
||||
@@ -379,7 +382,8 @@ const Image = ({ commentMediaInfo, disableToggle = false, displayHeight, display
|
||||
) : (
|
||||
<span
|
||||
className={isImageExpanded ? mediaClass : `${isOutOfFeed ? styles.communityAvatar : styles.thumbnailBig} ${styles.thumbnail}`}
|
||||
style={isImageExpanded ? {} : thumbnailDimensions}
|
||||
data-expanded-media={expandedMediaAttribute}
|
||||
style={imageMediaStyle}
|
||||
>
|
||||
{hasError ? (
|
||||
<img src='assets/filedeleted-res.gif' alt='File deleted' />
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
resolveFeedVirtualizationMode,
|
||||
resolveReplyVirtualizationMode,
|
||||
} from '../pretext-height-estimates';
|
||||
import { EXPANDED_MEDIA_DATA_ATTRIBUTE } from '../measurement-attributes';
|
||||
|
||||
describe('pretext-height-estimates', () => {
|
||||
beforeEach(() => {
|
||||
@@ -81,6 +82,18 @@ describe('pretext-height-estimates', () => {
|
||||
expect(getReplyItemSizeFromElement(element, 'offsetHeight')).toBe(222);
|
||||
});
|
||||
|
||||
it('uses live DOM height when expanded media is inside an estimated item', () => {
|
||||
const element = document.createElement('div');
|
||||
const child = document.createElement('div');
|
||||
|
||||
Object.defineProperty(element, 'offsetHeight', { configurable: true, value: 421 });
|
||||
element.dataset.pretextHeight = '123';
|
||||
child.setAttribute(EXPANDED_MEDIA_DATA_ATTRIBUTE, 'true');
|
||||
element.appendChild(child);
|
||||
|
||||
expect(getReplyItemSizeFromElement(element, 'offsetHeight')).toBe(421);
|
||||
});
|
||||
|
||||
it('adds desktop board-label height for multiboard text posts without media', () => {
|
||||
const metrics = {
|
||||
abbrFontSizePx: 13,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const EXPANDED_MEDIA_DATA_ATTRIBUTE = 'data-expanded-media';
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Comment } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { layout, layoutNextLine, prepare, prepareWithSegments } from '@chenglou/pretext';
|
||||
import { getCommentMediaInfo, getHasThumbnail } from './media-utils';
|
||||
import { EXPANDED_MEDIA_DATA_ATTRIBUTE } from './measurement-attributes';
|
||||
import { removeMarkdown } from './post-utils';
|
||||
import { getRenderableMobileBacklinks } from './reply-backlink-utils';
|
||||
|
||||
@@ -839,6 +840,10 @@ export const getPretextItemSizeFromElement = (element: HTMLElement, field: 'offs
|
||||
return element.offsetWidth;
|
||||
}
|
||||
|
||||
if (element.dataset.expandedMedia === 'true' || element.querySelector(`[${EXPANDED_MEDIA_DATA_ATTRIBUTE}="true"]`)) {
|
||||
return element.offsetHeight;
|
||||
}
|
||||
|
||||
const ownEstimatedHeight = Number.parseFloat(element.dataset.pretextHeight || '');
|
||||
if (Number.isFinite(ownEstimatedHeight) && ownEstimatedHeight > 0) {
|
||||
return ownEstimatedHeight;
|
||||
|
||||
Reference in New Issue
Block a user