111 lines
2.8 KiB
TypeScript
111 lines
2.8 KiB
TypeScript
import type { mastodon } from "masto";
|
|
import {
|
|
splitProps,
|
|
type Component,
|
|
type JSX,
|
|
createRenderEffect,
|
|
createMemo,
|
|
Show,
|
|
} from "solid-js";
|
|
import { resolveCustomEmoji } from "../../masto/toot.js";
|
|
import { makeAcctText, useDefaultSession } from "../../masto/clients.js";
|
|
import "./TootContent.css";
|
|
import { Button } from "@suid/material";
|
|
import { createTranslator } from "~platform/i18n.js";
|
|
|
|
function preventDefault(event: Event) {
|
|
event.preventDefault();
|
|
}
|
|
|
|
export type TootContentProps = JSX.HTMLAttributes<HTMLDivElement> & {
|
|
source?: string;
|
|
emojis?: mastodon.v1.CustomEmoji[];
|
|
mentions: mastodon.v1.StatusMention[];
|
|
sensitive?: boolean;
|
|
spoilerText?: string;
|
|
reveal?: boolean;
|
|
onToggleReveal?: JSX.EventHandlerUnion<HTMLElement, Event>;
|
|
};
|
|
|
|
const TootContent: Component<TootContentProps> = (oprops) => {
|
|
const [t] = createTranslator(
|
|
(code) =>
|
|
import(`./i18n/${code}.json`) as Promise<{
|
|
default: {
|
|
cw: string;
|
|
};
|
|
}>,
|
|
);
|
|
|
|
const session = useDefaultSession();
|
|
const [props, rest] = splitProps(oprops, [
|
|
"source",
|
|
"emojis",
|
|
"mentions",
|
|
"class",
|
|
"sensitive",
|
|
"spoilerText",
|
|
"reveal",
|
|
"onToggleReveal",
|
|
]);
|
|
|
|
const clientFinder = createMemo(() =>
|
|
session() ? makeAcctText(session()!) : undefined,
|
|
);
|
|
|
|
const shouldRevealContent = () => {
|
|
return !props.sensitive || (props.sensitive && props.reveal);
|
|
};
|
|
|
|
return (
|
|
<div
|
|
ref={(ref) => {
|
|
createRenderEffect(() => {
|
|
const finder = clientFinder();
|
|
for (const mention of props.mentions) {
|
|
const elements = ref.querySelectorAll<HTMLAnchorElement>(
|
|
`a[href='${mention.url}']`,
|
|
);
|
|
for (const e of elements) {
|
|
e.onclick = preventDefault;
|
|
e.dataset.action = "acct";
|
|
e.dataset.client = finder;
|
|
e.dataset.acctId = mention.id.toString();
|
|
}
|
|
}
|
|
});
|
|
}}
|
|
class={`TootContent ${props.class || ""}`}
|
|
{...rest}
|
|
>
|
|
<Show when={props.sensitive}>
|
|
<div>
|
|
<span
|
|
innerHTML={
|
|
props.spoilerText
|
|
? props.emojis
|
|
? resolveCustomEmoji(props.spoilerText, props.emojis)
|
|
: props.spoilerText
|
|
: ""
|
|
}
|
|
></span>
|
|
<Button onClick={props.onToggleReveal}>{t("cw")}</Button>
|
|
</div>
|
|
</Show>
|
|
<Show when={shouldRevealContent()}>
|
|
<div
|
|
class="content"
|
|
innerHTML={
|
|
props.source
|
|
? props.emojis
|
|
? resolveCustomEmoji(props.source, props.emojis)
|
|
: props.source
|
|
: ""
|
|
}
|
|
></div>
|
|
</Show>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default TootContent;
|