- TootPreviewCard and MediaAttachmentGrid - the placeholder thing is now offloaded to the browser
This commit is contained in:
parent
b9b2d40614
commit
66bded813d
3 changed files with 29 additions and 28 deletions
|
@ -81,58 +81,52 @@ const MediaAttachmentGrid: Component<{
|
||||||
>
|
>
|
||||||
<For each={props.attachments}>
|
<For each={props.attachments}>
|
||||||
{(item, index) => {
|
{(item, index) => {
|
||||||
const [loaded, setLoaded] = createSignal(false);
|
// I don't know why mastodon does not return this
|
||||||
const width = item.meta?.small?.width;
|
// and the condition for it to return this.
|
||||||
const height = item.meta?.small?.height;
|
// Anyway, It is useless now.
|
||||||
const aspectRatio = item.meta?.small?.aspect;
|
// My hope is the FastAverageColor, but
|
||||||
const maxHeight = vh35();
|
// we may need better tool to manage the performance impact
|
||||||
const realHeight = height && height > maxHeight ? maxHeight : height;
|
// before using this. See #37.
|
||||||
const realWidth =
|
// TODO: use fast average color to extract accent color
|
||||||
width && height && height > maxHeight
|
const accentColor = item.meta?.colors?.accent;
|
||||||
? maxHeight * (aspectRatio ?? 1)
|
|
||||||
: width;
|
|
||||||
const style = () =>
|
|
||||||
loaded()
|
|
||||||
? undefined
|
|
||||||
: {
|
|
||||||
width: realWidth ? `${realWidth}px` : undefined,
|
|
||||||
height: realHeight ? `${realHeight}px` : undefined,
|
|
||||||
};
|
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case "image":
|
case "image":
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
src={item.previewUrl}
|
src={item.previewUrl}
|
||||||
style={style()}
|
width={item.meta?.small?.width}
|
||||||
|
height={item.meta?.small?.height}
|
||||||
alt={item.description || undefined}
|
alt={item.description || undefined}
|
||||||
onClick={[openViewerFor, index()]}
|
onClick={[openViewerFor, index()]}
|
||||||
onLoad={[setLoaded, true]}
|
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
style={
|
||||||
|
accentColor ? { "--media-color-accent": accentColor } : {}
|
||||||
|
}
|
||||||
></img>
|
></img>
|
||||||
);
|
);
|
||||||
case "video":
|
case "video":
|
||||||
return (
|
return (
|
||||||
<video
|
<video
|
||||||
src={item.url || undefined}
|
src={item.url || undefined}
|
||||||
style={style()}
|
|
||||||
onLoadedMetadata={[setLoaded, true]}
|
|
||||||
autoplay={settings().autoPlayVideos}
|
autoplay={settings().autoPlayVideos}
|
||||||
playsinline={settings().autoPlayVideos ? true : undefined}
|
playsinline={settings().autoPlayVideos ? true : undefined}
|
||||||
controls
|
controls
|
||||||
poster={item.previewUrl}
|
poster={item.previewUrl}
|
||||||
|
width={item.meta?.small?.width}
|
||||||
|
height={item.meta?.small?.height}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case "gifv":
|
case "gifv":
|
||||||
return (
|
return (
|
||||||
<video
|
<video
|
||||||
src={item.url || undefined}
|
src={item.url || undefined}
|
||||||
style={style()}
|
|
||||||
onLoadedMetadata={[setLoaded, true]}
|
|
||||||
autoplay={settings().autoPlayGIFs}
|
autoplay={settings().autoPlayGIFs}
|
||||||
controls
|
controls
|
||||||
playsinline /* or safari on iOS will play in full-screen */
|
playsinline /* or safari on iOS will play in full-screen */
|
||||||
loop
|
loop
|
||||||
poster={item.previewUrl}
|
poster={item.previewUrl}
|
||||||
|
width={item.meta?.small?.width}
|
||||||
|
height={item.meta?.small?.height}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
createRenderEffect,
|
createRenderEffect,
|
||||||
createSignal,
|
createSignal,
|
||||||
createEffect,
|
createEffect,
|
||||||
|
type Accessor,
|
||||||
} from "solid-js";
|
} from "solid-js";
|
||||||
import tootStyle from "./toot.module.css";
|
import tootStyle from "./toot.module.css";
|
||||||
import { formatRelative } from "date-fns";
|
import { formatRelative } from "date-fns";
|
||||||
|
@ -306,6 +307,8 @@ export function TootPreviewCard(props: {
|
||||||
crossOrigin="anonymous"
|
crossOrigin="anonymous"
|
||||||
src={props.src.image!}
|
src={props.src.image!}
|
||||||
onLoad={onImgLoad}
|
onLoad={onImgLoad}
|
||||||
|
width={props.src.width || undefined}
|
||||||
|
height={props.src.height || undefined}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
|
@ -125,6 +125,7 @@
|
||||||
|
|
||||||
>img {
|
>img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
|
@ -232,18 +233,21 @@
|
||||||
max-height: 35vh;
|
max-height: 35vh;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
min-width: 40px;
|
min-width: 40px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
background-color: var(--tutu-color-surface-d);
|
background-color: var(--tutu-color-surface-d);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid var(--tutu-color-on-surface-d);
|
||||||
transition: border-color 220ms var(--tutu-anim-curve-std),
|
transition: outline-width 60ms var(--tutu-anim-curve-std), z-index 60ms var(--tutu-anim-curve-std);
|
||||||
box-shadow 220ms var(--tutu-anim-curve-std);
|
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
border: 1px solid var(--tutu-color-surface-dd);
|
/* TODO: the goal is to use the media's accent color as the outline */
|
||||||
box-shadow: var(--tutu-shadow-e1);
|
/* but our infra is not prepared for this. The average color thing is slow */
|
||||||
|
/* and we need further managing to control its performance impact. */
|
||||||
|
outline: 8px solid var(--media-color-accent, var(--tutu-color-surface-d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue