diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index c9b980cf79..f25cadf713 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -83,9 +83,16 @@ import { LocalWorkspace, SortableWorkspace, WorkspaceDragOverlay, + workspaceSortableDirectory, + workspaceSortableId, type WorkspaceSidebarContext, } from "./layout/sidebar-workspace" -import { ProjectDragOverlay, SortableProject, type ProjectSidebarContext } from "./layout/sidebar-project" +import { + ProjectDragOverlay, + SortableProject, + projectSortableWorktree, + type ProjectSidebarContext, +} from "./layout/sidebar-project" import { SidebarContent } from "./layout/sidebar-shell" export default function Layout(props: ParentProps) { @@ -1841,7 +1848,7 @@ export default function Layout(props: ParentProps) { ) function handleDragStart(event: unknown) { - const id = getDraggableId(event) + const id = projectSortableWorktree(getDraggableId(event)) if (!id) return setHoverProject(undefined) setStore("activeProject", id) @@ -1850,11 +1857,14 @@ export default function Layout(props: ParentProps) { function handleDragOver(event: DragEvent) { const { draggable, droppable } = event if (draggable && droppable) { + const from = projectSortableWorktree(draggable.id?.toString()) + const to = projectSortableWorktree(droppable.id?.toString()) + if (!from || !to) return const projects = layout.projects.list() - const fromIndex = projects.findIndex((p) => p.worktree === draggable.id.toString()) - const toIndex = projects.findIndex((p) => p.worktree === droppable.id.toString()) + const fromIndex = projects.findIndex((p) => p.worktree === from) + const toIndex = projects.findIndex((p) => p.worktree === to) if (fromIndex !== toIndex && toIndex !== -1) { - layout.projects.move(draggable.id.toString(), toIndex) + layout.projects.move(from, toIndex) } } } @@ -1892,7 +1902,7 @@ export default function Layout(props: ParentProps) { }) function handleWorkspaceDragStart(event: unknown) { - const id = getDraggableId(event) + const id = workspaceSortableDirectory(getDraggableId(event)) if (!id) return setStore("activeWorkspace", id) } @@ -1900,13 +1910,16 @@ export default function Layout(props: ParentProps) { function handleWorkspaceDragOver(event: DragEvent) { const { draggable, droppable } = event if (!draggable || !droppable) return + const from = workspaceSortableDirectory(draggable.id?.toString()) + const to = workspaceSortableDirectory(droppable.id?.toString()) + if (!from || !to) return const project = sidebarProject() if (!project) return const ids = workspaceIds(project) - const fromIndex = ids.findIndex((dir) => dir === draggable.id.toString()) - const toIndex = ids.findIndex((dir) => dir === droppable.id.toString()) + const fromIndex = ids.findIndex((dir) => dir === from) + const toIndex = ids.findIndex((dir) => dir === to) if (fromIndex === -1 || toIndex === -1) return if (fromIndex === toIndex) return @@ -2267,13 +2280,13 @@ export default function Layout(props: ParentProps) { }} class="size-full flex flex-col py-2 gap-4 overflow-y-auto no-scrollbar [overflow-anchor:none]" > - + {(directory) => ( diff --git a/packages/app/src/pages/layout/sidebar-project.tsx b/packages/app/src/pages/layout/sidebar-project.tsx index 076e1ef88b..d681cf3218 100644 --- a/packages/app/src/pages/layout/sidebar-project.tsx +++ b/packages/app/src/pages/layout/sidebar-project.tsx @@ -34,6 +34,17 @@ export type ProjectSidebarContext = { sessionProps: Omit } +const PROJECT_SORTABLE_PREFIX = "project:" + +export function projectSortableId(worktree: string) { + return `${PROJECT_SORTABLE_PREFIX}${worktree}` +} + +export function projectSortableWorktree(id: string | undefined) { + if (!id?.startsWith(PROJECT_SORTABLE_PREFIX)) return + return id.slice(PROJECT_SORTABLE_PREFIX.length) +} + export const ProjectDragOverlay = (props: { projects: Accessor activeProject: Accessor @@ -275,7 +286,7 @@ export const SortableProject = (props: { }): JSX.Element => { const globalSync = useGlobalSync() const language = useLanguage() - const sortable = createSortable(props.project.worktree) + const sortable = createSortable(projectSortableId(props.project.worktree)) const selected = createMemo(() => props.ctx.currentProject()?.worktree === props.project.worktree) const workspaces = createMemo(() => props.ctx.workspaceIds(props.project).slice(0, 2)) const workspaceEnabled = createMemo(() => props.ctx.workspacesEnabled(props.project)) diff --git a/packages/app/src/pages/layout/sidebar-shell.tsx b/packages/app/src/pages/layout/sidebar-shell.tsx index ca36af2a42..f8f8ea5165 100644 --- a/packages/app/src/pages/layout/sidebar-shell.tsx +++ b/packages/app/src/pages/layout/sidebar-shell.tsx @@ -11,6 +11,7 @@ import { ConstrainDragXAxis } from "@/utils/solid-dnd" import { IconButton } from "@opencode-ai/ui/icon-button" import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" import { type LocalProject } from "@/context/layout" +import { projectSortableId } from "./sidebar-project" export const SidebarContent = (props: { mobile?: boolean @@ -63,7 +64,7 @@ export const SidebarContent = (props: {
- p.worktree)}> + projectSortableId(p.worktree))}> {(project) => props.renderProject(project)} void } +const WORKSPACE_SORTABLE_PREFIX = "workspace:" + +export function workspaceSortableId(directory: string) { + return `${WORKSPACE_SORTABLE_PREFIX}${directory}` +} + +export function workspaceSortableDirectory(id: string | undefined) { + if (!id?.startsWith(WORKSPACE_SORTABLE_PREFIX)) return + return id.slice(WORKSPACE_SORTABLE_PREFIX.length) +} + export const WorkspaceDragOverlay = (props: { sidebarProject: Accessor activeWorkspace: Accessor @@ -300,7 +311,7 @@ export const SortableWorkspace = (props: { const params = useParams() const globalSync = useGlobalSync() const language = useLanguage() - const sortable = createSortable(props.directory) + const sortable = createSortable(workspaceSortableId(props.directory)) const [workspaceStore, setWorkspaceStore] = globalSync.child(props.directory, { bootstrap: false }) const [menu, setMenu] = createStore({ open: false,