|
@@ -8,8 +8,11 @@ import { useLanguage } from "@/context/language"
|
|
|
import { usePermission } from "@/context/permission"
|
|
import { usePermission } from "@/context/permission"
|
|
|
import { useSDK } from "@/context/sdk"
|
|
import { useSDK } from "@/context/sdk"
|
|
|
import { useSync } from "@/context/sync"
|
|
import { useSync } from "@/context/sync"
|
|
|
|
|
+import { todoState } from "./session-composer-helpers"
|
|
|
import { sessionPermissionRequest, sessionQuestionRequest } from "./session-request-tree"
|
|
import { sessionPermissionRequest, sessionQuestionRequest } from "./session-request-tree"
|
|
|
|
|
|
|
|
|
|
+const idle = { type: "idle" as const }
|
|
|
|
|
+
|
|
|
export function createSessionComposerBlocked() {
|
|
export function createSessionComposerBlocked() {
|
|
|
const params = useParams()
|
|
const params = useParams()
|
|
|
const permission = usePermission()
|
|
const permission = usePermission()
|
|
@@ -59,9 +62,22 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
|
|
|
return globalSync.data.session_todo[id] ?? []
|
|
return globalSync.data.session_todo[id] ?? []
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+ const done = createMemo(
|
|
|
|
|
+ () => todos().length > 0 && todos().every((todo) => todo.status === "completed" || todo.status === "cancelled"),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ const status = createMemo(() => {
|
|
|
|
|
+ const id = params.id
|
|
|
|
|
+ if (!id) return idle
|
|
|
|
|
+ return sync.data.session_status[id] ?? idle
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ const busy = createMemo(() => status().type !== "idle")
|
|
|
|
|
+ const live = createMemo(() => busy() || blocked())
|
|
|
|
|
+
|
|
|
const [store, setStore] = createStore({
|
|
const [store, setStore] = createStore({
|
|
|
responding: undefined as string | undefined,
|
|
responding: undefined as string | undefined,
|
|
|
- dock: todos().length > 0,
|
|
|
|
|
|
|
+ dock: todos().length > 0 && live(),
|
|
|
closing: false,
|
|
closing: false,
|
|
|
opening: false,
|
|
opening: false,
|
|
|
})
|
|
})
|
|
@@ -89,10 +105,6 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const done = createMemo(
|
|
|
|
|
- () => todos().length > 0 && todos().every((todo) => todo.status === "completed" || todo.status === "cancelled"),
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
let timer: number | undefined
|
|
let timer: number | undefined
|
|
|
let raf: number | undefined
|
|
let raf: number | undefined
|
|
|
|
|
|
|
@@ -111,21 +123,42 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
|
|
|
}, closeMs())
|
|
}, closeMs())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Keep stale turn todos from reopening if the model never clears them.
|
|
|
|
|
+ const clear = () => {
|
|
|
|
|
+ const id = params.id
|
|
|
|
|
+ if (!id) return
|
|
|
|
|
+ globalSync.todo.set(id, [])
|
|
|
|
|
+ sync.set("todo", id, [])
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
createEffect(
|
|
createEffect(
|
|
|
on(
|
|
on(
|
|
|
- () => [todos().length, done()] as const,
|
|
|
|
|
- ([count, complete], prev) => {
|
|
|
|
|
|
|
+ () => [todos().length, done(), live()] as const,
|
|
|
|
|
+ ([count, complete, active]) => {
|
|
|
if (raf) cancelAnimationFrame(raf)
|
|
if (raf) cancelAnimationFrame(raf)
|
|
|
raf = undefined
|
|
raf = undefined
|
|
|
|
|
|
|
|
- if (count === 0) {
|
|
|
|
|
|
|
+ const next = todoState({
|
|
|
|
|
+ count,
|
|
|
|
|
+ done: complete,
|
|
|
|
|
+ live: active,
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ if (next === "hide") {
|
|
|
if (timer) window.clearTimeout(timer)
|
|
if (timer) window.clearTimeout(timer)
|
|
|
timer = undefined
|
|
timer = undefined
|
|
|
setStore({ dock: false, closing: false, opening: false })
|
|
setStore({ dock: false, closing: false, opening: false })
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (!complete) {
|
|
|
|
|
|
|
+ if (next === "clear") {
|
|
|
|
|
+ if (timer) window.clearTimeout(timer)
|
|
|
|
|
+ timer = undefined
|
|
|
|
|
+ clear()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (next === "open") {
|
|
|
if (timer) window.clearTimeout(timer)
|
|
if (timer) window.clearTimeout(timer)
|
|
|
timer = undefined
|
|
timer = undefined
|
|
|
const hidden = !store.dock || store.closing
|
|
const hidden = !store.dock || store.closing
|
|
@@ -142,13 +175,8 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (prev && prev[1]) {
|
|
|
|
|
- if (store.closing && !timer) scheduleClose()
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
setStore({ dock: true, opening: false, closing: true })
|
|
setStore({ dock: true, opening: false, closing: true })
|
|
|
- scheduleClose()
|
|
|
|
|
|
|
+ if (!timer) scheduleClose()
|
|
|
},
|
|
},
|
|
|
),
|
|
),
|
|
|
)
|
|
)
|