diff --git a/src/material/Menu.tsx b/src/material/Menu.tsx index 6c08dad..365d090 100644 --- a/src/material/Menu.tsx +++ b/src/material/Menu.tsx @@ -14,84 +14,56 @@ type Props = { anchor: () => DOMRect; }; -function px(n?: number) { - if (n) { - return `${n}px`; - } else { - return undefined; - } +function adjustMenuPosition( + rect: DOMRect, + [left, top]: [number, number], + { width, height }: { width: number; height: number }, +) { + const ntop = rect.bottom > height ? top - (rect.bottom - height) : top; + const nleft = rect.right > width ? left - (rect.right - width) : left; + return [nleft, ntop] as [number, number]; } const Menu: ParentComponent = (props) => { let root: HTMLDialogElement; + const [pos, setPos] = createSignal<[number, number]>([0, 0]); const windowSize = useWindowSize(); - const [anchorPos, setAnchorPos] = createSignal<{ - left?: number; - top?: number; - }>({}); - - let openAnimationOrigin: "lt" | "rt" = "lt"; - createEffect(() => { if (props.open) { const a = props.anchor(); - if (!root.open) { root.showModal(); const rend = root.getBoundingClientRect(); - const { width } = windowSize; - const { left, top, right } = a; - if (left > width / 2) { - openAnimationOrigin = "rt"; - setAnchorPos({ - left: right - rend.width, - top, - }); + setPos(adjustMenuPosition(rend, [a.left, a.top], windowSize)); - const overflow = root.style.overflow; - root.style.overflow = "hidden"; - const duration = (rend.height / 1600) * 1000; - const easing = ANIM_CURVE_STD; - const animation = root.animate( - { - height: [`${rend.height / 2}px`, `${rend.height}px`], - }, - { - duration, - easing, - }, - ); - animation.addEventListener( - "finish", - () => (root.style.overflow = overflow), - ); - } else { - openAnimationOrigin = "lt"; - setAnchorPos({ left, top }); - - const overflow = root.style.overflow; - root.style.overflow = "hidden"; - const duration = (rend.height / 1600) * 1000; - const easing = ANIM_CURVE_STD; - const animation = root.animate( - { - height: [`${rend.height / 2}px`, `${rend.height}px`], - width: [`${(rend.width / 4) * 3}px`, `${rend.width}px`], - }, - { - duration, - easing, - }, - ); - animation.addEventListener( - "finish", - () => (root.style.overflow = overflow), - ); - } + const overflow = root.style.overflow; + root.style.overflow = "hidden"; + const duration = (rend.height / 1600) * 1000; + const easing = ANIM_CURVE_STD; + const animation = root.animate( + { + height: [`${rend.height / 2}px`, `${rend.height}px`], + width: [`${rend.width / 4 * 3}px`, `${rend.width}px`], + }, + { + duration, + easing, + }, + ); + animation.addEventListener( + "finish", + () => (root.style.overflow = overflow), + ); } else { - // TODO: update the pos + setPos( + adjustMenuPosition( + root.getBoundingClientRect(), + [a.left, a.top], + windowSize, + ), + ); } } else { animateClose(); @@ -100,40 +72,22 @@ const Menu: ParentComponent = (props) => { const animateClose = () => { const rend = root.getBoundingClientRect(); - if (openAnimationOrigin === "lt") { - const overflow = root.style.overflow; - root.style.overflow = "hidden"; - const animation = root.animate( - { - height: [`${rend.height}px`, `${rend.height / 2}px`], - width: [`${rend.width}px`, `${(rend.width / 4) * 3}px`], - }, - { - duration: (rend.height / 2 / 1600) * 1000, - easing: ANIM_CURVE_STD, - }, - ); - animation.addEventListener("finish", () => { - root.style.overflow = overflow; - root.close(); - }); - } else { - const overflow = root.style.overflow; - root.style.overflow = "hidden"; - const animation = root.animate( - { - height: [`${rend.height}px`, `${rend.height / 2}px`], - }, - { - duration: (rend.height / 2 / 1600) * 1000, - easing: ANIM_CURVE_STD, - }, - ); - animation.addEventListener("finish", () => { - root.style.overflow = overflow; - root.close(); - }); - } + const overflow = root.style.overflow; + root.style.overflow = "hidden"; + const animation = root.animate( + { + height: [`${rend.height}px`, `${rend.height / 2}px`], + width: [`${rend.width}px`, `${rend.width / 4 * 3}px`], + }, + { + duration: (rend.height / 2 / 1600) * 1000, + easing: ANIM_CURVE_STD, + }, + ); + animation.addEventListener("finish", () => { + root.style.overflow = overflow; + root.close(); + }); }; return ( @@ -157,15 +111,14 @@ const Menu: ParentComponent = (props) => { } }} style={{ - position: "fixed", - left: px(anchorPos().left), - top: px(anchorPos().top), + position: "absolute", + left: `${pos()[0]}px`, + top: `${pos()[1]}px`, border: "none", - "border-radius": "2px", padding: 0, "max-width": "560px", width: "max-content", - /* FIXME: the content may be overflow */ + /*"min-width": "20vw", */ "box-shadow": "var(--tutu-shadow-e8)", }} > diff --git a/src/profiles/Profile.tsx b/src/profiles/Profile.tsx index c9e7785..64cf0b5 100644 --- a/src/profiles/Profile.tsx +++ b/src/profiles/Profile.tsx @@ -2,34 +2,14 @@ import { createRenderEffect, createResource, createSignal, - createUniqueId, For, onCleanup, Show, type Component, } from "solid-js"; import Scaffold from "../material/Scaffold"; -import { - AppBar, - Avatar, - Button, - Divider, - IconButton, - ListItemIcon, - ListItemText, - MenuItem, - Toolbar, -} from "@suid/material"; -import { - Close, - Edit, - ExpandMore, - MoreVert, - OpenInBrowser, - Send, - Share, - Verified, -} from "@suid/icons-material"; +import { AppBar, Avatar, Button, IconButton, Toolbar } from "@suid/material"; +import { Close, MoreVert, Verified } from "@suid/icons-material"; import { Title } from "../material/typography"; import { useNavigate, useParams } from "@solidjs/router"; import { useSessionForAcctStr } from "../masto/clients"; @@ -41,8 +21,6 @@ import { createTimeline } from "../masto/timelines"; import TootList from "../timelines/TootList"; import { createTimeSource, TimeSourceProvider } from "../platform/timesrc"; import TootFilterButton from "./TootFilterButton"; -import Menu from "../material/Menu"; -import { share } from "../platform/share"; const Profile: Component = () => { const navigate = useNavigate(); @@ -56,10 +34,6 @@ const Profile: Component = () => { const windowSize = useWindowSize(); const time = createTimeSource(); - const menuButId = createUniqueId(); - - const [menuOpen, setMenuOpen] = createSignal(false); - const [scrolledPastBanner, setScrolledPastBanner] = createSignal(false); const obx = new IntersectionObserver( (entries) => { @@ -84,19 +58,18 @@ const Profile: Component = () => { ); const [recentTootFilter, setRecentTootFilter] = createSignal({ - boost: false, + boost: true, reply: true, original: true, }); - const [recentToots, recentTootChunk, { refetch: refetchRecentToots }] = - createTimeline( - () => session().client.v1.accounts.$select(params.id).statuses, - () => { - const { boost, reply } = recentTootFilter(); - return { limit: 20, excludeReblogs: !boost, excludeReplies: !reply }; - }, - ); + const [recentToots] = createTimeline( + () => session().client.v1.accounts.$select(params.id).statuses, + () => { + const { boost, reply } = recentTootFilter(); + return { limit: 20, excludeReblogs: !boost, excludeReplies: !reply }; + }, + ); const bannerImg = () => profile()?.header; const avatarImg = () => profile()?.avatar; @@ -167,11 +140,7 @@ const Profile: Component = () => { paddingTop: "var(--safe-area-inset-top)", }} > - + { createRenderEffect(() => (e.innerHTML = displayName())) } > - - + } > - - document.getElementById(menuButId)!.getBoundingClientRect() - } - > - - - - - Edit... - - - - - - - Mention {profile()?.displayName || ""}... - - - - - - - Open in browser... - - share({ url: profile()?.url })}> - - - - Share... - -
{
{ onChangeToot={recentToots.set} /> - - -
- - - -
-
); };