diff options
| author | adamelmore <[email protected]> | 2026-01-26 10:04:59 -0600 |
|---|---|---|
| committer | adamelmore <[email protected]> | 2026-01-26 11:26:17 -0600 |
| commit | d05ed5ca83e03904c7c3dda23a6dcccfd607bdce (patch) | |
| tree | 1afcb055bcedf8b477472f0b25432b318a95f53b /packages/app/src/pages | |
| parent | 37f1a1a4ef36eacb60ad5493db8aeb1130c5fa91 (diff) | |
| download | opencode-d05ed5ca83e03904c7c3dda23a6dcccfd607bdce.tar.gz opencode-d05ed5ca83e03904c7c3dda23a6dcccfd607bdce.zip | |
chore(app): createStore over signals
Diffstat (limited to 'packages/app/src/pages')
| -rw-r--r-- | packages/app/src/pages/layout.tsx | 147 | ||||
| -rw-r--r-- | packages/app/src/pages/session.tsx | 99 |
2 files changed, 147 insertions, 99 deletions
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 7ad97a989..fd6f6e527 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -91,7 +91,6 @@ export default function Layout(props: ParentProps) { let scrollContainerRef: HTMLDivElement | undefined const params = useParams() - const [autoselect, setAutoselect] = createSignal(!params.dir) const globalSDK = useGlobalSDK() const globalSync = useGlobalSync() const layout = useLayout() @@ -117,27 +116,31 @@ export default function Layout(props: ParentProps) { } const colorSchemeLabel = (scheme: ColorScheme) => language.t(colorSchemeKey[scheme]) + const [state, setState] = createStore({ + autoselect: !params.dir, + busyWorkspaces: new Set<string>(), + hoverSession: undefined as string | undefined, + hoverProject: undefined as string | undefined, + scrollSessionKey: undefined as string | undefined, + nav: undefined as HTMLElement | undefined, + }) + const [editor, setEditor] = createStore({ active: "" as string, value: "", }) - const [busyWorkspaces, setBusyWorkspaces] = createSignal<Set<string>>(new Set()) const setBusy = (directory: string, value: boolean) => { const key = workspaceKey(directory) - setBusyWorkspaces((prev) => { + setState("busyWorkspaces", (prev) => { const next = new Set(prev) if (value) next.add(key) else next.delete(key) return next }) } - const isBusy = (directory: string) => busyWorkspaces().has(workspaceKey(directory)) + const isBusy = (directory: string) => state.busyWorkspaces.has(workspaceKey(directory)) const editorRef = { current: undefined as HTMLInputElement | undefined } - const [hoverSession, setHoverSession] = createSignal<string | undefined>() - const [hoverProject, setHoverProject] = createSignal<string | undefined>() - - const [nav, setNav] = createSignal<HTMLElement | undefined>(undefined) const navLeave = { current: undefined as number | undefined } onCleanup(() => { @@ -145,18 +148,18 @@ export default function Layout(props: ParentProps) { clearTimeout(navLeave.current) }) - const sidebarHovering = createMemo(() => !layout.sidebar.opened() && hoverProject() !== undefined) + const sidebarHovering = createMemo(() => !layout.sidebar.opened() && state.hoverProject !== undefined) const sidebarExpanded = createMemo(() => layout.sidebar.opened() || sidebarHovering()) const hoverProjectData = createMemo(() => { - const id = hoverProject() + const id = state.hoverProject if (!id) return return layout.projects.list().find((project) => project.worktree === id) }) createEffect(() => { if (!layout.sidebar.opened()) return - setHoverProject(undefined) + setState("hoverProject", undefined) }) createEffect( @@ -164,9 +167,9 @@ export default function Layout(props: ParentProps) { () => ({ dir: params.dir, id: params.id }), () => { if (layout.sidebar.opened()) return - if (!hoverProject()) return - setHoverSession(undefined) - setHoverProject(undefined) + if (!state.hoverProject) return + setState("hoverSession", undefined) + setState("hoverProject", undefined) }, { defer: true }, ), @@ -175,7 +178,7 @@ export default function Layout(props: ParentProps) { const autoselecting = createMemo(() => { if (params.dir) return false if (initialDir) return false - if (!autoselect()) return false + if (!state.autoselect) return false if (!pageReady()) return true if (!layoutReady()) return true const list = layout.projects.list() @@ -483,20 +486,18 @@ export default function Layout(props: ParentProps) { } } - const [scrollSessionKey, setScrollSessionKey] = createSignal<string | undefined>(undefined) - function scrollToSession(sessionId: string, sessionKey: string) { if (!scrollContainerRef) return - if (scrollSessionKey() === sessionKey) return + if (state.scrollSessionKey === sessionKey) return const element = scrollContainerRef.querySelector(`[data-session-id="${sessionId}"]`) if (!element) return const containerRect = scrollContainerRef.getBoundingClientRect() const elementRect = element.getBoundingClientRect() if (elementRect.top >= containerRect.top && elementRect.bottom <= containerRect.bottom) { - setScrollSessionKey(sessionKey) + setState("scrollSessionKey", sessionKey) return } - setScrollSessionKey(sessionKey) + setState("scrollSessionKey", sessionKey) element.scrollIntoView({ block: "nearest", behavior: "smooth" }) } @@ -544,7 +545,7 @@ export default function Layout(props: ParentProps) { (value) => { if (!value.ready) return if (!value.layoutReady) return - if (!autoselect()) return + if (!state.autoselect) return if (initialDir) return if (value.dir) return if (value.list.length === 0) return @@ -552,7 +553,7 @@ export default function Layout(props: ParentProps) { const last = server.projects.last() const next = value.list.find((project) => project.worktree === last) ?? value.list[0] if (!next) return - setAutoselect(false) + setState("autoselect", false) openProject(next.worktree, false) navigateToProject(next.worktree) }, @@ -1066,8 +1067,8 @@ export default function Layout(props: ParentProps) { function navigateToProject(directory: string | undefined) { if (!directory) return if (!layout.sidebar.opened()) { - setHoverSession(undefined) - setHoverProject(undefined) + setState("hoverSession", undefined) + setState("hoverProject", undefined) } server.projects.touch(directory) const lastSession = store.lastSession[directory] @@ -1078,8 +1079,8 @@ export default function Layout(props: ParentProps) { function navigateToSession(session: Session | undefined) { if (!session) return if (!layout.sidebar.opened()) { - setHoverSession(undefined) - setHoverProject(undefined) + setState("hoverSession", undefined) + setState("hoverProject", undefined) } navigate(`/${base64Encode(session.directory)}/session/${session.id}`) layout.mobileSidebar.hide() @@ -1472,7 +1473,7 @@ export default function Layout(props: ParentProps) { function handleDragStart(event: unknown) { const id = getDraggableId(event) if (!id) return - setHoverProject(undefined) + setState("hoverProject", undefined) setStore("activeProject", id) } @@ -1632,8 +1633,10 @@ export default function Layout(props: ParentProps) { const hoverAllowed = createMemo(() => !props.mobile && sidebarExpanded()) const hoverEnabled = createMemo(() => (props.popover ?? true) && hoverAllowed()) const isActive = createMemo(() => props.session.id === params.id) - const [menuOpen, setMenuOpen] = createSignal(false) - const [pendingRename, setPendingRename] = createSignal(false) + const [menu, setMenu] = createStore({ + open: false, + pendingRename: false, + }) const messageLabel = (message: Message) => { const parts = sessionStore.part[message.id] ?? [] @@ -1644,13 +1647,13 @@ export default function Layout(props: ParentProps) { const item = ( <A href={`${props.slug}/session/${props.session.id}`} - class={`flex items-center justify-between gap-3 min-w-0 text-left w-full focus:outline-none transition-[padding] ${menuOpen() ? "pr-7" : ""} group-hover/session:pr-7 group-focus-within/session:pr-7 group-active/session:pr-7 ${props.dense ? "py-0.5" : "py-1"}`} + class={`flex items-center justify-between gap-3 min-w-0 text-left w-full focus:outline-none transition-[padding] ${menu.open ? "pr-7" : ""} group-hover/session:pr-7 group-focus-within/session:pr-7 group-active/session:pr-7 ${props.dense ? "py-0.5" : "py-1"}`} onMouseEnter={() => prefetchSession(props.session, "high")} onFocus={() => prefetchSession(props.session, "high")} onClick={() => { - setHoverSession(undefined) + setState("hoverSession", undefined) if (layout.sidebar.opened()) return - queueMicrotask(() => setHoverProject(undefined)) + queueMicrotask(() => setState("hoverProject", undefined)) }} > <div class="flex items-center gap-1 w-full"> @@ -1713,9 +1716,9 @@ export default function Layout(props: ParentProps) { gutter={16} shift={-2} trigger={item} - mount={!props.mobile ? nav() : undefined} - open={hoverSession() === props.session.id} - onOpenChange={(open) => setHoverSession(open ? props.session.id : undefined)} + mount={!props.mobile ? state.nav : undefined} + open={state.hoverSession === props.session.id} + onOpenChange={(open) => setState("hoverSession", open ? props.session.id : undefined)} > <Show when={hoverReady()} @@ -1745,13 +1748,13 @@ export default function Layout(props: ParentProps) { <div class={`absolute ${props.dense ? "top-0.5 right-0.5" : "top-1 right-1"} flex items-center gap-0.5 transition-opacity`} classList={{ - "opacity-100 pointer-events-auto": menuOpen(), - "opacity-0 pointer-events-none": !menuOpen(), + "opacity-100 pointer-events-auto": menu.open, + "opacity-0 pointer-events-none": !menu.open, "group-hover/session:opacity-100 group-hover/session:pointer-events-auto": true, "group-focus-within/session:opacity-100 group-focus-within/session:pointer-events-auto": true, }} > - <DropdownMenu modal={!sidebarHovering()} open={menuOpen()} onOpenChange={setMenuOpen}> + <DropdownMenu modal={!sidebarHovering()} open={menu.open} onOpenChange={(open) => setMenu("open", open)}> <Tooltip value={language.t("common.moreOptions")} placement="top"> <DropdownMenu.Trigger as={IconButton} @@ -1761,19 +1764,19 @@ export default function Layout(props: ParentProps) { aria-label={language.t("common.moreOptions")} /> </Tooltip> - <DropdownMenu.Portal mount={!props.mobile ? nav() : undefined}> + <DropdownMenu.Portal mount={!props.mobile ? state.nav : undefined}> <DropdownMenu.Content onCloseAutoFocus={(event) => { - if (!pendingRename()) return + if (!menu.pendingRename) return event.preventDefault() - setPendingRename(false) + setMenu("pendingRename", false) openEditor(`session:${props.session.id}`, props.session.title) }} > <DropdownMenu.Item onSelect={() => { - setPendingRename(true) - setMenuOpen(false) + setMenu("pendingRename", true) + setMenu("open", false) }} > <DropdownMenu.ItemLabel>{language.t("common.rename")}</DropdownMenu.ItemLabel> @@ -1802,9 +1805,9 @@ export default function Layout(props: ParentProps) { end class={`flex items-center justify-between gap-3 min-w-0 text-left w-full focus:outline-none ${props.dense ? "py-0.5" : "py-1"}`} onClick={() => { - setHoverSession(undefined) + setState("hoverSession", undefined) if (layout.sidebar.opened()) return - queueMicrotask(() => setHoverProject(undefined)) + queueMicrotask(() => setState("hoverProject", undefined)) }} > <div class="flex items-center gap-1 w-full"> @@ -1884,8 +1887,10 @@ export default function Layout(props: ParentProps) { const SortableWorkspace = (props: { directory: string; project: LocalProject; mobile?: boolean }): JSX.Element => { const sortable = createSortable(props.directory) const [workspaceStore, setWorkspaceStore] = globalSync.child(props.directory, { bootstrap: false }) - const [menuOpen, setMenuOpen] = createSignal(false) - const [pendingRename, setPendingRename] = createSignal(false) + const [menu, setMenu] = createStore({ + open: false, + pendingRename: false, + }) const slug = createMemo(() => base64Encode(props.directory)) const sessions = createMemo(() => workspaceStore.session @@ -1995,13 +2000,17 @@ export default function Layout(props: ParentProps) { <div class="absolute right-1 top-1/2 -translate-y-1/2 flex items-center gap-0.5 transition-opacity" classList={{ - "opacity-100 pointer-events-auto": menuOpen(), - "opacity-0 pointer-events-none": !menuOpen(), + "opacity-100 pointer-events-auto": menu.open, + "opacity-0 pointer-events-none": !menu.open, "group-hover/workspace:opacity-100 group-hover/workspace:pointer-events-auto": true, "group-focus-within/workspace:opacity-100 group-focus-within/workspace:pointer-events-auto": true, }} > - <DropdownMenu modal={!sidebarHovering()} open={menuOpen()} onOpenChange={setMenuOpen}> + <DropdownMenu + modal={!sidebarHovering()} + open={menu.open} + onOpenChange={(open) => setMenu("open", open)} + > <Tooltip value={language.t("common.moreOptions")} placement="top"> <DropdownMenu.Trigger as={IconButton} @@ -2011,20 +2020,20 @@ export default function Layout(props: ParentProps) { aria-label={language.t("common.moreOptions")} /> </Tooltip> - <DropdownMenu.Portal mount={!props.mobile ? nav() : undefined}> + <DropdownMenu.Portal mount={!props.mobile ? state.nav : undefined}> <DropdownMenu.Content onCloseAutoFocus={(event) => { - if (!pendingRename()) return + if (!menu.pendingRename) return event.preventDefault() - setPendingRename(false) + setMenu("pendingRename", false) openEditor(`workspace:${props.directory}`, workspaceValue()) }} > <DropdownMenu.Item disabled={local()} onSelect={() => { - setPendingRename(true) - setMenuOpen(false) + setMenu("pendingRename", true) + setMenu("open", false) }} > <DropdownMenu.ItemLabel>{language.t("common.rename")}</DropdownMenu.ItemLabel> @@ -2103,7 +2112,7 @@ export default function Layout(props: ParentProps) { const preview = createMemo(() => !props.mobile && layout.sidebar.opened()) const overlay = createMemo(() => !props.mobile && !layout.sidebar.opened()) - const active = createMemo(() => (preview() ? open() : overlay() && hoverProject() === props.project.worktree)) + const active = createMemo(() => (preview() ? open() : overlay() && state.hoverProject === props.project.worktree)) createEffect(() => { if (preview()) return @@ -2155,14 +2164,14 @@ export default function Layout(props: ParentProps) { onMouseEnter={() => { if (!overlay()) return globalSync.child(props.project.worktree) - setHoverProject(props.project.worktree) - setHoverSession(undefined) + setState("hoverProject", props.project.worktree) + setState("hoverSession", undefined) }} onFocus={() => { if (!overlay()) return globalSync.child(props.project.worktree) - setHoverProject(props.project.worktree) - setHoverSession(undefined) + setState("hoverProject", props.project.worktree) + setState("hoverSession", undefined) }} onClick={() => navigateToProject(props.project.worktree)} onBlur={() => setOpen(false)} @@ -2184,7 +2193,7 @@ export default function Layout(props: ParentProps) { trigger={trigger} onOpenChange={(value) => { setOpen(value) - if (value) setHoverSession(undefined) + if (value) setState("hoverSession", undefined) }} > <div class="-m-3 p-2 flex flex-col w-72"> @@ -2323,8 +2332,8 @@ export default function Layout(props: ParentProps) { const createWorkspace = async (project: LocalProject) => { if (!layout.sidebar.opened()) { - setHoverSession(undefined) - setHoverProject(undefined) + setState("hoverSession", undefined) + setState("hoverProject", undefined) } const created = await globalSDK.client.worktree .create({ directory: project.worktree }) @@ -2427,7 +2436,7 @@ export default function Layout(props: ParentProps) { class="shrink-0 size-6 rounded-md opacity-0 group-hover/project:opacity-100 data-[expanded]:opacity-100 data-[expanded]:bg-surface-base-active" aria-label={language.t("common.moreOptions")} /> - <DropdownMenu.Portal mount={!panelProps.mobile ? nav() : undefined}> + <DropdownMenu.Portal mount={!panelProps.mobile ? state.nav : undefined}> <DropdownMenu.Content class="mt-1"> <DropdownMenu.Item onSelect={() => dialog.show(() => <DialogEditProject project={p} />)}> <DropdownMenu.ItemLabel>{language.t("common.edit")}</DropdownMenu.ItemLabel> @@ -2476,8 +2485,8 @@ export default function Layout(props: ParentProps) { class="w-full" onClick={() => { if (!layout.sidebar.opened()) { - setHoverSession(undefined) - setHoverProject(undefined) + setState("hoverSession", undefined) + setState("hoverProject", undefined) } navigate(`/${base64Encode(p.worktree)}/session`) layout.mobileSidebar.hide() @@ -2668,7 +2677,7 @@ export default function Layout(props: ParentProps) { }} style={{ width: layout.sidebar.opened() ? `${Math.max(layout.sidebar.width(), 244)}px` : "64px" }} ref={(el) => { - setNav(el) + setState("nav", el) }} onMouseEnter={() => { if (navLeave.current === undefined) return @@ -2681,8 +2690,8 @@ export default function Layout(props: ParentProps) { if (navLeave.current !== undefined) clearTimeout(navLeave.current) navLeave.current = window.setTimeout(() => { navLeave.current = undefined - setHoverProject(undefined) - setHoverSession(undefined) + setState("hoverProject", undefined) + setState("hoverSession", undefined) }, 300) }} > diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 458decfc4..e9b29c03e 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -1,4 +1,4 @@ -import { For, onCleanup, onMount, Show, Match, Switch, createMemo, createEffect, on, createSignal } from "solid-js" +import { For, onCleanup, onMount, Show, Match, Switch, createMemo, createEffect, on } from "solid-js" import { createMediaQuery } from "@solid-primitives/media" import { createResizeObserver } from "@solid-primitives/resize-observer" import { Dynamic } from "solid-js/web" @@ -198,12 +198,17 @@ export default function Page() { return next }) - const [responding, setResponding] = createSignal(false) + const [ui, setUi] = createStore({ + responding: false, + pendingMessage: undefined as string | undefined, + scrollGesture: 0, + autoCreated: false, + }) createEffect( on( () => request()?.id, - () => setResponding(false), + () => setUi("responding", false), { defer: true }, ), ) @@ -211,18 +216,17 @@ export default function Page() { const decide = (response: "once" | "always" | "reject") => { const perm = request() if (!perm) return - if (responding()) return + if (ui.responding) return - setResponding(true) + setUi("responding", true) sdk.client.permission .respond({ sessionID: perm.sessionID, permissionID: perm.id, response }) .catch((err: unknown) => { const message = err instanceof Error ? err.message : String(err) showToast({ title: language.t("common.requestFailed"), description: message }) }) - .finally(() => setResponding(false)) + .finally(() => setUi("responding", false)) } - const [pendingMessage, setPendingMessage] = createSignal<string | undefined>(undefined) const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) const tabs = createMemo(() => layout.tabs(sessionKey)) const view = createMemo(() => layout.view(sessionKey)) @@ -439,7 +443,6 @@ export default function Page() { let promptDock: HTMLDivElement | undefined let scroller: HTMLDivElement | undefined - const [scrollGesture, setScrollGesture] = createSignal(0) const scrollGestureWindowMs = 250 const markScrollGesture = (target?: EventTarget | null) => { @@ -450,26 +453,24 @@ export default function Page() { const nested = el?.closest("[data-scrollable]") if (nested && nested !== root) return - setScrollGesture(Date.now()) + setUi("scrollGesture", Date.now()) } - const hasScrollGesture = () => Date.now() - scrollGesture() < scrollGestureWindowMs + const hasScrollGesture = () => Date.now() - ui.scrollGesture < scrollGestureWindowMs createEffect(() => { if (!params.id) return sync.session.sync(params.id) }) - const [autoCreated, setAutoCreated] = createSignal(false) - createEffect(() => { if (!view().terminal.opened()) { - setAutoCreated(false) + setUi("autoCreated", false) return } - if (!terminal.ready() || terminal.all().length !== 0 || autoCreated()) return + if (!terminal.ready() || terminal.all().length !== 0 || ui.autoCreated) return terminal.new() - setAutoCreated(true) + setUi("autoCreated", true) }) createEffect( @@ -1019,9 +1020,18 @@ export default function Page() { const showTabs = createMemo(() => view().reviewPanel.opened()) - const [fileTreeTab, setFileTreeTab] = createSignal<"changes" | "all">("changes") - const [reviewScroll, setReviewScroll] = createSignal<HTMLDivElement | undefined>(undefined) - const [pendingDiff, setPendingDiff] = createSignal<string | undefined>(undefined) + const [tree, setTree] = createStore({ + fileTreeTab: "changes" as "changes" | "all", + reviewScroll: undefined as HTMLDivElement | undefined, + pendingDiff: undefined as string | undefined, + }) + + const fileTreeTab = () => tree.fileTreeTab + const setFileTreeTab = (value: "changes" | "all") => setTree("fileTreeTab", value) + const reviewScroll = () => tree.reviewScroll + const setReviewScroll = (value: HTMLDivElement | undefined) => setTree("reviewScroll", value) + const pendingDiff = () => tree.pendingDiff + const setPendingDiff = (value: string | undefined) => setTree("pendingDiff", value) createEffect(() => { if (!layout.fileTree.opened()) return @@ -1316,7 +1326,7 @@ export default function Page() { if (pendingSessionID !== sessionID) return sessionStorage.removeItem("opencode.pendingMessage") - setPendingMessage(messageID) + setUi("pendingMessage", messageID) }) const scrollToElement = (el: HTMLElement, behavior: ScrollBehavior) => { @@ -1484,7 +1494,7 @@ export default function Page() { store.turnStart const targetId = - pendingMessage() ?? + ui.pendingMessage ?? (() => { const hash = window.location.hash.slice(1) const match = hash.match(/^message-(.+)$/) @@ -1496,7 +1506,7 @@ export default function Page() { const msg = visibleUserMessages().find((m) => m.id === targetId) if (!msg) return - if (pendingMessage() === targetId) setPendingMessage(undefined) + if (ui.pendingMessage === targetId) setUi("pendingMessage", undefined) requestAnimationFrame(() => scrollToMessage(msg, "auto")) }) @@ -1877,18 +1887,18 @@ export default function Page() { </BasicTool> <div data-component="permission-prompt"> <div data-slot="permission-actions"> - <Button variant="ghost" size="small" onClick={() => decide("reject")} disabled={responding()}> + <Button variant="ghost" size="small" onClick={() => decide("reject")} disabled={ui.responding}> {language.t("ui.permission.deny")} </Button> <Button variant="secondary" size="small" onClick={() => decide("always")} - disabled={responding()} + disabled={ui.responding} > {language.t("ui.permission.allowAlways")} </Button> - <Button variant="primary" size="small" onClick={() => decide("once")} disabled={responding()}> + <Button variant="primary" size="small" onClick={() => decide("once")} disabled={ui.responding}> {language.t("ui.permission.allowOnce")} </Button> </div> @@ -2144,11 +2154,40 @@ export default function Page() { const commentedLines = createMemo(() => fileComments().map((comment) => comment.selection)) - const [openedComment, setOpenedComment] = createSignal<string | null>(null) - const [commenting, setCommenting] = createSignal<SelectedLineRange | null>(null) - const [draft, setDraft] = createSignal("") - const [positions, setPositions] = createSignal<Record<string, number>>({}) - const [draftTop, setDraftTop] = createSignal<number | undefined>(undefined) + const [note, setNote] = createStore({ + openedComment: null as string | null, + commenting: null as SelectedLineRange | null, + draft: "", + positions: {} as Record<string, number>, + draftTop: undefined as number | undefined, + }) + + const openedComment = () => note.openedComment + const setOpenedComment = ( + value: + | typeof note.openedComment + | ((value: typeof note.openedComment) => typeof note.openedComment), + ) => setNote("openedComment", value) + + const commenting = () => note.commenting + const setCommenting = ( + value: typeof note.commenting | ((value: typeof note.commenting) => typeof note.commenting), + ) => setNote("commenting", value) + + const draft = () => note.draft + const setDraft = ( + value: typeof note.draft | ((value: typeof note.draft) => typeof note.draft), + ) => setNote("draft", value) + + const positions = () => note.positions + const setPositions = ( + value: typeof note.positions | ((value: typeof note.positions) => typeof note.positions), + ) => setNote("positions", value) + + const draftTop = () => note.draftTop + const setDraftTop = ( + value: typeof note.draftTop | ((value: typeof note.draftTop) => typeof note.draftTop), + ) => setNote("draftTop", value) const commentLabel = (range: SelectedLineRange) => { const start = Math.min(range.start, range.end) @@ -2695,7 +2734,7 @@ export default function Page() { terminal={pty} onClose={() => { view().terminal.close() - setAutoCreated(false) + setUi("autoCreated", false) }} /> )} |
