import type { Bookmark } from "@markone/core" import { createFileRoute, useNavigate } from "@tanstack/react-router" import clsx from "clsx" import { atom, useAtom } from "jotai" import { useCallback, useEffect, useRef } from "react" import { fetchApi, useAuthenticatedQuery } from "~/api" import { useBookmark } from "~/bookmark/api" import { Button, LinkButton } from "~/components/button" import { LoadingSpinner } from "~/components/loading-spinner" import { useMnemonics } from "~/hooks/use-mnemonics" import { ActionBar } from "./-action-bar" import { BookmarkList } from "./-bookmark-list" import { DialogKind, LayoutMode, useBookmarkPageStore } from "./-store" export const Route = createFileRoute("/bookmarks/$bookmarkId")({ component: RouteComponent, }) const actionBarHeight = atom(0) const setActionBarHeight = atom(null, (_, set, update: number) => { set(actionBarHeight, update) }) const titleBarHeight = atom(0) const setTitleBarHeight = atom(null, (_, set, update: number) => { set(titleBarHeight, update) }) function RouteComponent() { return (
) } function Main({ children }: React.PropsWithChildren) { const layoutMode = useBookmarkPageStore((state) => state.layoutMode) return (
{children}
) } function BookmarkPreviewContainer({ children }: React.PropsWithChildren) { const layoutMode = useBookmarkPageStore((state) => state.layoutMode) return (
{children}
) } function BookmarkListSidebar() { return (

 >  YOUR BOOKMARKS

) } function BookmarkListContainer() { const { bookmarkId } = Route.useParams() const navigate = useNavigate() const { data: bookmarks, status } = useAuthenticatedQuery(["bookmarks"], () => fetchApi("/bookmarks").then((res) => res.json()), ) const handleBookmarkListItemAction = useBookmarkPageStore((state) => state.handleBookmarkListItemAction) const onSelectedBookmarkChange = useCallback( (bookmark: Bookmark) => { navigate({ to: `/bookmarks/${bookmark.id}` }) }, [navigate], ) switch (status) { case "success": return ( ) case "pending": return (

Loading

) case "error": return

error loading bookmarks

} } function BookmarkListActionBar() { const setActiveDialog = useBookmarkPageStore((state) => state.setActiveDialog) function addBookmark() { setActiveDialog({ kind: DialogKind.AddBookmark }) } useMnemonics( { a: addBookmark, }, { ignore: useCallback(() => useBookmarkPageStore.getState().dialog.kind !== DialogKind.None, []) }, ) return ( ) } function BookmarkPreview() { const { bookmarkId } = Route.useParams() const { data: previewHtml, status: previewQueryStatus } = useAuthenticatedQuery( ["bookmarks", `${bookmarkId}.html`], () => fetchApi(`/bookmarks/${bookmarkId}`, { headers: { Accept: "text/html", }, }).then((res) => res.text()), ) const { data: bookmark, status: bookmarkQueryStatus } = useBookmark(bookmarkId) const [_titleBarHeight] = useAtom(titleBarHeight) const [_actionBarHeight] = useAtom(actionBarHeight) const navigate = useNavigate() function attachKeyListenerToIFrame(event: React.SyntheticEvent) { if (event.currentTarget.contentDocument) { event.currentTarget.contentDocument.addEventListener("keydown", (keyEvent) => { switch (keyEvent.key) { case "c": navigate({ to: "/bookmarks", replace: true }) break case "o": if (bookmark) { window.open(bookmark.url, "_blank")?.focus() } break default: break } }) } } if (previewQueryStatus === "error") { return (

Preview not available

) } if (previewQueryStatus === "success" && bookmarkQueryStatus === "success") { return (