From 77d3289d277751a98900d8969b2c94dabeba5ea9 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" <219766164+opencode-agent[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 15:24:47 -0500 Subject: [PATCH] chore: merge dev into v2 (#38182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com> Co-authored-by: opencode-agent[bot] Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Victor Navarro Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: Frank Co-authored-by: Aiden Cline Co-authored-by: Dax Raad Co-authored-by: Dax Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Nabs Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: Brendan Allan Co-authored-by: Vladimir Glafirov Co-authored-by: AidenGeunGeun Co-authored-by: Mark Co-authored-by: Aiden Cline Co-authored-by: opencode Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com> Co-authored-by: David Hill <1879069+iamdavidhill@users.noreply.github.com> Co-authored-by: Jay Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: BB84 <110078428+BB-84C@users.noreply.github.com> Co-authored-by: Dustin Deus Co-authored-by: Jack Co-authored-by: Sebastian Co-authored-by: Jérôme Benoit Co-authored-by: Test User Co-authored-by: Simon Klee Co-authored-by: Rahul A Mistry <149420892+ProdigyRahul@users.noreply.github.com> Co-authored-by: Qiping Li Co-authored-by: liqiping Co-authored-by: OpeOginni <107570612+OpeOginni@users.noreply.github.com> Co-authored-by: Matthias Reso <13337103+mreso@users.noreply.github.com> Co-authored-by: tobwen <1864057+tobwen@users.noreply.github.com> Co-authored-by: Daniel Polito --- packages/app/src/pages/home.tsx | 153 +- packages/console/app/src/i18n/ar.ts | 1 + packages/console/app/src/i18n/br.ts | 1 + packages/console/app/src/i18n/da.ts | 1 + packages/console/app/src/i18n/de.ts | 1 + packages/console/app/src/i18n/en.ts | 1 + packages/console/app/src/i18n/es.ts | 1 + packages/console/app/src/i18n/fr.ts | 1 + packages/console/app/src/i18n/it.ts | 1 + packages/console/app/src/i18n/ja.ts | 1 + packages/console/app/src/i18n/ko.ts | 1 + packages/console/app/src/i18n/no.ts | 1 + packages/console/app/src/i18n/pl.ts | 1 + packages/console/app/src/i18n/ru.ts | 1 + packages/console/app/src/i18n/th.ts | 1 + packages/console/app/src/i18n/tr.ts | 1 + packages/console/app/src/i18n/uk.ts | 1 + packages/console/app/src/i18n/zh.ts | 1 + packages/console/app/src/i18n/zht.ts | 1 + .../app/src/routes/zen/util/handler.ts | 9 + .../migration.sql | 3 + .../snapshot.json | 3135 +++++++++++++++++ .../console/core/src/schema/workspace.sql.ts | 5 +- .../components/prompt-input/machine.test.ts | 13 + .../src/v2/components/prompt-input/machine.ts | 4 +- .../src/v2/components/progress-circle-v2.css | 2 +- packages/web/src/content/docs/ar/zen.mdx | 120 +- packages/web/src/content/docs/bs/zen.mdx | 120 +- packages/web/src/content/docs/da/zen.mdx | 120 +- packages/web/src/content/docs/de/zen.mdx | 120 +- packages/web/src/content/docs/es/zen.mdx | 120 +- packages/web/src/content/docs/fr/zen.mdx | 120 +- packages/web/src/content/docs/it/zen.mdx | 120 +- packages/web/src/content/docs/ja/zen.mdx | 120 +- packages/web/src/content/docs/ko/zen.mdx | 120 +- packages/web/src/content/docs/nb/zen.mdx | 120 +- packages/web/src/content/docs/pl/zen.mdx | 120 +- packages/web/src/content/docs/pt-br/zen.mdx | 120 +- packages/web/src/content/docs/ru/zen.mdx | 120 +- packages/web/src/content/docs/th/zen.mdx | 120 +- packages/web/src/content/docs/tr/zen.mdx | 120 +- packages/web/src/content/docs/zen.mdx | 120 +- packages/web/src/content/docs/zh-cn/zen.mdx | 120 +- packages/web/src/content/docs/zh-tw/zen.mdx | 120 +- 44 files changed, 4465 insertions(+), 1037 deletions(-) create mode 100644 packages/console/core/migrations/20260721182121_wet_pestilence/migration.sql create mode 100644 packages/console/core/migrations/20260721182121_wet_pestilence/snapshot.json diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx index 278032a4ca..49440a4aba 100644 --- a/packages/app/src/pages/home.tsx +++ b/packages/app/src/pages/home.tsx @@ -17,6 +17,11 @@ import { } from "solid-js" import { makeEventListener } from "@solid-primitives/event-listener" import { createStore, produce } from "solid-js/store" +import { DragDropProvider, PointerSensor } from "@dnd-kit/solid" +import { isSortable, useSortable } from "@dnd-kit/solid/sortable" +import { AutoScroller, Feedback, PointerActivationConstraints } from "@dnd-kit/dom" +import { RestrictToVerticalAxis } from "@dnd-kit/abstract/modifiers" +import { RestrictToElement } from "@dnd-kit/dom/modifiers" import { useQuery } from "@tanstack/solid-query" import { Button } from "@opencode-ai/ui/button" import { Logo } from "@opencode-ai/ui/logo" @@ -1002,7 +1007,7 @@ function HomeServerRow(props: { ) } -function HomeProjectList(props: { +type HomeProjectListProps = { server: ServerConnection.Any projects: LocalProject[] selected: HomeProjectSelection @@ -1013,29 +1018,82 @@ function HomeProjectList(props: { clearNotifications: (server: ServerConnection.Any, project: LocalProject) => void unseenCount: (server: ServerConnection.Any, project: LocalProject) => number language: ReturnType -}) { +} + +function HomeProjectList(props: HomeProjectListProps) { + const global = useGlobal() + let listRef!: HTMLDivElement + const projects = () => global.ensureServerCtx(props.server).projects + return ( -
- - {(project) => ( - - )} - -
+ [ + ...defaults.filter((sensor) => sensor !== PointerSensor), + PointerSensor.configure({ + activationConstraints: (event) => + event.pointerType === "touch" + ? [new PointerActivationConstraints.Delay({ value: 250, tolerance: 5 })] + : [new PointerActivationConstraints.Distance({ value: 4 })], + preventActivation: (event) => event.target instanceof Element && !!event.target.closest("[data-action]"), + }), + ]} + modifiers={[RestrictToVerticalAxis, RestrictToElement.configure({ element: () => listRef })]} + plugins={(defaults) => [ + ...defaults.filter((plugin) => plugin !== AutoScroller && plugin !== Feedback), + AutoScroller.configure({ acceleration: 8, threshold: { x: 0, y: 0.05 } }), + Feedback.configure({ dropAnimation: null }), + ]} + onDragEnd={(event) => { + const source = event.operation.source + if (event.canceled || !isSortable(source)) return + if (source.initialIndex !== source.index) projects().move(source.id.toString(), source.index) + if (props.selected.server !== ServerConnection.key(props.server)) + props.selectProject(props.server, source.id.toString()) + }} + > +
+ {/* Keyed on worktree strings: the enriched project objects are + recreated on every store or sync update, so iterating them directly + remounts all rows — killing any in-flight drag activation (the + row's sortable unregisters on unmount) and discarding animations. + String keys keep row elements alive and move them on reorder. */} + project.worktree)}> + {(worktree, index) => } + +
+
+ ) +} + +function HomeProjectSlot( + props: HomeProjectListProps & { + worktree: string + index: () => number + }, +) { + const project = createMemo(() => props.projects.find((item) => item.worktree === props.worktree)) + + return ( + + {(item) => ( + + )} + ) } @@ -1115,6 +1173,8 @@ function HomeRecentlyClosedRow(props: { function HomeProjectRow(props: { project: LocalProject server: ServerConnection.Any + index: () => number + serverSelected: boolean selected: boolean unseenCount: number selectProject: (server: ServerConnection.Any, directory: string) => void @@ -1128,6 +1188,15 @@ function HomeProjectRow(props: { const platform = usePlatform() const serverUnreachable = () => global.servers.health[ServerConnection.key(props.server)]?.healthy === false const [state, setState] = createStore({ menuOpen: false }) + const sortable = useSortable({ + get id() { + return props.project.worktree + }, + get index() { + return props.index() + }, + }) + let pointerDownSelected: boolean | undefined const canRevealInFileManager = () => platform.platform === "desktop" && !!platform.openPath && ServerConnection.local(props.server) const fileManagerActionLabel = () => @@ -1144,15 +1213,49 @@ function HomeProjectRow(props: { ) } return ( -
+