Skip to content

Commit 55538f3

Browse files
committed
fix: DocGen reject restores full typed card for all block types
- Fixed: rejecting Translate block showed generic AI Generate card (missing language dropdown) - Fixed: rejecting OCR/TTS/STT/Image/AI blocks lost all type-specific UI - Reject handler now uses M.transformDocgenMarkdown(block.fullMatch) to re-render exact original card - data-ai-index patched on restored card and all child elements after re-render - Review panel header now shows correct icon+label per type (🌐 Translate, 🔍 OCR, etc.) - README: backfilled commit IDs for recent entries (f012a30, 971de55, 6f495fe, 1519804, fe7bde6)
1 parent f012a30 commit 55538f3

3 files changed

Lines changed: 69 additions & 32 deletions

File tree

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -544,10 +544,11 @@ TextAgent has undergone significant evolution since its inception. What started
544544

545545
| Date | Commits | Feature / Update |
546546
|------|---------|-----------------:|
547-
| **2026-04-02** | |**Share Link Loading Overlay** — eliminates the flash of bare UI when opening shared links (`#space=`, `#s=`, `#id=`, `#d=`); full-screen branded loading splash (TextAgent logo + spinner) activates before any JS loads via inline hash detection in `<head>`; theme-aware (dark `#0d1117` / light `#f6f8fa`); fades out smoothly (0.35s) once content is ready; `hideShareLoader()` called at every terminal path (success, error, form-gate); 15-second safety timeout auto-dismisses on network failure |
548-
| **2026-04-02** | | ✏️ **Annotate DocGen + Pretext Reflow Engine** — new `{{Annotate:}}` DocGen tag with canvas-based freehand annotation overlay; `@text:` source mode renders text on-canvas with real-time Pretext-style scanline reflow (~0.5–1.5ms/frame, O(width) per row); freehand strokes build an offscreen mask; per-row `getImageData` scans free x-intervals; words packed into intervals via `canvas.measureText()` (same arithmetic as Pretext `layoutNextLine()`); tools: pen, highlighter, eraser, line, arrow, rect, circle; color swatches + size slider; `📖 Present` button calls `M.setViewMode('preview')` — hides editor, annotation stays fully drawable while reading; `↩ Undo` / `🗑 Clear` / `📥 PNG` actions; Fixed: `data-text` stripped by DOMPurify — added `data-text`, `data-reflow` to `ADD_ATTR` + hidden `<span class="ann-reflow-text">` textContent as primary storage (survives sanitization without whitelisting); `annotate-docgen.js` (~710 lines) + `annotate-docgen.css` (~340 lines); interactive demo: `public/pretext-reflow-demo.html` — 4-tab demo (Float Image, Draw Exclusion, Both Together, API explainer) |
549-
| **2026-04-02** | | 📬 **Space Recovery by Email + Email Link Fix** — Spaces "Recover" view now has two tabs: **By Email** (default — enter email + access key, Firestore queries by hashed `eh` field to recover all matching spaces) and **By Slug** (existing flow); email pre-filled from localStorage; recovers multiple spaces at once if same key used; "Email to Self" now embeds all generated links (Share Link, Editor Link, Respondent Link, Password) directly in the email body so they always appear in the sent email |
550-
| **2026-04-02** | | 🔬 **Research Loop UX Fixes** — fixed table-tools toolbar hijacking research results table (skips `research-results-table` class); fixed results table `max-height: 350px` clipping to `600px`; moved `research-loop.js` import to Phase 3b-ext3 with try/catch to prevent silent load failures; clicking row now shows only the extracted `PROMPT` text with `📋 Copy` button (not full scorer code); added search pills panel (`@search:` field) with provider API key prompts; DOMPurify allowlist expanded for `input`, `label`, `checked`, `data-research-*` attrs; iframe sandbox height raised from 800→5000px |
547+
| **2026-04-02** | `(pending)` | 🔧 **DocGen Reject Block Fix** — fixed: rejecting a generated Translate/OCR/TTS/STT/Image/AI block restored a generic hardcoded "AI Generate" card, losing all type-specific UI (language dropdown, mode pills, camera button, step inputs, etc.); reject handler now calls `M.transformDocgenMarkdown(block.fullMatch)` to re-render the exact original typed card with all controls intact; `data-ai-index` patched on restored card and all children; review panel header label+icon now shows correct type for all blocks ("🌐 Translate — Review", "🔍 OCR Scan — Review", etc.) instead of always "✨ AI Generate — Review" |
548+
| **2026-04-02** | `f012a30`, `971de55` |**Share Link Loading Overlay** — eliminates the flash of bare UI when opening shared links (`#space=`, `#s=`, `#id=`, `#d=`); full-screen branded loading splash (TextAgent logo + spinner) activates before any JS loads via inline hash detection in `<head>`; theme-aware (dark `#0d1117` / light `#f6f8fa`); fades out smoothly (0.35s) once content is ready; `hideShareLoader()` called at every terminal path (success, error, form-gate); 15-second safety timeout auto-dismisses on network failure |
549+
| **2026-04-02** | `6f495fe` | ✏️ **Annotate DocGen + Pretext Reflow Engine** — new `{{Annotate:}}` DocGen tag with canvas-based freehand annotation overlay; `@text:` source mode renders text on-canvas with real-time Pretext-style scanline reflow (~0.5–1.5ms/frame, O(width) per row); freehand strokes build an offscreen mask; per-row `getImageData` scans free x-intervals; words packed into intervals via `canvas.measureText()` (same arithmetic as Pretext `layoutNextLine()`); tools: pen, highlighter, eraser, line, arrow, rect, circle; color swatches + size slider; `📖 Present` button calls `M.setViewMode('preview')` — hides editor, annotation stays fully drawable while reading; `↩ Undo` / `🗑 Clear` / `📥 PNG` actions; Fixed: `data-text` stripped by DOMPurify — added `data-text`, `data-reflow` to `ADD_ATTR` + hidden `<span class="ann-reflow-text">` textContent as primary storage (survives sanitization without whitelisting); `annotate-docgen.js` (~710 lines) + `annotate-docgen.css` (~340 lines); interactive demo: `public/pretext-reflow-demo.html` — 4-tab demo (Float Image, Draw Exclusion, Both Together, API explainer) |
550+
| **2026-04-02** | `1519804` | 📬 **Space Recovery by Email + Email Link Fix** — Spaces "Recover" view now has two tabs: **By Email** (default — enter email + access key, Firestore queries by hashed `eh` field to recover all matching spaces) and **By Slug** (existing flow); email pre-filled from localStorage; recovers multiple spaces at once if same key used; "Email to Self" now embeds all generated links (Share Link, Editor Link, Respondent Link, Password) directly in the email body so they always appear in the sent email |
551+
| **2026-04-02** | `fe7bde6` | 🔬 **Research Loop UX Fixes** — fixed table-tools toolbar hijacking research results table (skips `research-results-table` class); fixed results table `max-height: 350px` clipping to `600px`; moved `research-loop.js` import to Phase 3b-ext3 with try/catch to prevent silent load failures; clicking row now shows only the extracted `PROMPT` text with `📋 Copy` button (not full scorer code); added search pills panel (`@search:` field) with provider API key prompts; DOMPurify allowlist expanded for `input`, `label`, `checked`, `data-research-*` attrs; iframe sandbox height raised from 800→5000px |
551552
| **2026-04-01** | | 🔬 **Research Loop Tag** — new `{{@Research:}}` tag for autonomous AI-driven experiment optimization (inspired by Karpathy's autoresearch); Propose→Execute→Evaluate→Keep/Discard loop runs entirely in-browser via Pyodide (Python in WASM); configurable `@metric`, `@direction` (lower/higher), `@max_iterations`, `@model`, `@goal`; multiline `@code: \|` (mutable) and `@test: \|` (fixed harness) fields; metric extraction from stdout (`METRIC:xxx`); AI prompt includes experiment history with strategy shift hints after 3 consecutive failures; live results table with status badges (baseline/keep/discard/crash), delta indicators, progress bar; per-card model selector; Start/Stop controls; glass card UI with purple accents and pulse animation; `js/research-loop.js` (~795 lines) + `css/research-loop.css` (~300 lines) |
552553
| **2026-04-01** | | 🎨 **AI Panel UI Redesign** — centered initial chat state (Claude-like welcome with input + model selector clustered in middle, transitions to bottom-pinned on first message via CSS `:has(.ai-welcome-message)`); merged separate Attach File (paperclip) and Screenshot (camera) buttons into single `+` button with unified dropdown menu (Attach File / Capture Page / Capture Screen / Upload Image, `+` rotates to `×` when open); merged header bar and status bar into single compact header (status text inline below title, download progress bar still standalone); fixed download progress bar stuck at 96% after model load |
553554
| **2026-03-31** | | 📷 **Screenshot to AI** — new 📷 camera button in the AI chat input bar with three capture modes: Capture Page (`html2canvas` full-page snapshot, AI panel hidden during capture), Capture Screen (`getDisplayMedia` screen-share with frame extraction from a hidden DOM-attached video element), and Upload Image (file picker); captured image auto-injected into `pendingAttachments` and sent to AI for analysis; fixed black-screen capture bug (video must be in DOM for GPU decoder, wait for `timeupdate` event not just `requestAnimationFrame`); self-healing button injection via `injectButtonIfMissing()` with 2s fallback poll; CSS-independent dropdown via inline `style.display` toggling; vision model warning toast; `js/ai-screenshot.js` new module (~300 lines) + `css/ai-panel.css` styles + `js/modal-templates.js` template update + `src/main.js` registration |
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# DocGen Reject Fix — Restore Full Typed Card on Reject
2+
3+
- Fixed: Rejecting a generated Translate block restored a generic "AI Generate" card instead of the proper Translate card with language dropdown
4+
- Fixed: Rejecting a generated OCR block lost mode pills, camera button, and upload button
5+
- Fixed: Rejecting any specialized block (Translate, OCR, TTS, STT, etc.) always showed a generic "AI Generate" card missing all type-specific UI
6+
- Fixed: Review panel header showed wrong icon and label ("✨ AI Generate") for Translate, OCR, TTS, STT, and Image blocks — now correctly shows "🌐 Translate — Review", "🔍 OCR Scan — Review", etc.
7+
- Reject handler now uses `M.transformDocgenMarkdown(block.fullMatch)` to re-render the exact original block into its full typed card
8+
- `data-ai-index` attribute patched on the restored card and all child elements so button actions remain correctly bound after reject
9+
- Fallback minimal card included in case `transformDocgenMarkdown` produces no output (defensive)
10+
11+
---
12+
13+
## Summary
14+
15+
When users clicked **Reject** on a generated AI block, the review handler rebuilt a hardcoded generic "AI Generate" card for all block types. For `{{@Translate:}}` blocks this dropped the language selection dropdown; for `{{@OCR:}}` blocks it dropped the mode pills, camera, and upload buttons; for other types similar UI was lost. This fix re-renders the original DocGen tag markdown through the existing `transformDocgenMarkdown` renderer, producing a bit-perfect typed card restoration regardless of block type.
16+
17+
---
18+
19+
## 1. Reject Handler — Full Card Restoration
20+
**Files:** `js/ai-docgen-generate.js`
21+
**What:** Replaced the hardcoded "AI Generate" card HTML in the `handleDecision('reject')` branch of `showReviewPanel()` with a call to `M.transformDocgenMarkdown(block.fullMatch)`, which produces the same full card HTML as the initial render. The resulting DOM node is patched to restore the correct `data-ai-index` (since `transformDocgenMarkdown` always counts from index 0), then swapped into the preview pane. `M.bindDocgenPreviewActions()` is called after the swap to re-bind all button handlers.
22+
**Impact:** Translate blocks restore with language dropdown + model selector. OCR blocks restore with mode pills + camera + upload. Agent blocks restore with step inputs + search pills + cloud toggle. All other typed block UIs (TTS, STT, Image, Memory) are likewise correct after reject.
23+
24+
## 2. Review Panel Header Label Fix
25+
**Files:** `js/ai-docgen-generate.js`
26+
**What:** The review panel header `icon` and `typeLabel` variables were previously only checking for `block.type === 'Think'` and defaulting to `✨ / AI Generate` for everything else. Extended the ternary chain to cover all DocGen types: Translate → `🌐`, OCR → `🔍`, TTS → `🔊`, STT → `🎤`, Image → `🖼️`, AI/Think → `✨/🧠`.
27+
**Impact:** The review panel header now correctly shows e.g. "🌐 Translate — Review" or "🔍 OCR Scan — Review" instead of always "✨ AI Generate — Review".
28+
29+
---
30+
31+
## Files Changed (1 total)
32+
33+
| File | Lines Changed | Type |
34+
|------|:---:|------|
35+
| `js/ai-docgen-generate.js` | +29 −28 | Bug fix — reject handler + review header label |

js/ai-docgen-generate.js

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,8 @@
441441
reviewCard.className = 'ai-inline-review';
442442
reviewCard.dataset.aiType = block.type;
443443

444-
var icon = block.type === 'Think' ? '🧠' : '✨';
445-
var typeLabel = block.type === 'Think' ? 'Think' : 'AI Generate';
444+
var icon = block.type === 'Think' ? '🧠' : block.type === 'Translate' ? '🌐' : block.type === 'OCR' ? '🔍' : block.type === 'TTS' ? '🔊' : block.type === 'STT' ? '🎤' : block.type === 'Image' ? '🖼️' : '✨';
445+
var typeLabel = block.type === 'Think' ? 'Think' : block.type === 'Translate' ? 'Translate' : block.type === 'OCR' ? 'OCR Scan' : block.type === 'TTS' ? 'Text to Speech' : block.type === 'STT' ? 'Speech to Text' : block.type === 'Image' ? 'Image Generate' : 'AI Generate';
446446

447447
reviewCard.innerHTML =
448448
'<div class="ai-inline-review-header">'
@@ -476,32 +476,33 @@
476476
resolved = true;
477477
resolve(decision);
478478
if (decision === 'reject' && placeholderCard) {
479-
var models = window.AI_MODELS || {};
480-
var modelIds = Object.keys(models);
481-
var currentModel = (M.getCurrentAiModel ? M.getCurrentAiModel() : modelIds[0]) || modelIds[0];
482-
var modelOptionsHtml = '';
483-
modelIds.forEach(function (id) {
484-
var m = models[id];
485-
var name = m.dropdownName || m.label || id;
486-
var sel = id === currentModel ? ' selected' : '';
487-
modelOptionsHtml += '<option value="' + id + '"' + sel + '>' + name + '</option>';
488-
});
489-
var newCard = document.createElement('div');
490-
newCard.className = 'ai-placeholder-card';
491-
newCard.dataset.aiType = block.type;
492-
newCard.dataset.aiIndex = blockIndex;
493-
var icon = block.type === 'Think' ? '🧠' : '✨';
494-
var label = block.type === 'Think' ? 'Think' : 'AI Generate';
495-
newCard.innerHTML =
496-
'<div class="ai-placeholder-header">'
497-
+ '<span class="ai-placeholder-icon">' + icon + '</span>'
498-
+ '<span class="ai-placeholder-label">' + label + '</span>'
499-
+ '<div class="ai-placeholder-actions">'
500-
+ '<select class="ai-card-model-select" data-ai-index="' + blockIndex + '" title="Model for this generation">' + modelOptionsHtml + '</select>'
501-
+ '<button class="ai-placeholder-btn ai-fill-one" data-ai-index="' + blockIndex + '" title="Generate this block">▶</button>'
502-
+ '<button class="ai-placeholder-btn ai-remove-tag" data-ai-index="' + blockIndex + '" title="Remove tag">✕</button>'
503-
+ '</div></div>'
504-
+ '<div class="ai-placeholder-prompt">' + block.prompt + '</div>';
479+
// Re-render the original block's full markdown back into its proper typed card
480+
// (preserves language dropdown for Translate, steps for Agent, etc.)
481+
var restoredHtml = M.transformDocgenMarkdown(block.fullMatch);
482+
var tempDiv = document.createElement('div');
483+
tempDiv.innerHTML = restoredHtml;
484+
var newCard = tempDiv.querySelector('.ai-placeholder-card') || tempDiv.firstElementChild;
485+
if (!newCard) {
486+
// Fallback: build a minimal generic card if transform fails
487+
newCard = document.createElement('div');
488+
newCard.className = 'ai-placeholder-card';
489+
newCard.dataset.aiType = block.type;
490+
newCard.dataset.aiIndex = String(blockIndex);
491+
var icon = block.type === 'Think' ? '🧠' : block.type === 'Translate' ? '🌐' : '✨';
492+
var label = block.type === 'Think' ? 'Think' : block.type === 'Translate' ? 'Translate' : 'AI Generate';
493+
newCard.innerHTML =
494+
'<div class="ai-placeholder-header">'
495+
+ '<span class="ai-placeholder-icon">' + icon + '</span>'
496+
+ '<span class="ai-placeholder-label">' + label + '</span>'
497+
+ '</div>'
498+
+ '<div class="ai-placeholder-prompt">' + block.prompt + '</div>';
499+
} else {
500+
// Fix up the block index in case transformDocgenMarkdown assigned index 0
501+
newCard.dataset.aiIndex = String(blockIndex);
502+
newCard.querySelectorAll('[data-ai-index]').forEach(function (el) {
503+
el.dataset.aiIndex = String(blockIndex);
504+
});
505+
}
505506
reviewCard.parentNode.replaceChild(newCard, reviewCard);
506507
M.bindDocgenPreviewActions(newCard.parentNode);
507508
} else if (decision === 'accept') {

0 commit comments

Comments
 (0)