mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-06 00:12:11 +00:00
fix(app): optimistic revert/restore
This commit is contained in:
parent
02c75821a8
commit
f0542fae7a
4 changed files with 98 additions and 28 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import type { Project, UserMessage } from "@opencode-ai/sdk/v2"
|
||||
import { useDialog } from "@opencode-ai/ui/context/dialog"
|
||||
import {
|
||||
batch,
|
||||
onCleanup,
|
||||
Show,
|
||||
Match,
|
||||
|
|
@ -291,6 +292,7 @@ export default function Page() {
|
|||
git: false,
|
||||
pendingMessage: undefined as string | undefined,
|
||||
restoring: undefined as string | undefined,
|
||||
reverting: false,
|
||||
reviewSnap: false,
|
||||
scrollGesture: 0,
|
||||
scroll: {
|
||||
|
|
@ -1243,6 +1245,24 @@ export default function Page() {
|
|||
})
|
||||
}
|
||||
|
||||
const merge = (next: NonNullable<ReturnType<typeof info>>) =>
|
||||
sync.set("session", (list) => {
|
||||
const idx = list.findIndex((item) => item.id === next.id)
|
||||
if (idx < 0) return list
|
||||
const out = list.slice()
|
||||
out[idx] = next
|
||||
return out
|
||||
})
|
||||
|
||||
const roll = (sessionID: string, next: NonNullable<ReturnType<typeof info>>["revert"]) =>
|
||||
sync.set("session", (list) => {
|
||||
const idx = list.findIndex((item) => item.id === sessionID)
|
||||
if (idx < 0) return list
|
||||
const out = list.slice()
|
||||
out[idx] = { ...out[idx], revert: next }
|
||||
return out
|
||||
})
|
||||
|
||||
const busy = (sessionID: string) => {
|
||||
if (sync.data.session_status[sessionID]?.type !== "idle") return true
|
||||
return (sync.data.message[sessionID] ?? []).some(
|
||||
|
|
@ -1275,42 +1295,77 @@ export default function Page() {
|
|||
}
|
||||
|
||||
const revert = (input: { sessionID: string; messageID: string }) => {
|
||||
if (ui.reverting || ui.restoring) return
|
||||
const prev = prompt.current().slice()
|
||||
const last = info()?.revert
|
||||
const value = draft(input.messageID)
|
||||
batch(() => {
|
||||
setUi("reverting", true)
|
||||
roll(input.sessionID, { messageID: input.messageID })
|
||||
prompt.set(value)
|
||||
})
|
||||
return halt(input.sessionID)
|
||||
.then(() => sdk.client.session.revert(input))
|
||||
.then(() => {
|
||||
prompt.set(value)
|
||||
.then((result) => {
|
||||
if (result.data) merge(result.data)
|
||||
})
|
||||
.catch((err) => {
|
||||
batch(() => {
|
||||
roll(input.sessionID, last)
|
||||
prompt.set(prev)
|
||||
})
|
||||
fail(err)
|
||||
})
|
||||
.finally(() => {
|
||||
setUi("reverting", false)
|
||||
})
|
||||
.catch(fail)
|
||||
}
|
||||
|
||||
const restore = (id: string) => {
|
||||
const sessionID = params.id
|
||||
if (!sessionID || ui.restoring) return
|
||||
if (!sessionID || ui.restoring || ui.reverting) return
|
||||
|
||||
const next = userMessages().find((item) => item.id > id)
|
||||
setUi("restoring", id)
|
||||
const prev = prompt.current().slice()
|
||||
const last = info()?.revert
|
||||
|
||||
batch(() => {
|
||||
setUi("restoring", id)
|
||||
setUi("reverting", true)
|
||||
roll(sessionID, next ? { messageID: next.id } : undefined)
|
||||
if (next) {
|
||||
prompt.set(draft(next.id))
|
||||
return
|
||||
}
|
||||
prompt.reset()
|
||||
})
|
||||
|
||||
const task = !next
|
||||
? halt(sessionID)
|
||||
.then(() => sdk.client.session.unrevert({ sessionID }))
|
||||
.then(() => {
|
||||
prompt.reset()
|
||||
})
|
||||
: halt(sessionID)
|
||||
.then(() =>
|
||||
sdk.client.session.revert({
|
||||
sessionID,
|
||||
messageID: next.id,
|
||||
}),
|
||||
)
|
||||
.then(() => {
|
||||
prompt.set(draft(next.id))
|
||||
})
|
||||
? halt(sessionID).then(() => sdk.client.session.unrevert({ sessionID }))
|
||||
: halt(sessionID).then(() =>
|
||||
sdk.client.session.revert({
|
||||
sessionID,
|
||||
messageID: next.id,
|
||||
}),
|
||||
)
|
||||
|
||||
return task.catch(fail).finally(() => {
|
||||
setUi("restoring", (value) => (value === id ? undefined : value))
|
||||
})
|
||||
return task
|
||||
.then((result) => {
|
||||
if (result.data) merge(result.data)
|
||||
})
|
||||
.catch((err) => {
|
||||
batch(() => {
|
||||
roll(sessionID, last)
|
||||
prompt.set(prev)
|
||||
})
|
||||
fail(err)
|
||||
})
|
||||
.finally(() => {
|
||||
batch(() => {
|
||||
setUi("restoring", (value) => (value === id ? undefined : value))
|
||||
setUi("reverting", false)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const rolled = createMemo(() => {
|
||||
|
|
@ -1487,6 +1542,7 @@ export default function Page() {
|
|||
? {
|
||||
items: rolled(),
|
||||
restoring: ui.restoring,
|
||||
disabled: ui.reverting,
|
||||
onRestore: restore,
|
||||
}
|
||||
: undefined
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue