chore: cleanup (#17115)

This commit is contained in:
Adam
2026-03-12 12:26:43 +00:00
committed by GitHub
parent d8fbe0af01
commit d4107d51f1
35 changed files with 75 additions and 1202 deletions
@@ -6,9 +6,15 @@ import {
parseDeepLink,
parseNewSessionDeepLink,
} from "./deep-links"
import { displayName, errorMessage, getDraggableId, syncWorkspaceOrder, workspaceKey } from "./helpers"
import { type Session } from "@opencode-ai/sdk/v2/client"
import { hasProjectPermissions, latestRootSession } from "./helpers"
import {
displayName,
errorMessage,
hasProjectPermissions,
latestRootSession,
syncWorkspaceOrder,
workspaceKey,
} from "./helpers"
const session = (input: Partial<Session> & Pick<Session, "id" | "directory">) =>
({
@@ -192,12 +198,6 @@ describe("layout workspace helpers", () => {
expect(result?.id).toBe("root")
})
test("extracts draggable id safely", () => {
expect(getDraggableId({ draggable: { id: "x" } })).toBe("x")
expect(getDraggableId({ draggable: { id: 42 } })).toBeUndefined()
expect(getDraggableId(null)).toBeUndefined()
})
test("formats fallback project display name", () => {
expect(displayName({ worktree: "/tmp/app" })).toBe("app")
expect(displayName({ worktree: "/tmp/app", name: "My App" })).toBe("My App")
-8
View File
@@ -54,14 +54,6 @@ export const childMapByParent = (sessions: Session[]) => {
return map
}
export 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
}
export const displayName = (project: { name?: string; worktree: string }) =>
project.name || getFilename(project.worktree)
@@ -1,63 +0,0 @@
import { describe, expect, test } from "bun:test"
import { projectSelected, projectTileActive } from "./sidebar-project-helpers"
describe("projectSelected", () => {
test("matches direct worktree", () => {
expect(projectSelected("/tmp/root", "/tmp/root")).toBe(true)
})
test("matches sandbox worktree", () => {
expect(projectSelected("/tmp/branch", "/tmp/root", ["/tmp/branch"])).toBe(true)
expect(projectSelected("/tmp/other", "/tmp/root", ["/tmp/branch"])).toBe(false)
})
})
describe("projectTileActive", () => {
test("menu state always wins", () => {
expect(
projectTileActive({
menu: true,
preview: false,
open: false,
overlay: false,
worktree: "/tmp/root",
}),
).toBe(true)
})
test("preview mode uses open state", () => {
expect(
projectTileActive({
menu: false,
preview: true,
open: true,
overlay: true,
hoverProject: "/tmp/other",
worktree: "/tmp/root",
}),
).toBe(true)
})
test("overlay mode uses hovered project", () => {
expect(
projectTileActive({
menu: false,
preview: false,
open: false,
overlay: true,
hoverProject: "/tmp/root",
worktree: "/tmp/root",
}),
).toBe(true)
expect(
projectTileActive({
menu: false,
preview: false,
open: false,
overlay: true,
hoverProject: "/tmp/other",
worktree: "/tmp/root",
}),
).toBe(false)
})
})
@@ -1,11 +0,0 @@
export const projectSelected = (currentDir: string, worktree: string, sandboxes?: string[]) =>
worktree === currentDir || sandboxes?.includes(currentDir) === true
export const projectTileActive = (args: {
menu: boolean
preview: boolean
open: boolean
overlay: boolean
hoverProject?: string
worktree: string
}) => args.menu || (args.preview ? args.open : args.overlay && args.hoverProject === args.worktree)
@@ -12,7 +12,6 @@ import { useLanguage } from "@/context/language"
import { useNotification } from "@/context/notification"
import { ProjectIcon, SessionItem, type SessionItemProps } from "./sidebar-items"
import { childMapByParent, displayName, sortedRootSessions } from "./helpers"
import { projectSelected, projectTileActive } from "./sidebar-project-helpers"
export type ProjectSidebarContext = {
currentDir: Accessor<string>
@@ -277,8 +276,10 @@ export const SortableProject = (props: {
const globalSync = useGlobalSync()
const language = useLanguage()
const sortable = createSortable(props.project.worktree)
const selected = createMemo(() =>
projectSelected(props.ctx.currentDir(), props.project.worktree, props.project.sandboxes),
const selected = createMemo(
() =>
props.project.worktree === props.ctx.currentDir() ||
props.project.sandboxes?.includes(props.ctx.currentDir()) === true,
)
const workspaces = createMemo(() => props.ctx.workspaceIds(props.project).slice(0, 2))
const workspaceEnabled = createMemo(() => props.ctx.workspacesEnabled(props.project))
@@ -291,15 +292,8 @@ export const SortableProject = (props: {
const preview = createMemo(() => !props.mobile && props.ctx.sidebarOpened())
const overlay = createMemo(() => !props.mobile && !props.ctx.sidebarOpened())
const active = createMemo(() =>
projectTileActive({
menu: state.menu,
preview: preview(),
open: state.open,
overlay: overlay(),
hoverProject: props.ctx.hoverProject(),
worktree: props.project.worktree,
}),
const active = createMemo(
() => state.menu || (preview() ? state.open : overlay() && props.ctx.hoverProject() === props.project.worktree),
)
createEffect(() => {
@@ -1 +0,0 @@
export const sidebarExpanded = (mobile: boolean | undefined, opened: boolean) => !!mobile || opened
@@ -1,13 +0,0 @@
import { describe, expect, test } from "bun:test"
import { sidebarExpanded } from "./sidebar-shell-helpers"
describe("sidebarExpanded", () => {
test("expands on mobile regardless of desktop open state", () => {
expect(sidebarExpanded(true, false)).toBe(true)
})
test("follows desktop open state when not mobile", () => {
expect(sidebarExpanded(false, true)).toBe(true)
expect(sidebarExpanded(false, false)).toBe(false)
})
})
@@ -11,7 +11,6 @@ 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 { sidebarExpanded } from "./sidebar-shell-helpers"
export const SidebarContent = (props: {
mobile?: boolean
@@ -33,7 +32,7 @@ export const SidebarContent = (props: {
onOpenHelp: () => void
renderPanel: () => JSX.Element
}): JSX.Element => {
const expanded = createMemo(() => sidebarExpanded(props.mobile, props.opened()))
const expanded = createMemo(() => !!props.mobile || props.opened())
const placement = () => (props.mobile ? "bottom" : "right")
let panel: HTMLDivElement | undefined
@@ -1,2 +0,0 @@
export const workspaceOpenState = (expanded: Record<string, boolean>, directory: string, local: boolean) =>
expanded[directory] ?? local
@@ -1,13 +0,0 @@
import { describe, expect, test } from "bun:test"
import { workspaceOpenState } from "./sidebar-workspace-helpers"
describe("workspaceOpenState", () => {
test("defaults to local workspace open", () => {
expect(workspaceOpenState({}, "/tmp/root", true)).toBe(true)
})
test("uses persisted expansion state when present", () => {
expect(workspaceOpenState({ "/tmp/root": false }, "/tmp/root", true)).toBe(false)
expect(workspaceOpenState({ "/tmp/branch": true }, "/tmp/branch", false)).toBe(true)
})
})
@@ -144,8 +144,6 @@ const WorkspaceActions = (props: {
setMenuOpen: (open: boolean) => void
setPendingRename: (value: boolean) => void
sidebarHovering: Accessor<boolean>
mobile?: boolean
nav: Accessor<HTMLElement | undefined>
touch: Accessor<boolean>
language: ReturnType<typeof useLanguage>
workspaceValue: Accessor<string>
@@ -340,6 +338,22 @@ export const SortableWorkspace = (props: {
}
const workspaceEditActive = createMemo(() => props.ctx.editorOpen(`workspace:${props.directory}`))
const header = () => (
<WorkspaceHeader
local={local}
busy={busy}
open={open}
directory={props.directory}
language={language}
branch={() => workspaceStore.vcs?.branch}
workspaceValue={workspaceValue}
workspaceEditActive={workspaceEditActive}
InlineEditor={props.ctx.InlineEditor}
renameWorkspace={props.ctx.renameWorkspace}
setEditor={props.ctx.setEditor}
projectId={props.project.id}
/>
)
const openWrapper = (value: boolean) => {
props.ctx.setWorkspaceExpanded(props.directory, value)
@@ -379,20 +393,7 @@ export const SortableWorkspace = (props: {
data-action="workspace-toggle"
data-workspace={base64Encode(props.directory)}
>
<WorkspaceHeader
local={local}
busy={busy}
open={open}
directory={props.directory}
language={language}
branch={() => workspaceStore.vcs?.branch}
workspaceValue={workspaceValue}
workspaceEditActive={workspaceEditActive}
InlineEditor={props.ctx.InlineEditor}
renameWorkspace={props.ctx.renameWorkspace}
setEditor={props.ctx.setEditor}
projectId={props.project.id}
/>
{header()}
</Collapsible.Trigger>
}
>
@@ -401,20 +402,7 @@ export const SortableWorkspace = (props: {
menu.open ? "pr-16" : "pr-2"
} group-hover/workspace:pr-16 group-focus-within/workspace:pr-16`}
>
<WorkspaceHeader
local={local}
busy={busy}
open={open}
directory={props.directory}
language={language}
branch={() => workspaceStore.vcs?.branch}
workspaceValue={workspaceValue}
workspaceEditActive={workspaceEditActive}
InlineEditor={props.ctx.InlineEditor}
renameWorkspace={props.ctx.renameWorkspace}
setEditor={props.ctx.setEditor}
projectId={props.project.id}
/>
{header()}
</div>
</Show>
<WorkspaceActions
@@ -426,8 +414,6 @@ export const SortableWorkspace = (props: {
setMenuOpen={(open) => setMenu("open", open)}
setPendingRename={(value) => setMenu("pendingRename", value)}
sidebarHovering={props.ctx.sidebarHovering}
mobile={props.mobile}
nav={props.ctx.nav}
touch={touch}
language={language}
workspaceValue={workspaceValue}
@@ -490,44 +476,18 @@ export const LocalWorkspace = (props: {
ref={(el) => props.ctx.setScrollContainerRef(el, props.mobile)}
class="size-full flex flex-col py-2 overflow-y-auto no-scrollbar [overflow-anchor:none]"
>
<nav class="flex flex-col gap-1 px-3">
<Show when={loading()}>
<SessionSkeleton />
</Show>
<For each={sessions()}>
{(session) => (
<SessionItem
session={session}
slug={slug()}
mobile={props.mobile}
children={children()}
sidebarExpanded={props.ctx.sidebarExpanded}
sidebarHovering={props.ctx.sidebarHovering}
nav={props.ctx.nav}
hoverSession={props.ctx.hoverSession}
setHoverSession={props.ctx.setHoverSession}
clearHoverProjectSoon={props.ctx.clearHoverProjectSoon}
prefetchSession={props.ctx.prefetchSession}
archiveSession={props.ctx.archiveSession}
/>
)}
</For>
<Show when={hasMore()}>
<div class="relative w-full py-1">
<Button
variant="ghost"
class="flex w-full text-left justify-start text-14-regular text-text-weak pl-9 pr-10"
size="large"
onClick={(e: MouseEvent) => {
loadMore()
;(e.currentTarget as HTMLButtonElement).blur()
}}
>
{language.t("common.loadMore")}
</Button>
</div>
</Show>
</nav>
<WorkspaceSessionList
slug={slug}
mobile={props.mobile}
ctx={props.ctx}
showNew={() => false}
loading={loading}
sessions={sessions}
children={children}
hasMore={hasMore}
loadMore={loadMore}
language={language}
/>
</div>
)
}