diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index f7ba15501..ab2687dca 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -1,4 +1,16 @@ -import { batch, createEffect, createMemo, For, on, onCleanup, onMount, ParentProps, Show, untrack } from "solid-js" +import { + batch, + createEffect, + createMemo, + For, + on, + onCleanup, + onMount, + ParentProps, + Show, + untrack, + type Accessor, +} from "solid-js" import { useNavigate, useParams } from "@solidjs/router" import { useLayout, LocalProject } from "@/context/layout" import { useGlobalSync } from "@/context/global-sync" @@ -135,7 +147,7 @@ export default function Layout(props: ParentProps) { nav: undefined as HTMLElement | undefined, sortNow: Date.now(), sizing: false, - peek: undefined as LocalProject | undefined, + peek: undefined as string | undefined, peeked: false, }) @@ -233,6 +245,12 @@ export default function Layout(props: ParentProps) { return layout.projects.list().find((project) => project.worktree === id) }) + const peekProject = createMemo(() => { + const id = state.peek + if (!id) return + return layout.projects.list().find((project) => project.worktree === id) + }) + createEffect(() => { const p = hoverProjectData() if (p) { @@ -240,7 +258,7 @@ export default function Layout(props: ParentProps) { clearTimeout(peekt) peekt = undefined } - setState("peek", p) + setState("peek", p.worktree) setState("peeked", true) return } @@ -1932,17 +1950,32 @@ export default function Layout(props: ParentProps) { setHoverSession, } - const SidebarPanel = (panelProps: { project: LocalProject | undefined; mobile?: boolean; merged?: boolean }) => { + const SidebarPanel = (panelProps: { + project: Accessor + mobile?: boolean + merged?: boolean + }) => { + const project = panelProps.project const merged = createMemo(() => panelProps.mobile || (panelProps.merged ?? layout.sidebar.opened())) const hover = createMemo(() => !panelProps.mobile && panelProps.merged === false && !layout.sidebar.opened()) const popover = createMemo(() => !!panelProps.mobile || panelProps.merged === false || layout.sidebar.opened()) const projectName = createMemo(() => { - const project = panelProps.project - if (!project) return "" - return project.name || getFilename(project.worktree) + const item = project() + if (!item) return "" + return item.name || getFilename(item.worktree) + }) + const projectId = createMemo(() => project()?.id ?? "") + const worktree = createMemo(() => project()?.worktree ?? "") + const slug = createMemo(() => { + const dir = worktree() + if (!dir) return "" + return base64Encode(dir) + }) + const workspaces = createMemo(() => { + const item = project() + if (!item) return [] as string[] + return workspaceIds(item) }) - const projectId = createMemo(() => panelProps.project?.id ?? "") - const workspaces = createMemo(() => workspaceIds(panelProps.project)) const unseenCount = createMemo(() => workspaces().reduce((total, directory) => total + notification.project.unseenCount(directory), 0), ) @@ -1951,10 +1984,15 @@ export default function Layout(props: ParentProps) { .filter((directory) => notification.project.unseenCount(directory) > 0) .forEach((directory) => notification.project.markViewed(directory)) const workspacesEnabled = createMemo(() => { - const project = panelProps.project - if (!project) return false - if (project.vcs !== "git") return false - return layout.sidebar.workspaces(project.worktree)() + const item = project() + if (!item) return false + if (item.vcs !== "git") return false + return layout.sidebar.workspaces(item.worktree)() + }) + const canToggle = createMemo(() => { + const item = project() + if (!item) return false + return item.vcs === "git" || layout.sidebar.workspaces(item.worktree)() }) const homedir = createMemo(() => globalSync.data.path.home) @@ -1973,168 +2011,197 @@ export default function Layout(props: ParentProps) { width: panelProps.mobile ? undefined : `${Math.max(Math.max(layout.sidebar.width(), 244) - 64, 0)}px`, }} > - - {(p) => ( - <> -
-
-
- renameProject(p(), next)} - class="text-14-medium text-text-strong truncate" - displayClass="text-14-medium text-text-strong truncate" - stopPropagation - /> + + <> +
+
+
+ { + const item = project() + if (!item) return + renameProject(item, next) + }} + class="text-14-medium text-text-strong truncate" + displayClass="text-14-medium text-text-strong truncate" + stopPropagation + /> - - - {p().worktree.replace(homedir(), "~")} - - -
- - - - - - showEditProjectDialog(p())}> - {language.t("common.edit")} - - toggleProjectWorkspaces(p())} - > - - {layout.sidebar.workspaces(p().worktree)() - ? language.t("sidebar.workspaces.disable") - : language.t("sidebar.workspaces.enable")} - - - - - {language.t("sidebar.project.clearNotifications")} - - - - closeProject(p().worktree)} - > - {language.t("common.close")} - - - - + + + {worktree().replace(homedir(), "~")} + +
-
-
- -
- -
-
- -
- - } - > + + + + + { + const item = project() + if (!item) return + showEditProjectDialog(item) + }} + > + {language.t("common.edit")} + + { + const item = project() + if (!item) return + toggleProjectWorkspaces(item) + }} + > + + {workspacesEnabled() + ? language.t("sidebar.workspaces.disable") + : language.t("sidebar.workspaces.enable")} + + + + + {language.t("sidebar.project.clearNotifications")} + + + + { + const dir = worktree() + if (!dir) return + closeProject(dir) + }} + > + {language.t("common.close")} + + + + +
+
+ +
+
-
-
- - - -
{ - if (!panelProps.mobile) scrollContainerRef = el - }} - class="size-full flex flex-col py-2 gap-4 overflow-y-auto no-scrollbar [overflow-anchor:none]" - > - - - {(directory) => ( - - )} - - -
- - store.activeWorkspace} - workspaceLabel={workspaceLabel} - /> - -
+
+
- -
- - )} + } + > + <> +
+ +
+
+ + + +
{ + if (!panelProps.mobile) scrollContainerRef = el + }} + class="size-full flex flex-col py-2 gap-4 overflow-y-auto no-scrollbar [overflow-anchor:none]" + > + + + {(directory) => ( + + )} + + +
+ + store.activeWorkspace} + workspaceLabel={workspaceLabel} + /> + +
+
+ +
+
+
platform.openLink("https://opencode.ai/desktop-feedback")} renderPanel={() => mobile ? ( - + ) : ( - + ) } @@ -2325,8 +2392,8 @@ export default function Layout(props: ParentProps) { arm() }} > - - + +