diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx index 4ccab98e3ff..4869503baa0 100644 --- a/packages/app/src/context/layout.tsx +++ b/packages/app/src/context/layout.tsx @@ -29,6 +29,8 @@ type SessionTabs = { export type LocalProject = Partial & { worktree: string; expanded: boolean } +export type ExpandedSessions = Record + export const { use: useLayout, provider: LayoutProvider } = createSimpleContext({ name: "Layout", init: () => { @@ -53,6 +55,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( width: 600, }, sessionTabs: {} as Record, + expandedSessions: {} as ExpandedSessions, }), ) @@ -184,6 +187,33 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( } }, }, + sessions: { + expanded: createMemo(() => store.expandedSessions ?? {}), + isExpanded(sessionID: string) { + return store.expandedSessions?.[sessionID] ?? false + }, + expand(sessionID: string) { + if (!store.expandedSessions) { + setStore("expandedSessions", { [sessionID]: true }) + } else { + setStore("expandedSessions", sessionID, true) + } + }, + collapse(sessionID: string) { + if (!store.expandedSessions) { + setStore("expandedSessions", { [sessionID]: false }) + } else { + setStore("expandedSessions", sessionID, false) + } + }, + toggle(sessionID: string) { + if (!store.expandedSessions) { + setStore("expandedSessions", { [sessionID]: true }) + } else { + setStore("expandedSessions", sessionID, !store.expandedSessions[sessionID]) + } + }, + }, tabs(sessionKey: string) { const tabs = createMemo(() => store.sessionTabs[sessionKey] ?? { all: [] }) return { diff --git a/packages/app/src/context/local.tsx b/packages/app/src/context/local.tsx index 49217b82be8..7703de621ee 100644 --- a/packages/app/src/context/local.tsx +++ b/packages/app/src/context/local.tsx @@ -72,7 +72,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ return { list, current() { - return list().find((x) => x.name === store.current)! + return list().find((x) => x.name === store.current) ?? list()[0] }, set(name: string | undefined) { setStore("current", name ?? list()[0].name) diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 0b917894809..c644562e81d 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -596,17 +596,24 @@ export default function Layout(props: ParentProps) { slug: string project: LocalProject mobile?: boolean + depth?: number + allSessions: Session[] }): JSX.Element => { const notification = useNotification() + const depth = () => props.depth ?? 0 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")) + const childSessions = createMemo(() => + props.allSessions.filter((s) => s.parentID === props.session.id).toSorted(sortSessions), + ) + const hasChildren = createMemo(() => childSessions().length > 0) + const isExpanded = createMemo(() => layout.sessions.isExpanded(props.session.id)) const hasPermissions = createMemo(() => { const store = globalSync.child(props.project.worktree)[0] const permissions = store.permission?.[props.session.id] ?? [] if (permissions.length > 0) return true - const childSessions = store.session.filter((s) => s.parentID === props.session.id) - for (const child of childSessions) { + for (const child of childSessions()) { const childPermissions = store.permission?.[child.id] ?? [] if (childPermissions.length > 0) return true } @@ -618,20 +625,30 @@ export default function Layout(props: ParentProps) { const status = globalSync.child(props.project.worktree)[0].session_status[props.session.id] return status?.type === "busy" || status?.type === "retry" }) - return ( - <> -
- - -
+ + const SessionRow = () => ( +
hasChildren() && layout.sessions.toggle(props.session.id)} + > + + +
+
+ }> + + {props.session.title} -
- - - - - -
- - -
- - 0}> -
- - - - {Math.abs(updated().diffNow().as("seconds")) < 60 - ? "Now" - : updated() - .toRelative({ - style: "short", - unit: ["days", "hours", "minutes"], - }) - ?.replace(" ago", "") - ?.replace(/ days?/, "d") - ?.replace(" min.", "m") - ?.replace(" hr.", "h")} - - - -
- -
- {`${props.session.summary?.files || "No"} file${props.session.summary?.files !== 1 ? "s" : ""} changed`} - {(summary) => } -
-
-
+
+ + + + + +
+ + +
+ + 0}> +
+ + + + {Math.abs(updated().diffNow().as("seconds")) < 60 + ? "Now" + : updated() + .toRelative({ + style: "short", + unit: ["days", "hours", "minutes"], + }) + ?.replace(" ago", "") + ?.replace(/ days?/, "d") + ?.replace(" min.", "m") + ?.replace(" hr.", "h")} + + + +
+
+ +
+ {`${props.session.summary?.files || "No"} file${props.session.summary?.files !== 1 ? "s" : ""} changed`} + {(summary) => } +
+
+ + + + } + > + archiveSession(props.session)} /> - - } - > - archiveSession(props.session)} /> - -
+
+ ) + + return ( + <> + + + + {(child) => ( + + )} + + ) } @@ -776,7 +813,13 @@ export default function Layout(props: ParentProps) {