Merge remote-tracking branch 'origin/main' into fix-classnames
This commit is contained in:
commit
ce0301adc7
|
@ -17,11 +17,11 @@ const AttachmentThumbs = (props: IAttachmentThumbs) => {
|
||||||
const { media, onClick, sensitive } = props;
|
const { media, onClick, sensitive } = props;
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const fallback = <div className='media-gallery--compact' />;
|
const fallback = <div className='!h-[50px] bg-transparent' />;
|
||||||
const onOpenMedia = (media: ImmutableList<Attachment>, index: number) => dispatch(openModal('MEDIA', { media, index }));
|
const onOpenMedia = (media: ImmutableList<Attachment>, index: number) => dispatch(openModal('MEDIA', { media, index }));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='attachment-thumbs'>
|
<div className='relative'>
|
||||||
<Suspense fallback={fallback}>
|
<Suspense fallback={fallback}>
|
||||||
<MediaGallery
|
<MediaGallery
|
||||||
media={media}
|
media={media}
|
||||||
|
@ -34,7 +34,11 @@ const AttachmentThumbs = (props: IAttachmentThumbs) => {
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
{onClick && (
|
{onClick && (
|
||||||
<div className='attachment-thumbs__clickable-region' onClick={onClick} />
|
<button
|
||||||
|
className='absolute inset-0 size-full cursor-pointer'
|
||||||
|
onClick={onClick}
|
||||||
|
style={{ background: 'none', border: 'none', padding: 0 }}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,6 @@ import clsx from 'clsx';
|
||||||
import React, { useState, useRef, useLayoutEffect } from 'react';
|
import React, { useState, useRef, useLayoutEffect } from 'react';
|
||||||
|
|
||||||
import Blurhash from 'soapbox/components/blurhash';
|
import Blurhash from 'soapbox/components/blurhash';
|
||||||
import Icon from 'soapbox/components/icon';
|
|
||||||
import StillImage from 'soapbox/components/still-image';
|
import StillImage from 'soapbox/components/still-image';
|
||||||
import { MIMETYPE_ICONS } from 'soapbox/components/upload';
|
import { MIMETYPE_ICONS } from 'soapbox/components/upload';
|
||||||
import { useSettings, useSoapboxConfig } from 'soapbox/hooks';
|
import { useSettings, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
@ -12,6 +11,8 @@ import { truncateFilename } from 'soapbox/utils/media';
|
||||||
import { isIOS } from '../is-mobile';
|
import { isIOS } from '../is-mobile';
|
||||||
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../utils/media-aspect-ratio';
|
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../utils/media-aspect-ratio';
|
||||||
|
|
||||||
|
import SvgIcon from './ui/icon/svg-icon';
|
||||||
|
|
||||||
import type { Property } from 'csstype';
|
import type { Property } from 'csstype';
|
||||||
import type { List as ImmutableList } from 'immutable';
|
import type { List as ImmutableList } from 'immutable';
|
||||||
|
|
||||||
|
@ -60,6 +61,7 @@ interface IItem {
|
||||||
dimensions: Dimensions;
|
dimensions: Dimensions;
|
||||||
last?: boolean;
|
last?: boolean;
|
||||||
total: number;
|
total: number;
|
||||||
|
compact?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Item: React.FC<IItem> = ({
|
const Item: React.FC<IItem> = ({
|
||||||
|
@ -71,6 +73,7 @@ const Item: React.FC<IItem> = ({
|
||||||
dimensions,
|
dimensions,
|
||||||
last,
|
last,
|
||||||
total,
|
total,
|
||||||
|
compact,
|
||||||
}) => {
|
}) => {
|
||||||
const { autoPlayGif } = useSettings();
|
const { autoPlayGif } = useSettings();
|
||||||
const { mediaPreview } = useSoapboxConfig();
|
const { mediaPreview } = useSoapboxConfig();
|
||||||
|
@ -111,16 +114,21 @@ const Item: React.FC<IItem> = ({
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleVideoHover: React.MouseEventHandler<HTMLVideoElement> = ({ currentTarget: video }) => {
|
const handleVideoHover = (event: React.SyntheticEvent<HTMLVideoElement>) => {
|
||||||
|
const video = event.currentTarget;
|
||||||
video.playbackRate = 3.0;
|
video.playbackRate = 3.0;
|
||||||
video.play();
|
video.play();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleVideoLeave: React.MouseEventHandler<HTMLVideoElement> = ({ currentTarget: video }) => {
|
const handleVideoLeave = (event: React.SyntheticEvent<HTMLVideoElement>) => {
|
||||||
|
const video = event.currentTarget;
|
||||||
video.pause();
|
video.pause();
|
||||||
video.currentTime = 0;
|
video.currentTime = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleFocus: React.FocusEventHandler<HTMLVideoElement> = handleVideoHover;
|
||||||
|
const handleBlur: React.FocusEventHandler<HTMLVideoElement> = handleVideoLeave;
|
||||||
|
|
||||||
let width: Dimensions['w'] = 100;
|
let width: Dimensions['w'] = 100;
|
||||||
let height: Dimensions['h'] = '100%';
|
let height: Dimensions['h'] = '100%';
|
||||||
let top: Dimensions['t'] = 'auto';
|
let top: Dimensions['t'] = 'auto';
|
||||||
|
@ -144,43 +152,29 @@ const Item: React.FC<IItem> = ({
|
||||||
let thumbnail: React.ReactNode = '';
|
let thumbnail: React.ReactNode = '';
|
||||||
const ext = attachment.url.split('.').pop()?.toLowerCase();
|
const ext = attachment.url.split('.').pop()?.toLowerCase();
|
||||||
|
|
||||||
/*if (attachment.type === 'unknown' && ['gb', 'gbc'].includes(ext!)) {
|
if (attachment.type === 'unknown') {
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={clsx('media-gallery__item', {
|
|
||||||
standalone,
|
|
||||||
'rounded-md': total > 1,
|
|
||||||
})}
|
|
||||||
key={attachment.id}
|
|
||||||
style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}
|
|
||||||
>
|
|
||||||
<Suspense fallback={<div className='media-gallery__item-thumbnail' />}>
|
|
||||||
<Gameboy className='media-gallery__item-thumbnail cursor-default' src={attachment.url} />
|
|
||||||
</Suspense>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else */if (attachment.type === 'unknown') {
|
|
||||||
const filename = truncateFilename(attachment.url, MAX_FILENAME_LENGTH);
|
const filename = truncateFilename(attachment.url, MAX_FILENAME_LENGTH);
|
||||||
const attachmentIcon = (
|
const attachmentIcon = (
|
||||||
<Icon
|
<SvgIcon
|
||||||
className='size-16 text-gray-800 dark:text-gray-200'
|
className={clsx('size-16 text-gray-800 dark:text-gray-200', { 'size-8': compact })}
|
||||||
src={MIMETYPE_ICONS[attachment.getIn(['pleroma', 'mime_type']) as string] || require('@tabler/icons/outline/paperclip.svg')}
|
src={MIMETYPE_ICONS[attachment.getIn(['pleroma', 'mime_type']) as string] || require('@tabler/icons/outline/paperclip.svg')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx('media-gallery__item', {
|
className={clsx('relative float-left box-border block overflow-hidden rounded-sm border-0', {
|
||||||
standalone,
|
standalone,
|
||||||
'rounded-md': total > 1,
|
'rounded-md': total > 1,
|
||||||
|
'!size-[50px] !inset-auto !float-left !mr-[50px]': compact,
|
||||||
})}
|
})}
|
||||||
key={attachment.id}
|
key={attachment.id}
|
||||||
style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}
|
style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}
|
||||||
>
|
>
|
||||||
<a className='media-gallery__item-thumbnail' href={attachment.url} target='_blank' style={{ cursor: 'pointer' }}>
|
<a className='relative z-[1] block size-full cursor-zoom-in leading-none text-gray-400 no-underline' href={attachment.url} target='_blank' style={{ cursor: 'pointer' }}>
|
||||||
<Blurhash hash={attachment.blurhash} className='media-gallery__preview' />
|
<Blurhash hash={attachment.blurhash} className='absolute left-0 top-0 z-0 size-full rounded-lg bg-gray-200 object-cover dark:bg-gray-900' />
|
||||||
<span className='media-gallery__item__icons'>{attachmentIcon}</span>
|
<span className='absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'>{attachmentIcon}</span>
|
||||||
<span className='media-gallery__filename__label'>{filename}</span>
|
<span className='pointer-events-none absolute bottom-1.5 left-1.5 z-[1] block bg-black/50 px-1.5 py-0.5 text-[11px] font-semibold leading-[18px] text-white opacity-90 transition-opacity duration-100 ease-linear'>{filename}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -189,7 +183,7 @@ const Item: React.FC<IItem> = ({
|
||||||
|
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<a
|
<a
|
||||||
className='media-gallery__item-thumbnail'
|
className='relative z-[1] block size-full cursor-zoom-in leading-none text-gray-400 no-underline'
|
||||||
href={attachment.url}
|
href={attachment.url}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
|
@ -213,9 +207,9 @@ const Item: React.FC<IItem> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<div className={clsx('media-gallery__gifv', { autoplay: autoPlayGif })}>
|
<div className='group relative size-full overflow-hidden'>
|
||||||
<video
|
<video
|
||||||
className='media-gallery__item-gifv-thumbnail'
|
className='relative top-0 z-10 size-full transform-none cursor-zoom-in rounded-md object-cover'
|
||||||
aria-label={attachment.description}
|
aria-label={attachment.description}
|
||||||
title={attachment.description}
|
title={attachment.description}
|
||||||
role='application'
|
role='application'
|
||||||
|
@ -228,61 +222,65 @@ const Item: React.FC<IItem> = ({
|
||||||
{...conditionalAttributes}
|
{...conditionalAttributes}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span className='media-gallery__gifv__label'>GIF</span> {/* eslint-disable-line formatjs/no-literal-string-in-jsx */}
|
<span className={clsx('pointer-events-none absolute bottom-1.5 left-1.5 z-[1] block bg-black/50 px-1.5 py-0.5 text-[11px] font-semibold leading-[18px] text-white opacity-90 transition-opacity duration-100 ease-linear group-hover:opacity-100', { 'hidden': autoPlayGif })}>GIF</span> {/* eslint-disable-line formatjs/no-literal-string-in-jsx */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (attachment.type === 'audio') {
|
} else if (attachment.type === 'audio') {
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<a
|
<a
|
||||||
className={clsx('media-gallery__item-thumbnail')}
|
className={clsx('relative z-[1] block size-full cursor-zoom-in leading-none text-gray-400 no-underline')}
|
||||||
href={attachment.url}
|
href={attachment.url}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
title={attachment.description}
|
title={attachment.description}
|
||||||
>
|
>
|
||||||
<span className='media-gallery__item__icons'><Icon src={require('@tabler/icons/outline/volume.svg')} /></span>
|
<span className='absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'><SvgIcon className='size-24' src={require('@tabler/icons/outline/volume.svg')} /></span>
|
||||||
<span className='media-gallery__file-extension__label uppercase'>{ext}</span>
|
<span className={clsx('pointer-events-none absolute bottom-1.5 left-1.5 z-[1] block bg-black/50 px-1.5 py-0.5 text-[11px] font-semibold uppercase leading-[18px] text-white opacity-90 transition-opacity duration-100 ease-linear', { 'hidden': compact })}>{ext}</span>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else if (attachment.type === 'video') {
|
} else if (attachment.type === 'video') {
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<a
|
<a
|
||||||
className={clsx('media-gallery__item-thumbnail')}
|
className={clsx('relative z-[1] block size-full cursor-zoom-in leading-none text-gray-400 no-underline')}
|
||||||
href={attachment.url}
|
href={attachment.url}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
title={attachment.description}
|
title={attachment.description}
|
||||||
>
|
>
|
||||||
<video
|
<video
|
||||||
|
className='size-full object-cover'
|
||||||
muted
|
muted
|
||||||
loop
|
loop
|
||||||
onMouseOver={handleVideoHover}
|
onMouseOver={handleVideoHover}
|
||||||
onMouseOut={handleVideoLeave}
|
onMouseOut={handleVideoLeave}
|
||||||
|
onFocus={handleFocus}
|
||||||
|
onBlur={handleBlur}
|
||||||
>
|
>
|
||||||
<source src={attachment.url} />
|
<source src={attachment.url} />
|
||||||
</video>
|
</video>
|
||||||
<span className='media-gallery__file-extension__label uppercase'>{ext}</span>
|
<span className={clsx('pointer-events-none absolute bottom-1.5 left-1.5 z-[1] block bg-black/50 px-1.5 py-0.5 text-[11px] font-semibold uppercase leading-[18px] text-white opacity-90 transition-opacity duration-100 ease-linear', { 'hidden': compact })}>{ext}</span>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx('media-gallery__item', `media-gallery__item--${attachment.type}`, {
|
className={clsx('relative float-left box-border block overflow-hidden rounded-sm border-0', {
|
||||||
standalone,
|
standalone,
|
||||||
'rounded-md': total > 1,
|
'rounded-md': total > 1,
|
||||||
|
'!size-[50px] !inset-auto !float-left !mr-[50px]': compact,
|
||||||
})}
|
})}
|
||||||
key={attachment.id}
|
key={attachment.id}
|
||||||
style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}
|
style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}
|
||||||
>
|
>
|
||||||
{last && total > ATTACHMENT_LIMIT && (
|
{last && total > ATTACHMENT_LIMIT && (
|
||||||
<div className='media-gallery__item-overflow'> {/* eslint-disable-line formatjs/no-literal-string-in-jsx */}
|
<div className={clsx('pointer-events-none absolute inset-0 z-[2] flex size-full items-center justify-center bg-white/75 text-center text-[50px] font-bold text-gray-800', { '!text-5': compact })}> {/* eslint-disable-line formatjs/no-literal-string-in-jsx */}
|
||||||
+{total - ATTACHMENT_LIMIT + 1}
|
+{total - ATTACHMENT_LIMIT + 1}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Blurhash
|
<Blurhash
|
||||||
hash={attachment.blurhash}
|
hash={attachment.blurhash}
|
||||||
className='media-gallery__preview'
|
className='absolute left-0 top-0 z-0 size-full rounded-lg bg-gray-200 object-cover dark:bg-gray-900'
|
||||||
/>
|
/>
|
||||||
{visible && thumbnail}
|
{visible && thumbnail}
|
||||||
</div>
|
</div>
|
||||||
|
@ -561,6 +559,7 @@ const MediaGallery: React.FC<IMediaGallery> = (props) => {
|
||||||
dimensions={sizeData.itemsDimensions[i]}
|
dimensions={sizeData.itemsDimensions[i]}
|
||||||
last={i === ATTACHMENT_LIMIT - 1}
|
last={i === ATTACHMENT_LIMIT - 1}
|
||||||
total={media.size}
|
total={media.size}
|
||||||
|
compact={compact}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -578,7 +577,7 @@ const MediaGallery: React.FC<IMediaGallery> = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(className, 'media-gallery', { 'media-gallery--compact': compact })}
|
className={clsx(className, 'relative isolate box-border h-auto w-full overflow-hidden rounded-lg', { '!h-[50px] bg-transparent': compact })}
|
||||||
style={sizeData.style}
|
style={sizeData.style}
|
||||||
ref={node}
|
ref={node}
|
||||||
>
|
>
|
||||||
|
|
|
@ -166,7 +166,7 @@ const Upload: React.FC<IUpload> = ({
|
||||||
onDragEnter={onDragEnter}
|
onDragEnter={onDragEnter}
|
||||||
onDragEnd={onDragEnd}
|
onDragEnd={onDragEnd}
|
||||||
>
|
>
|
||||||
<Blurhash hash={media.blurhash} className='media-gallery__preview' />
|
<Blurhash hash={media.blurhash} className='absolute left-0 top-0 z-0 size-full rounded-lg bg-gray-200 object-cover dark:bg-gray-900' />
|
||||||
<Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12 }) }}>
|
<Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12 }) }}>
|
||||||
{({ scale }) => (
|
{({ scale }) => (
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -2,8 +2,8 @@ import clsx from 'clsx';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import Blurhash from 'soapbox/components/blurhash';
|
import Blurhash from 'soapbox/components/blurhash';
|
||||||
import Icon from 'soapbox/components/icon';
|
|
||||||
import StillImage from 'soapbox/components/still-image';
|
import StillImage from 'soapbox/components/still-image';
|
||||||
|
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
||||||
import { useSettings } from 'soapbox/hooks';
|
import { useSettings } from 'soapbox/hooks';
|
||||||
import { isIOS } from 'soapbox/is-mobile';
|
import { isIOS } from 'soapbox/is-mobile';
|
||||||
|
|
||||||
|
@ -80,9 +80,9 @@ const MediaItem: React.FC<IMediaItem> = ({ attachment, onOpenMedia }) => {
|
||||||
conditionalAttributes.autoPlay = true;
|
conditionalAttributes.autoPlay = true;
|
||||||
}
|
}
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<div className={clsx('media-gallery__gifv', { autoplay: autoPlayGif })}>
|
<div className='group relative size-full overflow-hidden'>
|
||||||
<video
|
<video
|
||||||
className='media-gallery__item-gifv-thumbnail'
|
className='relative top-0 z-10 size-full transform-none cursor-zoom-in rounded-md object-cover'
|
||||||
aria-label={attachment.description}
|
aria-label={attachment.description}
|
||||||
title={attachment.description}
|
title={attachment.description}
|
||||||
role='application'
|
role='application'
|
||||||
|
@ -94,7 +94,7 @@ const MediaItem: React.FC<IMediaItem> = ({ attachment, onOpenMedia }) => {
|
||||||
{...conditionalAttributes}
|
{...conditionalAttributes}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span className='media-gallery__gifv__label'>GIF</span> {/* eslint-disable-line formatjs/no-literal-string-in-jsx */}
|
<span className={clsx('pointer-events-none absolute bottom-1.5 left-1.5 z-[1] block bg-black/50 px-1.5 py-0.5 text-[11px] font-semibold leading-[18px] text-white opacity-90 transition-opacity duration-100 ease-linear group-hover:opacity-100', { 'hidden': autoPlayGif })}>GIF</span> {/* eslint-disable-line formatjs/no-literal-string-in-jsx */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (attachment.type === 'audio') {
|
} else if (attachment.type === 'audio') {
|
||||||
|
@ -102,28 +102,28 @@ const MediaItem: React.FC<IMediaItem> = ({ attachment, onOpenMedia }) => {
|
||||||
const fileExtensionLastIndex = remoteURL.lastIndexOf('.');
|
const fileExtensionLastIndex = remoteURL.lastIndexOf('.');
|
||||||
const fileExtension = remoteURL.slice(fileExtensionLastIndex + 1).toUpperCase();
|
const fileExtension = remoteURL.slice(fileExtensionLastIndex + 1).toUpperCase();
|
||||||
thumbnail = (
|
thumbnail = (
|
||||||
<div className='media-gallery__item-thumbnail'>
|
<div className='relative z-[1] block size-full cursor-zoom-in leading-none text-gray-400 no-underline'>
|
||||||
<span className='media-gallery__item__icons'><Icon src={require('@tabler/icons/outline/volume.svg')} /></span>
|
<span className='absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'><SvgIcon className='size-24' src={require('@tabler/icons/outline/volume.svg')} /></span>
|
||||||
<span className='media-gallery__file-extension__label'>{fileExtension}</span>
|
<span className='pointer-events-none absolute bottom-1.5 left-1.5 z-[1] block bg-black/50 px-1.5 py-0.5 text-[11px] font-semibold leading-[18px] text-white opacity-90 transition-opacity duration-100 ease-linear'>{fileExtension}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
icon = (
|
icon = (
|
||||||
<span className='media-gallery__item__icons'>
|
<span className='absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'>
|
||||||
<Icon src={require('@tabler/icons/outline/eye-off.svg')} />
|
<SvgIcon className='size-24' src={require('@tabler/icons/outline/eye-off.svg')} />
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='col-span-1'>
|
<div className='col-span-1'>
|
||||||
<a className='media-gallery__item-thumbnail aspect-1' href={status.url} target='_blank' onClick={handleClick} title={title}>
|
<a className='relative z-[1] block aspect-1 size-full cursor-zoom-in leading-none text-gray-400 no-underline' href={status.url} target='_blank' onClick={handleClick} title={title}>
|
||||||
<Blurhash
|
<Blurhash
|
||||||
hash={attachment.blurhash}
|
hash={attachment.blurhash}
|
||||||
className={clsx('media-gallery__preview', {
|
className={clsx('absolute left-0 top-0 z-0 size-full rounded-lg bg-gray-200 object-cover dark:bg-gray-900', {
|
||||||
'media-gallery__preview--hidden': visible,
|
'hidden': visible,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
{visible && thumbnail}
|
{visible && thumbnail}
|
||||||
|
|
|
@ -78,13 +78,13 @@ const PlaceholderMediaGallery: React.FC<IPlaceholderMediaGallery> = ({ media, de
|
||||||
const float = dimensions.float as any || 'left';
|
const float = dimensions.float as any || 'left';
|
||||||
const position = dimensions.pos as any || 'relative';
|
const position = dimensions.pos as any || 'relative';
|
||||||
|
|
||||||
return <div key={i} className='media-gallery__item animate-pulse bg-primary-200' style={{ position, float, left, top, right, bottom, height, width }} />;
|
return <div key={i} className='relative float-left box-border block animate-pulse overflow-hidden rounded-sm border-0 bg-primary-200' style={{ position, float, left, top, right, bottom, height, width }} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const sizeData = getSizeData(media.size);
|
const sizeData = getSizeData(media.size);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='media-gallery media-gallery--placeholder' style={sizeData.get('style')} ref={handleRef}>
|
<div className='relative isolate box-border h-auto w-full overflow-hidden rounded-lg' style={sizeData.get('style')} ref={handleRef}>
|
||||||
{media.take(4).map((_, i) => renderItem(sizeData.get('itemsDimensions')[i], i))}
|
{media.take(4).map((_, i) => renderItem(sizeData.get('itemsDimensions')[i], i))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue