import { useLocation, useNavigate, useParams } from "@solidjs/router"; import { createEffect, createRenderEffect, createResource, For, Show, type Component, } from "solid-js"; import Scaffold from "../material/Scaffold"; import TootThread from "./TootThread"; import { AppBar, Avatar, CircularProgress, IconButton, Toolbar, } from "@suid/material"; import { Title } from "../material/typography"; import { ArrowBack as BackIcon, Close as CloseIcon, Send, } from "@suid/icons-material"; import { isiOS } from "../platform/host"; import { createUnauthorizedClient, useSessions } from "../masto/clients"; import { resolveCustomEmoji } from "../masto/toot"; import RegularToot from "./RegularToot"; import type { mastodon } from "masto"; import cards from "../material/cards.module.css"; import { css } from "solid-styled"; import { vibrate } from "../platform/hardware"; let cachedEntry: [string, mastodon.v1.Status] | undefined; export function setCache(acct: string, status: mastodon.v1.Status) { cachedEntry = [acct, status]; } function getCache(acct: string, id: string) { if (acct === cachedEntry?.[0] && id === cachedEntry?.[1].id) { return cachedEntry[1]; } } const TootBottomSheet: Component = (props) => { const params = useParams<{ acct: string; id: string }>(); const location = useLocation<{ tootBottomSheetPushedCount?: number }>(); const navigate = useNavigate(); const allSession = useSessions(); const acctText = () => decodeURIComponent(params.acct); const session = () => { const [inputUsername, inputSite] = acctText().split("@", 2); const authedSession = allSession().find( (x) => x.account.site === inputSite && x.account.inf?.username === inputUsername, ); return ( authedSession ?? { client: createUnauthorizedClient(inputSite), account: undefined, } ); }; const profile = () => { return session().account; }; const pushedCount = () => { return location.state?.tootBottomSheetPushedCount || 0; }; const [remoteToot, { mutate: setRemoteToot }] = createResource( () => [session().client, params.id] as const, async ([client, id]) => { return await client.v1.statuses.$select(id).fetch(); }, ); const toot = () => remoteToot() ?? getCache(acctText(), params.id); createEffect(() => { const tootId = toot()?.id; if (!tootId) return; const elementId = `toot-${tootId}`; document.getElementById(elementId)?.scrollIntoView({ behavior: "smooth" }); }); const [tootContext] = createResource( () => [session().client, params.id] as const, async ([client, id]) => { return await client.v1.statuses.$select(id).context.fetch(); }, ); const ancestors = () => tootContext()?.ancestors ?? []; const descendants = () => tootContext()?.descendants ?? []; createEffect(() => { if (ancestors().length > 0) { document.querySelector(`#toot-${toot()!.id}`)?.scrollIntoView(); } }); const tootTitle = () => { const t = toot(); if (t) { const name = resolveCustomEmoji(t.account.displayName, t.account.emojis); return `${name}'s toot`; } return "A toot"; }; const actSession = () => { const s = session(); return s.account ? s : undefined; }; const onBookmark = async () => { const status = remoteToot()!; const client = actSession()!.client; const result = await (status.bookmarked ? client.v1.statuses.$select(status.id).unbookmark() : client.v1.statuses.$select(status.id).bookmark()); setRemoteToot(result); }; const onBoost = async () => { const status = remoteToot()!; const client = actSession()!.client; vibrate(50); setRemoteToot( Object.assign({}, status, { reblogged: !status.reblogged, }), ); const result = await (status.reblogged ? client.v1.statuses.$select(status.id).unreblog() : client.v1.statuses.$select(status.id).reblog()); vibrate([20, 30]); setRemoteToot(result); }; const onFav = async () => { const status = remoteToot()!; const client = actSession()!.client; const result = await (status.favourited ? client.v1.statuses.$select(status.id).favourite() : client.v1.statuses.$select(status.id).unfavourite()); setRemoteToot(result); }; const switchContext = (status: mastodon.v1.Status) => { setCache(params.acct, status); navigate(`/${params.acct}/${status.id}`, { state: { tootBottomSheetPushedCount: pushedCount() + 1, }, }); }; css` .bottom-dock { position: sticky; bottom: 0; } .name :global(img) { max-height: 1em; } `; return ( {pushedCount() > 0 ? : } createRenderEffect(() => (e.innerHTML = tootTitle())) } > } > {(item) => ( )}
{(item) => ( )}
); }; export default TootBottomSheet;