import { Col } from "@/components/col"; import { Toolbar } from "@/components/toolbar"; import { ArrowLeftIcon, ArrowRightIcon } from "@lume/icons"; import { EventColumns, LumeColumn } from "@lume/types"; import { Spinner } from "@lume/ui"; import { createFileRoute } from "@tanstack/react-router"; import { listen } from "@tauri-apps/api/event"; import { resolveResource } from "@tauri-apps/api/path"; import { getCurrent } from "@tauri-apps/api/webviewWindow"; import { readTextFile } from "@tauri-apps/plugin-fs"; import { nanoid } from "nanoid"; import { useEffect, useRef, useState } from "react"; import { useDebounce, useDebouncedCallback } from "use-debounce"; import { VList, VListHandle } from "virtua"; export const Route = createFileRoute("/$account/home")({ component: Screen, pendingComponent: Pending, beforeLoad: async ({ context }) => { const ark = context.ark; const resourcePath = await resolveResource("resources/system_columns.json"); const systemColumns: LumeColumn[] = JSON.parse( await readTextFile(resourcePath), ); const userColumns = await ark.get_columns(); return { storedColumns: !userColumns.length ? systemColumns : userColumns, }; }, }); function Screen() { const vlistRef = useRef(null); const { account } = Route.useParams(); const { ark, storedColumns } = Route.useRouteContext(); const [selectedIndex, setSelectedIndex] = useState(-1); const [columns, setColumns] = useState(storedColumns); const [isScroll, setIsScroll] = useState(false); const [isResize, setIsResize] = useState(false); const goLeft = () => { const prevIndex = Math.max(selectedIndex - 1, 0); setSelectedIndex(prevIndex); vlistRef.current.scrollToIndex(prevIndex, { align: "center", }); }; const goRight = () => { const nextIndex = Math.min(selectedIndex + 1, columns.length - 1); setSelectedIndex(nextIndex); vlistRef.current.scrollToIndex(nextIndex, { align: "center", }); }; const add = useDebouncedCallback((column: LumeColumn) => { // update col label column["label"] = column.label + "-" + nanoid(); // create new cols const cols = [...columns]; const openColIndex = cols.findIndex((col) => col.label === "open"); const newCols = [ ...cols.slice(0, openColIndex), column, ...cols.slice(openColIndex), ]; setColumns(newCols); setSelectedIndex(cols.length - 1); // scroll to the newest column vlistRef.current.scrollToIndex(cols.length - 1, { align: "end", }); }, 150); const remove = useDebouncedCallback((label: string) => { setColumns((state) => state.filter((t) => t.label !== label)); setSelectedIndex(columns.length - 1); // scroll to the first column vlistRef.current.scrollToIndex(0, { align: "start", }); }, 150); const startResize = useDebouncedCallback( () => setIsResize((prev) => !prev), 150, ); useEffect(() => { // save state ark.set_columns(columns); }, [columns]); useEffect(() => { let unlistenColEvent: Awaited> | undefined = undefined; let unlistenWindowResize: Awaited> | undefined = undefined; (async () => { if (unlistenColEvent && unlistenWindowResize) return; unlistenColEvent = await listen("columns", (data) => { if (data.payload.type === "add") add(data.payload.column); if (data.payload.type === "remove") remove(data.payload.label); }); unlistenWindowResize = await getCurrent().listen("tauri://resize", () => { startResize(); }); })(); return () => { if (unlistenColEvent) unlistenColEvent(); if (unlistenWindowResize) unlistenWindowResize(); }; }, []); return (
setIsScroll(true)} onScrollEnd={() => setIsScroll(false)} className="scrollbar-none h-full w-full overflow-x-auto focus:outline-none" > {columns.map((column, index) => ( ))}
); } function Pending() { return (
); }