tutu/src/timelines/toots/TootPollDialog.tsx
thislight 5d6eb7282a
All checks were successful
/ depoly (push) Successful in 1m18s
use innerHTML property
2024-11-24 17:16:06 +08:00

122 lines
3 KiB
TypeScript

import {
Button,
Checkbox,
List,
ListItemButton,
ListItemText,
Radio,
} from "@suid/material";
import type { mastodon } from "masto";
import {
createEffect,
createRenderEffect,
createSignal,
Index,
Show,
type Component,
} from "solid-js";
import BottomSheet, { type BottomSheetProps } from "~material/BottomSheet";
import Scaffold from "~material/Scaffold";
import { resolveCustomEmoji } from "../../masto/toot";
import "./TootPollDialog.css";
export type TootPollDialogPoll = {
open?: boolean;
options: Readonly<mastodon.v1.Poll["options"]>;
initialVotes?: readonly number[];
multiple?: boolean;
onVote: [
(
status: mastodon.v1.Status,
votes: readonly number[],
) => void | Promise<void>,
mastodon.v1.Status,
];
onClose?: BottomSheetProps["onClose"] &
((reason: "cancel" | "success") => void);
};
const TootPollDialog: Component<TootPollDialogPoll> = (props) => {
const [votes, setVotes] = createSignal([] as readonly number[]);
const [inProgress, setInProgress] = createSignal(false);
createEffect(() => {
setVotes(props.initialVotes || []);
});
const toggleVote = (i: number) => {
if (props.multiple) {
setVotes((o) => [...o.filter((x) => x === i), i]);
} else {
setVotes([i]);
}
};
const sendVote = async () => {
setInProgress(true);
try {
await props.onVote[0](props.onVote[1], votes());
} catch (reason) {
console.error(reason);
props.onClose?.("cancel");
return;
} finally {
setInProgress(false);
}
props.onClose?.("success");
};
return (
<BottomSheet open={props.open} onClose={props.onClose} bottomUp>
<Scaffold
class="TootPollDialog"
bottom={
<div class="actions">
<Button
color="error"
onClick={props.onClose ? [props.onClose, "cancel"] : undefined}
disabled={inProgress()}
>
Cancel
</Button>
<Button onClick={sendVote} disabled={inProgress()}>
Confirm
</Button>
</div>
}
>
<List>
<Index each={props.options}>
{(option, index) => {
return (
<ListItemButton
onClick={[toggleVote, index]}
disabled={inProgress()}
>
<ListItemText>
<span
innerHTML={resolveCustomEmoji(
option().title,
option().emojis,
)}
></span>
</ListItemText>
<Show
when={props.multiple}
fallback={<Radio checked={votes().includes(index)} />}
>
<Checkbox checked={votes().includes(index)} />
</Show>
</ListItemButton>
);
}}
</Index>
</List>
</Scaffold>
</BottomSheet>
);
};
export default TootPollDialog;