summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam <[email protected]>2025-12-24 08:55:24 -0600
committerAdam <[email protected]>2025-12-24 08:55:32 -0600
commit08a075df61b8bf917bc3cc9dfd565e63b6ad9bfc (patch)
tree820d6469244028dd8cff3fdfbcefb40c889309b0
parenta2e8737114626563be92d41025d4b1f2cf0ab695 (diff)
downloadopencode-08a075df61b8bf917bc3cc9dfd565e63b6ad9bfc.tar.gz
opencode-08a075df61b8bf917bc3cc9dfd565e63b6ad9bfc.zip
fix(desktop): better session navigation, hide child sessions
-rw-r--r--packages/app/src/pages/layout.tsx74
1 files changed, 12 insertions, 62 deletions
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx
index 03ac27d9a..838b8ee94 100644
--- a/packages/app/src/pages/layout.tsx
+++ b/packages/app/src/pages/layout.tsx
@@ -129,40 +129,18 @@ export default function Layout(props: ParentProps) {
return bUpdated - aUpdated
}
- function flattenSessions(sessions: Session[]): Session[] {
- const childrenMap = new Map<string, Session[]>()
- for (const session of sessions) {
- if (session.parentID) {
- const children = childrenMap.get(session.parentID) ?? []
- children.push(session)
- childrenMap.set(session.parentID, children)
- }
- }
- const result: Session[] = []
- function visit(session: Session) {
- result.push(session)
- for (const child of childrenMap.get(session.id) ?? []) {
- visit(child)
- }
- }
- for (const session of sessions) {
- if (!session.parentID) visit(session)
- }
- return result
- }
-
function scrollToSession(sessionId: string) {
if (!scrollContainerRef) return
const element = scrollContainerRef.querySelector(`[data-session-id="${sessionId}"]`)
if (element) {
- element.scrollIntoView({ block: "center", behavior: "smooth" })
+ element.scrollIntoView({ block: "nearest", behavior: "smooth" })
}
}
function projectSessions(directory: string) {
if (!directory) return []
const sessions = globalSync.child(directory)[0].session.toSorted(sortSessions)
- return flattenSessions(sessions ?? [])
+ return (sessions ?? []).filter((s) => !s.parentID)
}
const currentSessions = createMemo(() => {
@@ -342,8 +320,11 @@ export default function Layout(props: ParentProps) {
createEffect(() => {
if (!params.dir || !params.id) return
const directory = base64Decode(params.dir)
- setStore("lastSession", directory, params.id)
- notification.session.markViewed(params.id)
+ const id = params.id
+ setStore("lastSession", directory, id)
+ notification.session.markViewed(id)
+ layout.projects.expand(directory)
+ requestAnimationFrame(() => scrollToSession(id))
})
createEffect(() => {
@@ -466,13 +447,9 @@ export default function Layout(props: ParentProps) {
session: Session
slug: string
project: LocalProject
- depth?: number
- childrenMap: Map<string, Session[]>
mobile?: boolean
}): JSX.Element => {
const notification = useNotification()
- const depth = props.depth ?? 0
- const children = createMemo(() => props.childrenMap.get(props.session.id) ?? [])
const updated = createMemo(() => DateTime.fromMillis(props.session.time.updated))
const notifications = createMemo(() => notification.session.unseen(props.session.id))
const hasError = createMemo(() => notifications().some((n) => n.type === "error"))
@@ -487,7 +464,7 @@ export default function Layout(props: ParentProps) {
data-session-id={props.session.id}
class="group/session relative w-full pr-2 py-1 rounded-md cursor-default transition-colors
hover:bg-surface-raised-base-hover focus-within:bg-surface-raised-base-hover has-[.active]:bg-surface-raised-base-hover"
- style={{ "padding-left": `${16 + depth * 12}px` }}
+ style={{ "padding-left": "16px" }}
>
<Tooltip placement={props.mobile ? "bottom" : "right"} value={props.session.title} gutter={10}>
<A
@@ -541,18 +518,6 @@ export default function Layout(props: ParentProps) {
</Tooltip>
</div>
</div>
- <For each={children()}>
- {(child) => (
- <SessionItem
- session={child}
- slug={props.slug}
- project={props.project}
- depth={depth + 1}
- childrenMap={props.childrenMap}
- mobile={props.mobile}
- />
- )}
- </For>
</>
)
}
@@ -565,17 +530,6 @@ export default function Layout(props: ParentProps) {
const [store, setProjectStore] = globalSync.child(props.project.worktree)
const sessions = createMemo(() => store.session.toSorted(sortSessions))
const rootSessions = createMemo(() => sessions().filter((s) => !s.parentID))
- const childSessionsByParent = createMemo(() => {
- const map = new Map<string, Session[]>()
- for (const session of sessions()) {
- if (session.parentID) {
- const children = map.get(session.parentID) ?? []
- children.push(session)
- map.set(session.parentID, children)
- }
- }
- return map
- })
const hasMoreSessions = createMemo(() => store.session.length >= store.limit)
const loadMoreSessions = async () => {
setProjectStore("limit", (limit) => limit + 5)
@@ -633,13 +587,7 @@ export default function Layout(props: ParentProps) {
<nav class="hidden @[4rem]:flex w-full flex-col gap-1.5">
<For each={rootSessions()}>
{(session) => (
- <SessionItem
- session={session}
- slug={slug()}
- project={props.project}
- childrenMap={childSessionsByParent()}
- mobile={props.mobile}
- />
+ <SessionItem session={session} slug={slug()} project={props.project} mobile={props.mobile} />
)}
</For>
<Show when={rootSessions().length === 0}>
@@ -761,7 +709,9 @@ export default function Layout(props: ParentProps) {
<DragDropSensors />
<ConstrainDragXAxis />
<div
- ref={sidebarProps.mobile ? undefined : scrollContainerRef}
+ ref={(el) => {
+ if (!sidebarProps.mobile) scrollContainerRef = el
+ }}
class="w-full min-w-8 flex flex-col gap-2 min-h-0 overflow-y-auto no-scrollbar"
>
<SortableProvider ids={layout.projects.list().map((p) => p.worktree)}>