|
1 | 1 | import type { Project, UserMessage } from "@opencode-ai/sdk/v2" |
2 | 2 | import { useDialog } from "@opencode-ai/ui/context/dialog" |
3 | 3 | import { |
| 4 | + batch, |
4 | 5 | onCleanup, |
5 | 6 | Show, |
6 | 7 | Match, |
@@ -291,6 +292,7 @@ export default function Page() { |
291 | 292 | git: false, |
292 | 293 | pendingMessage: undefined as string | undefined, |
293 | 294 | restoring: undefined as string | undefined, |
| 295 | + reverting: false, |
294 | 296 | reviewSnap: false, |
295 | 297 | scrollGesture: 0, |
296 | 298 | scroll: { |
@@ -1243,6 +1245,24 @@ export default function Page() { |
1243 | 1245 | }) |
1244 | 1246 | } |
1245 | 1247 |
|
| 1248 | + const merge = (next: NonNullable<ReturnType<typeof info>>) => |
| 1249 | + sync.set("session", (list) => { |
| 1250 | + const idx = list.findIndex((item) => item.id === next.id) |
| 1251 | + if (idx < 0) return list |
| 1252 | + const out = list.slice() |
| 1253 | + out[idx] = next |
| 1254 | + return out |
| 1255 | + }) |
| 1256 | + |
| 1257 | + const roll = (sessionID: string, next: NonNullable<ReturnType<typeof info>>["revert"]) => |
| 1258 | + sync.set("session", (list) => { |
| 1259 | + const idx = list.findIndex((item) => item.id === sessionID) |
| 1260 | + if (idx < 0) return list |
| 1261 | + const out = list.slice() |
| 1262 | + out[idx] = { ...out[idx], revert: next } |
| 1263 | + return out |
| 1264 | + }) |
| 1265 | + |
1246 | 1266 | const busy = (sessionID: string) => { |
1247 | 1267 | if (sync.data.session_status[sessionID]?.type !== "idle") return true |
1248 | 1268 | return (sync.data.message[sessionID] ?? []).some( |
@@ -1275,42 +1295,77 @@ export default function Page() { |
1275 | 1295 | } |
1276 | 1296 |
|
1277 | 1297 | const revert = (input: { sessionID: string; messageID: string }) => { |
| 1298 | + if (ui.reverting || ui.restoring) return |
| 1299 | + const prev = prompt.current().slice() |
| 1300 | + const last = info()?.revert |
1278 | 1301 | const value = draft(input.messageID) |
| 1302 | + batch(() => { |
| 1303 | + setUi("reverting", true) |
| 1304 | + roll(input.sessionID, { messageID: input.messageID }) |
| 1305 | + prompt.set(value) |
| 1306 | + }) |
1279 | 1307 | return halt(input.sessionID) |
1280 | 1308 | .then(() => sdk.client.session.revert(input)) |
1281 | | - .then(() => { |
1282 | | - prompt.set(value) |
| 1309 | + .then((result) => { |
| 1310 | + if (result.data) merge(result.data) |
| 1311 | + }) |
| 1312 | + .catch((err) => { |
| 1313 | + batch(() => { |
| 1314 | + roll(input.sessionID, last) |
| 1315 | + prompt.set(prev) |
| 1316 | + }) |
| 1317 | + fail(err) |
| 1318 | + }) |
| 1319 | + .finally(() => { |
| 1320 | + setUi("reverting", false) |
1283 | 1321 | }) |
1284 | | - .catch(fail) |
1285 | 1322 | } |
1286 | 1323 |
|
1287 | 1324 | const restore = (id: string) => { |
1288 | 1325 | const sessionID = params.id |
1289 | | - if (!sessionID || ui.restoring) return |
| 1326 | + if (!sessionID || ui.restoring || ui.reverting) return |
1290 | 1327 |
|
1291 | 1328 | const next = userMessages().find((item) => item.id > id) |
1292 | | - setUi("restoring", id) |
| 1329 | + const prev = prompt.current().slice() |
| 1330 | + const last = info()?.revert |
| 1331 | + |
| 1332 | + batch(() => { |
| 1333 | + setUi("restoring", id) |
| 1334 | + setUi("reverting", true) |
| 1335 | + roll(sessionID, next ? { messageID: next.id } : undefined) |
| 1336 | + if (next) { |
| 1337 | + prompt.set(draft(next.id)) |
| 1338 | + return |
| 1339 | + } |
| 1340 | + prompt.reset() |
| 1341 | + }) |
1293 | 1342 |
|
1294 | 1343 | const task = !next |
1295 | | - ? halt(sessionID) |
1296 | | - .then(() => sdk.client.session.unrevert({ sessionID })) |
1297 | | - .then(() => { |
1298 | | - prompt.reset() |
1299 | | - }) |
1300 | | - : halt(sessionID) |
1301 | | - .then(() => |
1302 | | - sdk.client.session.revert({ |
1303 | | - sessionID, |
1304 | | - messageID: next.id, |
1305 | | - }), |
1306 | | - ) |
1307 | | - .then(() => { |
1308 | | - prompt.set(draft(next.id)) |
1309 | | - }) |
1310 | | - |
1311 | | - return task.catch(fail).finally(() => { |
1312 | | - setUi("restoring", (value) => (value === id ? undefined : value)) |
1313 | | - }) |
| 1344 | + ? halt(sessionID).then(() => sdk.client.session.unrevert({ sessionID })) |
| 1345 | + : halt(sessionID).then(() => |
| 1346 | + sdk.client.session.revert({ |
| 1347 | + sessionID, |
| 1348 | + messageID: next.id, |
| 1349 | + }), |
| 1350 | + ) |
| 1351 | + |
| 1352 | + return task |
| 1353 | + .then((result) => { |
| 1354 | + if (result.data) merge(result.data) |
| 1355 | + }) |
| 1356 | + .catch((err) => { |
| 1357 | + batch(() => { |
| 1358 | + roll(sessionID, last) |
| 1359 | + prompt.set(prev) |
| 1360 | + }) |
| 1361 | + fail(err) |
| 1362 | + }) |
| 1363 | + .finally(() => { |
| 1364 | + batch(() => { |
| 1365 | + setUi("restoring", (value) => (value === id ? undefined : value)) |
| 1366 | + setUi("reverting", false) |
| 1367 | + }) |
| 1368 | + }) |
1314 | 1369 | } |
1315 | 1370 |
|
1316 | 1371 | const rolled = createMemo(() => { |
@@ -1487,6 +1542,7 @@ export default function Page() { |
1487 | 1542 | ? { |
1488 | 1543 | items: rolled(), |
1489 | 1544 | restoring: ui.restoring, |
| 1545 | + disabled: ui.reverting, |
1490 | 1546 | onRestore: restore, |
1491 | 1547 | } |
1492 | 1548 | : undefined |
|
0 commit comments