Cache all the things

This commit is contained in:
2023-09-05 14:57:50 +01:00
parent 5521f685fc
commit b1459d0f49
49 changed files with 805 additions and 243 deletions

View File

@ -11,70 +11,109 @@ import { ProxyImg } from "./ProxyImg";
import { SpotlightMedia } from "./SpotlightMedia";
export interface TextProps {
id: string;
content: string;
creator: HexKey;
tags: Array<Array<string>>;
disableMedia?: boolean;
disableMediaSpotlight?: boolean;
disableLinkPreview?: boolean;
depth?: number;
truncate?: number;
className?: string;
onClick?: (e: React.MouseEvent) => void;
}
export default function Text({ content, tags, creator, disableMedia, depth, disableMediaSpotlight }: TextProps) {
const TextCache = new Map<string, Array<ParsedFragment>>();
export default function Text({
id,
content,
tags,
creator,
disableMedia,
depth,
disableMediaSpotlight,
disableLinkPreview,
truncate,
className,
onClick
}: TextProps) {
const [showSpotlight, setShowSpotlight] = useState(false);
const [imageIdx, setImageIdx] = useState(0);
const elements = useMemo(() => {
return transformText(content, tags);
}, [content]);
const cached = TextCache.get(id);
if (cached) return cached;
const newCache = transformText(content, tags);
TextCache.set(id, newCache);
return newCache;
}, [content, id]);
const images = elements.filter(a => a.type === "media" && a.mimeType?.startsWith("image")).map(a => a.content);
function renderChunk(a: ParsedFragment) {
if (a.type === "media" && !a.mimeType?.startsWith("unknown")) {
if (disableMedia ?? false) {
return (
<a href={a.content} onClick={e => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">
{a.content}
</a>
);
const renderContent = () => {
let lenCtr = 0;
function renderChunk(a: ParsedFragment) {
if (truncate) {
if (lenCtr > truncate) {
return null;
} else if (lenCtr + a.content.length > truncate) {
lenCtr += a.content.length;
return <div className="text-frag">{a.content.slice(0, truncate - lenCtr)}...</div>
} else {
lenCtr += a.content.length;
}
}
return (
<RevealMedia
link={a.content}
creator={creator}
onMediaClick={e => {
if (!disableMediaSpotlight) {
e.stopPropagation();
e.preventDefault();
setShowSpotlight(true);
const selected = images.findIndex(b => b === a.content);
setImageIdx(selected === -1 ? 0 : selected);
}
}}
/>
);
} else {
switch (a.type) {
case "invoice":
return <Invoice invoice={a.content} />;
case "hashtag":
return <Hashtag tag={a.content} />;
case "cashu":
return <CashuNuts token={a.content} />;
case "media":
case "link":
return <HyperText link={a.content} depth={depth} showLinkPreview={!(disableMedia ?? false)}/>;
case "custom_emoji":
return <ProxyImg src={a.content} size={15} className="custom-emoji" />;
default:
return <div className="text-frag">{a.content}</div>;
if (a.type === "media" && !a.mimeType?.startsWith("unknown")) {
if (disableMedia ?? false) {
return (
<a href={a.content} onClick={e => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">
{a.content}
</a>
);
}
return (
<RevealMedia
link={a.content}
creator={creator}
onMediaClick={e => {
if (!disableMediaSpotlight) {
e.stopPropagation();
e.preventDefault();
setShowSpotlight(true);
const selected = images.findIndex(b => b === a.content);
setImageIdx(selected === -1 ? 0 : selected);
}
}}
/>
);
} else {
switch (a.type) {
case "invoice":
return <Invoice invoice={a.content} />;
case "hashtag":
return <Hashtag tag={a.content} />;
case "cashu":
return <CashuNuts token={a.content} />;
case "media":
case "link":
return <HyperText link={a.content} depth={depth} showLinkPreview={!(disableLinkPreview ?? false)} />;
case "custom_emoji":
return <ProxyImg src={a.content} size={15} className="custom-emoji" />;
default:
return <div className="text-frag">{a.content}</div>;
}
}
}
return elements.map(a => renderChunk(a));
}
return (
<div dir="auto" className="text">
{elements.map(a => renderChunk(a))}
<div dir="auto" className={`text${className ? ` ${className}` : ""}`} onClick={onClick}>
{renderContent()}
{showSpotlight && <SpotlightMedia images={images} onClose={() => setShowSpotlight(false)} idx={imageIdx} />}
</div>
);