Mark unread turn summaries in the switcher and Project rows
This commit is contained in:
+56
-1
@@ -4,7 +4,7 @@ import { markdown } from "./markdown.js";
|
||||
import { previewURL } from "./preview.js";
|
||||
import { findingCount, reviewCounts, severityCounts, unignoredFindings } from "./reviews.js";
|
||||
import { composerText, endSend, flushDrafts, forgetLostImages, lostImageCount, setComposerImages, setComposerText, startSend } from "./drafts.js";
|
||||
import { currentSession, findTask, focusTab, focusTask, on, onEach, pickReview, pinSnapshot, setFocus, showReview, state, transcriptLoading, type Topic } from "./state.js";
|
||||
import { currentSession, findTask, focusTab, focusTask, markSummaryRead, on, onEach, pickReview, pinSnapshot, setFocus, showReview, state, transcriptLoading, type Topic } from "./state.js";
|
||||
import { taskStyle } from "./taskcolor.js";
|
||||
import { fillTodoLinks } from "./todolink.js";
|
||||
|
||||
@@ -220,6 +220,51 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
|
||||
const mutations = new MutationObserver(pin);
|
||||
mutations.observe(transcript, { childList: true, subtree: true, characterData: true });
|
||||
|
||||
const shown = new Set<HTMLElement>();
|
||||
const markShown = () => {
|
||||
const taskId = ctx.taskId;
|
||||
if (!taskId || document.visibilityState !== "visible") {
|
||||
return;
|
||||
}
|
||||
for (const el of shown) {
|
||||
markSummaryRead(taskId, Number(el.dataset["seq"]));
|
||||
}
|
||||
};
|
||||
const sightings = new IntersectionObserver(
|
||||
(entries) => {
|
||||
for (const e of entries) {
|
||||
if (e.isIntersecting) {
|
||||
shown.add(e.target as HTMLElement);
|
||||
} else {
|
||||
shown.delete(e.target as HTMLElement);
|
||||
}
|
||||
}
|
||||
markShown();
|
||||
},
|
||||
{ root: transcript },
|
||||
);
|
||||
document.addEventListener("visibilitychange", markShown);
|
||||
|
||||
const jump = () => {
|
||||
const target = state.jump;
|
||||
if (!target || target.taskId !== ctx.taskId) {
|
||||
return;
|
||||
}
|
||||
const end = transcript.querySelector<HTMLElement>(`.turn-end[data-seq="${target.seq}"]`);
|
||||
if (!end) {
|
||||
return;
|
||||
}
|
||||
state.jump = undefined;
|
||||
const msg = end.previousElementSibling;
|
||||
const box = transcript.getBoundingClientRect();
|
||||
if (msg?.classList.contains("agent")) {
|
||||
transcript.scrollTop += msg.getBoundingClientRect().top - box.top - 8;
|
||||
} else {
|
||||
transcript.scrollTop += end.getBoundingClientRect().bottom - box.bottom + 8;
|
||||
}
|
||||
stuck = transcript.scrollHeight - transcript.scrollTop - transcript.clientHeight < 80;
|
||||
};
|
||||
|
||||
const newCtx = (): Ctx => ({
|
||||
tools: new Map(),
|
||||
subagents: new Map(),
|
||||
@@ -517,6 +562,10 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
|
||||
if (ev.kind === "user.message" && p["mid_turn"] !== true) {
|
||||
ctx.open = true;
|
||||
}
|
||||
if (ev.kind === "turn.ended" && p["summary"] === true && ctx.taskId) {
|
||||
el.dataset["seq"] = String(ev.seq);
|
||||
sightings.observe(el);
|
||||
}
|
||||
put(el);
|
||||
}
|
||||
syncRunning();
|
||||
@@ -529,12 +578,15 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
|
||||
}
|
||||
fillTodoLinks(transcript, models[0]!);
|
||||
pin();
|
||||
jump();
|
||||
};
|
||||
|
||||
const renderAll = () => {
|
||||
stuck = true;
|
||||
dropStream();
|
||||
pending = [];
|
||||
sightings.disconnect();
|
||||
shown.clear();
|
||||
ctx = newCtx();
|
||||
context = new Map();
|
||||
focusStart = true;
|
||||
@@ -563,6 +615,7 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
|
||||
onEach([src.streamTopic], (ev) => appendDelta(ev as ByreEvent)),
|
||||
onEach([src.readyTopic], () => loading.remove()),
|
||||
onEach(["tasks", "sessions"], () => fillTodoLinks(transcript, models[0]!)),
|
||||
on("jump", jump),
|
||||
];
|
||||
|
||||
replace(root, h("div", { class: "transcript-view" }, head, transcript, composer));
|
||||
@@ -574,6 +627,8 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
|
||||
headImpl.dispose?.();
|
||||
resizes.disconnect();
|
||||
mutations.disconnect();
|
||||
sightings.disconnect();
|
||||
document.removeEventListener("visibilitychange", markShown);
|
||||
dropStream();
|
||||
const input = composer.querySelector("textarea");
|
||||
if (input) {
|
||||
|
||||
Reference in New Issue
Block a user