From 1bc1e56da379fdd9040dc40caac1a57ffe8d1197 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:52:39 -0600 Subject: wip(desktop): progress --- packages/desktop/src/pages/layout.tsx | 354 ++++++++++++++++++++------------- packages/desktop/src/pages/session.tsx | 2 +- 2 files changed, 221 insertions(+), 135 deletions(-) (limited to 'packages/desktop/src/pages') diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 6831fdf31..61fa6c766 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -1,4 +1,4 @@ -import { createEffect, createMemo, For, Match, ParentProps, Show, Switch } from "solid-js" +import { createEffect, createMemo, For, Match, ParentProps, Show, Switch, type JSX } from "solid-js" import { DateTime } from "luxon" import { A, useNavigate, useParams } from "@solidjs/router" import { useLayout } from "@/context/layout" @@ -19,10 +19,21 @@ import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu" import { Session } from "@opencode-ai/sdk/v2/client" import { usePlatform } from "@/context/platform" import { createStore } from "solid-js/store" +import { + DragDropProvider, + DragDropSensors, + DragOverlay, + SortableProvider, + closestCenter, + createSortable, + useDragDropContext, +} from "@thisbeyond/solid-dnd" +import type { DragEvent, Transformer } from "@thisbeyond/solid-dnd" export default function Layout(props: ParentProps) { const [store, setStore] = createStore({ lastSession: {} as { [directory: string]: string }, + activeDraggable: undefined as string | undefined, }) const params = useParams() @@ -52,6 +63,7 @@ export default function Layout(props: ParentProps) { function closeProject(directory: string) { layout.projects.close(directory) + // TODO: more intelligent navigation navigate("/") } @@ -76,6 +88,192 @@ export default function Layout(props: ParentProps) { setStore("lastSession", directory, params.id) }) + function getDraggableId(event: unknown): string | undefined { + if (typeof event !== "object" || event === null) return undefined + if (!("draggable" in event)) return undefined + const draggable = (event as { draggable?: { id?: unknown } }).draggable + if (!draggable) return undefined + return typeof draggable.id === "string" ? draggable.id : undefined + } + + function handleDragStart(event: unknown) { + const id = getDraggableId(event) + if (!id) return + setStore("activeDraggable", id) + } + + function handleDragOver(event: DragEvent) { + const { draggable, droppable } = event + if (draggable && droppable) { + const projects = layout.projects.list() + const fromIndex = projects.findIndex((p) => p.directory === draggable.id.toString()) + const toIndex = projects.findIndex((p) => p.directory === droppable.id.toString()) + if (fromIndex !== toIndex && toIndex !== -1) { + layout.projects.move(draggable.id.toString(), toIndex) + } + } + } + + function handleDragEnd() { + setStore("activeDraggable", undefined) + } + + const ConstrainDragXAxis = (): JSX.Element => { + const context = useDragDropContext() + if (!context) return <>> + const [, { onDragStart, onDragEnd, addTransformer, removeTransformer }] = context + const transformer: Transformer = { + id: "constrain-x-axis", + order: 100, + callback: (transform) => ({ ...transform, x: 0 }), + } + onDragStart((event) => { + const id = getDraggableId(event) + if (!id) return + addTransformer("draggables", id, transformer) + }) + onDragEnd((event) => { + const id = getDraggableId(event) + if (!id) return + removeTransformer("draggables", id, transformer.id) + }) + return <>> + } + + const SortableProject = (props: { project: { directory: string; expanded: boolean } }): JSX.Element => { + const sortable = createSortable(props.project.directory) + const [projectStore] = globalSync.child(props.project.directory) + const slug = createMemo(() => base64Encode(props.project.directory)) + const name = createMemo(() => getFilename(props.project.directory)) + return ( + // @ts-ignore +