diff --git a/src/timelines/TootList.tsx b/src/timelines/TootList.tsx index caaf4c3..38670e2 100644 --- a/src/timelines/TootList.tsx +++ b/src/timelines/TootList.tsx @@ -13,7 +13,6 @@ import { useDefaultSession } from "../masto/clients"; import { useHeroSource } from "../platform/anim"; import { HERO as BOTTOM_SHEET_HERO } from "../material/BottomSheet"; import { setCache as setTootBottomSheetCache } from "./TootBottomSheet"; -import { useNavigate } from "@solidjs/router"; import RegularToot, { findElementActionable, findRootToot, @@ -21,6 +20,21 @@ import RegularToot, { import cardStyle from "../material/cards.module.css"; import type { ThreadNode } from "../masto/timelines"; import { useNavigator } from "../platform/StackedRouter"; +import { ANIM_CURVE_STD } from "../material/theme"; + +function durationOf(rect0: DOMRect, rect1: DOMRect) { + const distancelt = Math.sqrt( + Math.pow(Math.abs(rect0.top - rect1.top), 2) + + Math.pow(Math.abs(rect0.left - rect1.left), 2), + ); + const distancerb = Math.sqrt( + Math.pow(Math.abs(rect0.bottom - rect1.bottom), 2) + + Math.pow(Math.abs(rect0.right - rect1.right), 2), + ); + const distance = distancelt + distancerb; + const duration = distance / 1.6; + return duration; +} function positionTootInThread(index: number, threadLength: number) { if (index === 0) { @@ -41,7 +55,7 @@ const TootList: Component<{ const session = useDefaultSession(); const heroSrc = useHeroSource(); const [expandedThreadId, setExpandedThreadId] = createSignal(); - const {push} = useNavigator(); + const { push } = useNavigator(); const onBookmark = async (status: mastodon.v1.Status) => { const client = session()?.client; @@ -100,7 +114,7 @@ const TootList: Component<{ const openFullScreenToot = ( toot: mastodon.v1.Status, - srcElement?: HTMLElement, + srcElement: HTMLElement, reply?: boolean, ) => { const p = session()?.account; @@ -116,12 +130,55 @@ const TootList: Component<{ const acct = `${inf.username}@${p.site}`; setTootBottomSheetCache(acct, toot); + push(`/${encodeURIComponent(acct)}/toot/${toot.id}`, { - state: reply - ? { - tootReply: true, - } - : undefined, + animateOpen(element) { + const rect0 = srcElement.getBoundingClientRect(); // the start rect + const rect1 = element.getBoundingClientRect(); // the end rect + + const duration = durationOf(rect0, rect1); + + const keyframes = { + top: [`${rect0.top}px`, `${rect1.top}px`], + bottom: [`${rect0.bottom}px`, `${rect1.bottom}px`], + left: [`${rect0.left}px`, `${rect1.left}px`], + right: [`${rect0.right}px`, `${rect1.right}px`], + height: [`${rect0.height}px`, `${rect1.height}px`], + margin: 0, + }; + + srcElement.style.visibility = "hidden"; + + const animation = element.animate(keyframes, { + duration, + easing: ANIM_CURVE_STD, + }); + return animation; + }, + + animateClose(element) { + const rect0 = element.getBoundingClientRect(); // the start rect + const rect1 = srcElement.getBoundingClientRect(); // the end rect + + const duration = durationOf(rect0, rect1); + + const keyframes = { + top: [`${rect0.top}px`, `${rect1.top}px`], + bottom: [`${rect0.bottom}px`, `${rect1.bottom}px`], + left: [`${rect0.left}px`, `${rect1.left}px`], + right: [`${rect0.right}px`, `${rect1.right}px`], + height: [`${rect0.height}px`, `${rect1.height}px`], + margin: 0, + }; + + srcElement.style.visibility = ""; + + const animation = element.animate(keyframes, { + duration, + easing: ANIM_CURVE_STD, + }); + return animation; + }, }); };