terry-staging #11
@@ -136,6 +136,7 @@ function PopularRankRow({
|
|||||||
src={cover}
|
src={cover}
|
||||||
alt=""
|
alt=""
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
className="h-full w-full object-cover"
|
className="h-full w-full object-cover"
|
||||||
onError={() => setCoverFailed(true)}
|
onError={() => setCoverFailed(true)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ export function RecommendedCard({
|
|||||||
alt=""
|
alt=""
|
||||||
className="ark-img-fade h-full w-full object-cover transition duration-300 group-hover:scale-[1.02]"
|
className="ark-img-fade h-full w-full object-cover transition duration-300 group-hover:scale-[1.02]"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
onLoad={(e) => e.currentTarget.classList.add("is-loaded")}
|
onLoad={(e) => e.currentTarget.classList.add("is-loaded")}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -223,6 +224,7 @@ export function ComingSoonRecommendedCard({
|
|||||||
alt=""
|
alt=""
|
||||||
className="h-full w-full object-cover opacity-75 grayscale-[15%]"
|
className="h-full w-full object-cover opacity-75 grayscale-[15%]"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
/>
|
/>
|
||||||
<span className="absolute left-3 top-3 rounded-md bg-ark-gold px-2.5 py-1 text-xs font-semibold text-black">
|
<span className="absolute left-3 top-3 rounded-md bg-ark-gold px-2.5 py-1 text-xs font-semibold text-black">
|
||||||
即将到来
|
即将到来
|
||||||
|
|||||||
@@ -68,9 +68,13 @@ export function BubbleImage({
|
|||||||
src={current}
|
src={current}
|
||||||
alt=""
|
alt=""
|
||||||
loading={loading}
|
loading={loading}
|
||||||
className={className}
|
decoding="async"
|
||||||
|
className={`ark-img-fade ${className ?? ""}`}
|
||||||
onLoad={(e) => {
|
onLoad={(e) => {
|
||||||
const img = e.currentTarget;
|
const img = e.currentTarget;
|
||||||
|
// Fade each image in as soon as it loads, so they appear progressively
|
||||||
|
// instead of the page seeming to wait for everything.
|
||||||
|
img.classList.add("is-loaded");
|
||||||
if (img.naturalWidth && img.naturalHeight)
|
if (img.naturalWidth && img.naturalHeight)
|
||||||
onNaturalSize?.(img.naturalWidth, img.naturalHeight);
|
onNaturalSize?.(img.naturalWidth, img.naturalHeight);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ function AttachmentRow({ postId, att }: { postId: string; att: Attachment }) {
|
|||||||
src={previewUrl}
|
src={previewUrl}
|
||||||
alt=""
|
alt=""
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
onError={() => setPreviewFailed(true)}
|
onError={() => setPreviewFailed(true)}
|
||||||
className="h-16 w-16 shrink-0 rounded-lg object-cover"
|
className="h-16 w-16 shrink-0 rounded-lg object-cover"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ export function SingleImageFrame({
|
|||||||
return (
|
return (
|
||||||
<AdaptiveImageFrame
|
<AdaptiveImageFrame
|
||||||
attachment={attachment}
|
attachment={attachment}
|
||||||
|
// Show the lightweight thumbnail in-stream for fast, progressive loading;
|
||||||
|
// the full image is loaded on tap in the lightbox. Falls back to the full
|
||||||
|
// asset if no thumbnail exists.
|
||||||
|
src={attachment.thumbnailUrl ?? attachment.thumbUrl ?? attachment.url}
|
||||||
|
fallbackSrc={[attachment.thumbUrl, attachment.url]}
|
||||||
onOpen={() => openLightbox([attachment], 0, text, postId)}
|
onOpen={() => openLightbox([attachment], 0, text, postId)}
|
||||||
ariaLabel="View image"
|
ariaLabel="View image"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LoaderCircle, Maximize2, Play, X } from "lucide-react";
|
import { LoaderCircle, Play, X } from "lucide-react";
|
||||||
import { DownloadCloudIcon } from "../../icons/DownloadCloudIcon";
|
import { DownloadCloudIcon } from "../../icons/DownloadCloudIcon";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
@@ -79,10 +79,12 @@ function VideoAttachmentCard({
|
|||||||
src={attachment.url}
|
src={attachment.url}
|
||||||
poster={attachment.posterUrl}
|
poster={attachment.posterUrl}
|
||||||
controls
|
controls
|
||||||
|
controlsList="nodownload noplaybackrate noremoteplayback"
|
||||||
|
disablePictureInPicture
|
||||||
playsInline
|
playsInline
|
||||||
autoPlay
|
autoPlay
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
className="absolute inset-0 h-full w-full"
|
className="ark-message-video absolute inset-0 h-full w-full"
|
||||||
/>
|
/>
|
||||||
<AttachmentDownloadPill
|
<AttachmentDownloadPill
|
||||||
postId={postId}
|
postId={postId}
|
||||||
@@ -90,18 +92,6 @@ function VideoAttachmentCard({
|
|||||||
leadingLabel={duration}
|
leadingLabel={duration}
|
||||||
className="absolute left-2 top-2 z-20"
|
className="absolute left-2 top-2 z-20"
|
||||||
/>
|
/>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
const v = videoRef.current;
|
|
||||||
openVideo(attachment, v?.currentTime ?? 0);
|
|
||||||
}}
|
|
||||||
className="absolute right-2 top-2 z-20 flex h-9 w-9 items-center justify-center rounded-full bg-black/60 text-white shadow-lg ring-1 ring-white/25 transition hover:bg-black/80"
|
|
||||||
aria-label="Fullscreen"
|
|
||||||
>
|
|
||||||
<Maximize2 className="h-4 w-4" strokeWidth={2.2} />
|
|
||||||
</button>
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -109,6 +99,8 @@ function VideoAttachmentCard({
|
|||||||
<img
|
<img
|
||||||
src={posterUrl}
|
src={posterUrl}
|
||||||
alt=""
|
alt=""
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
className={`absolute inset-0 h-full w-full object-cover ${
|
className={`absolute inset-0 h-full w-full object-cover ${
|
||||||
overlayCount ? "blur-sm scale-105" : ""
|
overlayCount ? "blur-sm scale-105" : ""
|
||||||
}`}
|
}`}
|
||||||
@@ -284,6 +276,8 @@ function VideoListDialog({
|
|||||||
<img
|
<img
|
||||||
src={thumb}
|
src={thumb}
|
||||||
alt=""
|
alt=""
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
className="h-full w-full object-cover"
|
className="h-full w-full object-cover"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Reference in New Issue
Block a user