RegularToot: support content warning

This commit is contained in:
thislight 2024-11-20 16:24:57 +08:00
parent cff0c2880a
commit 737d63f88a
No known key found for this signature in database
GPG key ID: FCFE5192241CCD4E
3 changed files with 64 additions and 11 deletions

View file

@ -5,6 +5,8 @@ import {
type JSX, type JSX,
Show, Show,
createRenderEffect, createRenderEffect,
createSignal,
type Setter,
} 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";
@ -200,6 +202,11 @@ export function findElementActionable(
return current; return current;
} }
function onToggleReveal(setValue: Setter<boolean>, event: Event) {
event.stopPropagation();
setValue((x) => !x);
}
/** /**
* Component for a toot. * Component for a toot.
* *
@ -239,6 +246,7 @@ const RegularToot: Component<TootCardProps> = (props) => {
const status = () => managed.status; const status = () => managed.status;
const toot = () => status().reblog ?? status(); const toot = () => status().reblog ?? status();
const session = useDefaultSession(); const session = useDefaultSession();
const [reveal, setReveal] = createSignal(false);
css` css`
.reply-sep { .reply-sep {
@ -326,6 +334,10 @@ const RegularToot: Component<TootCardProps> = (props) => {
emojis={toot().emojis} emojis={toot().emojis}
mentions={toot().mentions} mentions={toot().mentions}
class={cardStyle.cardNoPad} class={cardStyle.cardNoPad}
sensitive={toot().sensitive}
spoilerText={toot().spoilerText}
reveal={reveal()}
onToggleReveal={[onToggleReveal, setReveal]}
/> />
<Show when={toot().card}> <Show when={toot().card}>
<PreviewCard src={toot().card!} /> <PreviewCard src={toot().card!} />

View file

@ -4,6 +4,10 @@
margin-right: var(--card-pad, 0); margin-right: var(--card-pad, 0);
line-height: 1.5; line-height: 1.5;
> .content {
display: contents;
}
& * { & * {
user-select: text; user-select: text;
} }

View file

@ -5,20 +5,26 @@ import {
type JSX, type JSX,
createRenderEffect, createRenderEffect,
createMemo, createMemo,
Show,
} from "solid-js"; } from "solid-js";
import { resolveCustomEmoji } from "../../masto/toot.js"; import { resolveCustomEmoji } from "../../masto/toot.js";
import { makeAcctText, useDefaultSession } from "../../masto/clients"; import { makeAcctText, useDefaultSession } from "../../masto/clients";
import "./TootContent.css"; import "./TootContent.css";
import { Button } from "@suid/material";
function preventDefault(event: Event) { function preventDefault(event: Event) {
event.preventDefault(); event.preventDefault();
} }
export type TootContentProps = { export type TootContentProps = JSX.HTMLAttributes<HTMLDivElement> & {
source?: string; source?: string;
emojis?: mastodon.v1.CustomEmoji[]; emojis?: mastodon.v1.CustomEmoji[];
mentions: mastodon.v1.StatusMention[]; mentions: mastodon.v1.StatusMention[];
} & JSX.HTMLAttributes<HTMLDivElement>; sensitive?: boolean;
spoilerText?: string;
reveal?: boolean;
onToggleReveal?: JSX.EventHandlerUnion<HTMLElement, Event>;
};
const TootContent: Component<TootContentProps> = (oprops) => { const TootContent: Component<TootContentProps> = (oprops) => {
const session = useDefaultSession(); const session = useDefaultSession();
@ -27,23 +33,23 @@ const TootContent: Component<TootContentProps> = (oprops) => {
"emojis", "emojis",
"mentions", "mentions",
"class", "class",
"sensitive",
"spoilerText",
"reveal",
"onToggleReveal",
]); ]);
const clientFinder = createMemo(() => const clientFinder = createMemo(() =>
session() ? makeAcctText(session()!) : undefined, session() ? makeAcctText(session()!) : undefined,
); );
const shouldRevealContent = () => {
return !props.sensitive || (props.sensitive && props.reveal);
};
return ( return (
<div <div
ref={(ref) => { ref={(ref) => {
createRenderEffect(() => {
ref.innerHTML = props.source
? props.emojis
? resolveCustomEmoji(props.source, props.emojis)
: props.source
: "";
});
createRenderEffect(() => { createRenderEffect(() => {
const finder = clientFinder(); const finder = clientFinder();
for (const mention of props.mentions) { for (const mention of props.mentions) {
@ -61,7 +67,38 @@ const TootContent: Component<TootContentProps> = (oprops) => {
}} }}
class={`TootContent ${props.class || ""}`} class={`TootContent ${props.class || ""}`}
{...rest} {...rest}
>
<Show when={props.sensitive}>
<div>
<span
ref={(ref) => {
createRenderEffect(() => {
ref.innerHTML = props.spoilerText
? props.emojis
? resolveCustomEmoji(props.spoilerText, props.emojis)
: props.spoilerText
: "";
});
}}
></span>
<Button onClick={props.onToggleReveal}>"Content Warning"</Button>
</div>
</Show>
<Show when={shouldRevealContent()}>
<div
class="content"
ref={(ref) =>
createRenderEffect(() => {
ref.innerHTML = props.source
? props.emojis
? resolveCustomEmoji(props.source, props.emojis)
: props.source
: "";
})
}
></div> ></div>
</Show>
</div>
); );
}; };