From 3688b6595415fd7a9f1792ae0bc3ff122e161301 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Mon, 10 Aug 2026 11:52:13 -0700 Subject: [PATCH] Treat unresolved chat hashtags as plain text --- .../public/aesthetic.computer/disks/chat.mjs | 55 +++++++++++++------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/system/public/aesthetic.computer/disks/chat.mjs b/system/public/aesthetic.computer/disks/chat.mjs index 167e3b449..909f10322 100644 --- a/system/public/aesthetic.computer/disks/chat.mjs +++ b/system/public/aesthetic.computer/disks/chat.mjs @@ -205,8 +205,12 @@ let scroll = 0, // 🎨 Painting preview system let paintingPreviewCache = new Map(); // Store loaded painting previews let paintingLoadQueue = new Set(); // Track which paintings are being loaded -let paintingLoadProgress = new Map(); // Track loading progress (0-1) for each painting -// 🛑 Codes whose load failed (bad slug, 404, CORS, network). Without this the +let paintingLoadProgress = new Map(); // Track loading progress (0-1) for each painting +// Hashtag-shaped text is only a painting after /api/painting-code confirms it. +// Keep confirmed 404s separate from broken image loads so ordinary hashtags +// collapse back to plain chat text instead of showing a broken preview. +let nonPaintingCodeCache = new Set(); +// 🛑 Codes whose image load failed (bad slug, CORS, network). Without this the // paint loop re-fires loadPaintingPreview every frame for a broken code, // flooding the network + console and locking up the whole chat. Failures stick // for the session; a reload clears them (so a fixed code can retry). @@ -1461,13 +1465,13 @@ function paint( const code = message.layout.paintingCodes[codeIdx]; const cached = paintingPreviewCache.get(code); - if (!cached && !paintingLoadQueue.has(code) && !paintingFailedCache.has(code)) { - // Trigger async loading - loadPaintingPreview(code, api.get, store).then(result => { - if (result) { - help.repeat(); // Trigger repaint when preview loads - } - }); + if (!cached && !paintingLoadQueue.has(code) && !paintingFailedCache.has(code) && !nonPaintingCodeCache.has(code)) { + // Trigger async loading + loadPaintingPreview(code, api.get, store).then(() => { + // Recompute layout both when a preview loads and when a 404 proves + // that hashtag-shaped text is not a painting. + help.repeat(); + }); } if (cached) { @@ -4424,9 +4428,12 @@ async function loadPaintingPreview(code, get, store) { // 🛑 Give up on codes that already failed — otherwise the paint loop retries // every frame and floods the network/console. - if (paintingFailedCache.has(code)) { - return null; - } + if (paintingFailedCache.has(code)) { + return null; + } + if (nonPaintingCodeCache.has(code)) { + return null; + } // Check if already loading if (paintingLoadQueue.has(code)) { @@ -4460,11 +4467,17 @@ async function loadPaintingPreview(code, get, store) { metadata = cached; paintingLoadProgress.set(code, 0.4); // 40% - metadata from cache } else { - const response = await fetch(`/api/painting-code?code=${normalized}`); - if (!response.ok) { - markFailed(); - return null; - } + const response = await fetch(`/api/painting-code?code=${normalized}`); + if (!response.ok) { + if (response.status === 404) { + paintingLoadQueue.delete(code); + paintingLoadProgress.delete(code); + nonPaintingCodeCache.add(code); + return null; + } + markFailed(); + return null; + } metadata = await response.json(); paintingLoadProgress.set(code, 0.4); // 40% - metadata fetched @@ -5165,7 +5178,13 @@ function buildWordPositionMap(originalMessage, textBoxLines) { } // Use shared parsing function from chat-highlighting.mjs -const parseMessageElements = parseMessageElementsShared; +function parseMessageElements(message) { + return parseMessageElementsShared(message).filter((element) => { + if (element.type !== "painting") return true; + const code = element.text.replace(/^#/, ""); + return !nonPaintingCodeCache.has(code); + }); +} // Calculate the rendered position of an interactive element in the text layout function calculateElementPosition(element, fullMessage, textLines, text, currentRowHeight, typefaceName) { -- 2.51.2