1
0
mirror of https://github.com/coalaura/whiskr.git synced 2025-09-09 09:19:54 +00:00

morphdom & better images

This commit is contained in:
Laura
2025-08-10 15:53:30 +02:00
parent 8996173b3f
commit 960736e161
7 changed files with 96 additions and 78 deletions

View File

@@ -14,17 +14,20 @@
const messages = [];
let autoScrolling = false, interacted = false;
let autoScrolling = false,
interacted = false;
function scroll(force = false) {
if (!autoScrolling && !force) {
return;
}
$messages.scroll({
top: $messages.scrollHeight + 200,
behavior: "smooth",
});
setTimeout(() => {
$messages.scroll({
top: $messages.scrollHeight + 200,
behavior: "smooth",
});
}, 0);
}
class Message {
@@ -37,6 +40,10 @@
#expanded = false;
#state = false;
#_diff;
#pending = {};
#patching = {};
#_message;
#_role;
#_reasoning;
@@ -49,10 +56,16 @@
this.#reasoning = reasoning || "";
this.#text = text || "";
this.#_diff = document.createElement("div");
this.#build();
this.#render();
messages.push(this);
if (this.#reasoning || this.#text) {
this.#save();
}
}
#build() {
@@ -165,38 +178,81 @@
scroll();
}
#handleImages(element) {
element.querySelectorAll("img:not(.image)").forEach((img) => {
img.classList.add("image");
img.addEventListener("load", () => {
scroll(!interacted);
});
});
}
#patch(name, element, md, after = false) {
if (!element.firstChild) {
element.innerHTML = render(md);
this.#handleImages(element);
after?.();
return;
}
this.#pending[name] = md;
if (this.#patching[name]) {
return;
}
this.#patching[name] = true;
schedule(() => {
const html = render(this.#pending[name]);
this.#patching[name] = false;
this.#_diff.innerHTML = html;
morphdom(element, this.#_diff, {
childrenOnly: true,
onBeforeElUpdated: (fromEl, toEl) => {
return !fromEl.isEqualNode || !fromEl.isEqualNode(toEl);
},
});
this.#_diff.innerHTML = "";
this.#handleImages(element);
after?.();
});
}
#render(only = false, noScroll = false) {
if (!only || only === "role") {
this.#_role.textContent = this.#role;
}
if (!only || only === "reasoning") {
this.#_reasoning.innerHTML = render(this.#reasoning);
this.#patch("reasoning", this.#_reasoning, this.#reasoning, () => {
this.#_reasoning.style.setProperty(
"--height",
`${this.#_reasoning.scrollHeight}px`,
);
if (this.#reasoning) {
this.#_message.classList.add("has-reasoning");
} else {
this.#_message.classList.remove("has-reasoning");
}
noScroll || scroll();
});
this.#_reasoning.style.setProperty(
"--height",
`${this.#_reasoning.scrollHeight}px`,
);
this.#_message.classList.toggle("has-reasoning", !!this.#reasoning);
}
if (!only || only === "text") {
this.#_text.innerHTML = render(this.#text);
this.#patch("text", this.#_text, this.#text, () => {
noScroll || scroll();
});
if (this.#text) {
this.#_message.classList.add("has-text");
} else {
this.#_message.classList.remove("has-text");
}
}
if (!noScroll) {
scroll();
this.#_message.classList.toggle("has-text", !!this.#text);
}
}
@@ -555,8 +611,6 @@
return;
}
console.debug(chunk);
switch (chunk.type) {
case "reason":
message.setState("reasoning");
@@ -585,10 +639,6 @@
interacted = true;
});
addEventListener("image-loaded", () => {
scroll(!interacted);
});
dropdown($role);
dropdown($prompt);