viewer: ซ่อน tool มาร์กข้อความเมื่อไฟล์ไม่มีข้อความให้คลุม — ทั้งไฟล์รูปภาพ (N3) และ PDF สแกนล้วน (คำขอผู้ใช้ 2026-09-22)
- hideHighlightTool = ไฟล์ภาพ หรือ scannedOnly (ทุกหน้าที่ render แล้วไม่มี span เลย) ซ่อนทั้งปุ่ม HIGHLIGHT และเมนูรูปแบบมาร์ก ผ่าน visibleTools ที่กรอง TOOLS - scannedOnly เป็น latch: entry ของ pageSpanCount สะสมต่อหน้า ไม่ลบตอน virtualization unmount (รีเซ็ตเฉพาะตอนสลับไฟล์) — เคยเจอหน้ามีข้อความแม้หน้าเดียว ปุ่มกลับมาค้าง (ไฟล์ผสมสแกนนำหน้าโผล่ครั้งเดียวพอ ไม่โผล่-หายตามหน้าที่เปิดดู) - กันทางเข้าที่เหลือของ tool นี้: คีย์ลัด H โดน guard ที่ switchTool และ tool ที่ค้าง active ถูก reset กลับ select 2 จุด (effect ตอน scannedOnly กลายเป็น true ระหว่าง ใช้งาน + ตอนสลับมาเป็นไฟล์ภาพขณะ tool active — dynamic param เปลี่ยน Next reuse component ไม่ reset state) - แถบ hint M6 ภาพสแกน เหลือเป็น defensive ช่วง transition เท่านั้น - sync .claude/rules/pdf-viewer.md (กติกา N3 แถว toolbar) Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
3a06557bd4
commit
9ba8f0a8ec
2 changed files with 35 additions and 9 deletions
|
|
@ -34,4 +34,4 @@ paths:
|
|||
- TEXTBOX กล่องกว้างคงที่ (`width?` สไตล์ Smallpdf/Acrobat): กล่องที่สร้างใหม่คลิกเดียวได้ `width = min(TEXTBOX_DEFAULT_WIDTH_PCT=30, textboxMaxWidthPct)` — **ลากขอบซ้าย/ขวาของกรอบ selection = ปรับความกว้าง** (mode `wleft`/`wright` ใน AnnotationSelectionLayer: ขอบซ้ายขยับ = เลื่อนกล่อง+เปลี่ยนกว้าง (`position.x` = ขอบซ้ายตรง ๆ), ขอบขวาขยับ = เปลี่ยนกว้างอย่างเดียว, clamp กว้าง 2–50% และอยู่ในหน้า) ฟอนต์คงขนาด ข้อความ wrap ใหม่ ส่วนสูงตามจำนวนบรรทัดอัตโนมัติ — กล่องแบบนี้**ซ่อนมุมกรอบ** (scale ไม่มีความหมาย) ย้ายกล่องใช้ขอบบน/ล่าง; กล่องเก่าที่ไม่มี `width` = shrink-to-fit หุ้มข้อความตามพฤติกรรมเดิมทั้งหมด; ฟอนต์ default ตอนสร้าง = `TEXTBOX_DEFAULT_FONT_SIZE_PCT` 2.5% (≈15px — เดิม 1.2% ≈ 7px อ่านไม่ออก และเล็กกว่า preset ต่ำสุด 10px ของตัวเอง) และเข้าโหมดแก้ข้อความได้จากปุ่ม "แก้ไขข้อความ" ในแผง selection (`onStartEdit`) นอกเหนือจาก double-click (จอสัมผัส iOS double-tap = zoom หน้า dblclick จึงใช้ไม่ได้)
|
||||
- คลิกเลือกบนหน้า: tool select/highlight คลิกบน annotation = `setSelectedId` ผ่าน `hitTestAnnotation` (DRAW/SHAPE ใช้ hit-test แม่นเดียวกับ eraser, HIGHLIGHT ดู rect, ที่เหลือ bbox+padding) — เช็คจากรายการหลังสุดก่อน (ตัวบนสุดชนะ), คลิกที่ว่าง = deselect; ใช้ `visibleAnnotations` (เคารพ filter รายคน F4)
|
||||
- Tooltip hover (N1): `onMouseMove` ของ page wrapper ทำ hit-test ชุดเดียวกับคลิก → `hoveredId` state **เดี่ยวระดับ root เปลี่ยนเฉพาะเมื่อ id เปลี่ยน** (ห้าม setState ทุก mousemove, hit-test เดินจากท้าย array ไม่ allocate ต่อ event) → tooltip "ชนิด · ผู้ทำ + โน้ต" ลอยข้าง bbox (`pointer-events: none` เสมอ, z-[5], ยกเว้น COMMENT) — ปิดช่วง tool ที่รับ pointer (`draw/shape/erase/redact/pan`), `e.buttons !== 0`, ตอน `openPinId !== null` (popover ของ pin เปิดอยู่) และ**เมื่อรายการที่ชี้ = `selectedId`** (แผง selection เปิดอยู่แถวนั้นแล้ว — เจอตอนลากคลุมจบแล้ว auto-select โผล่ที่ตำแหน่งเคอร์เซอร์พอดี ซ้อนเป็นสองกล่อง)
|
||||
- **N3 ไฟล์รูปภาพ (jpg/jpeg/png/tif — `fileKindFromUrl` จาก `utils/file-kind.ts`):** รูป**โหลดจาก static `pdfUrl` ตรง ๆ ไม่ผ่าน `/api/pdf`** (ไม่มี ToUnicode ให้ซ่อม — route นั้นมี defensive branch คืน bytes ดิบ + content-type รูป กัน stray call เข้า `fixPdfActualText`) — หน้ารูป render เป็น `<img>` แทน canvas ที่ z-1 (`pointer-events:none` เหมือน canvas — invariant #3, DOM order ไม่ขยับ) + **ไม่มี textLayer** (conditional render เฉพาะ pdf) → PdfPage เรียก `onTextLayerRendered(pageIndex, 0)` ให้ hint "ภาพสแกน" + custom selection จอสัมผัส bail เอง — **toolbar คงทุก tool รวม HIGHLIGHT** (คลุมข้อความบนรูปไม่ได้ = no-op มี hint อธิบาย); `pageSizes` จาก `naturalWidth/Height` (browser คิด EXIF orientation ให้แล้ว) **normalize กว้าง `IMAGE_PAGE_WIDTH`=595** สัดส่วนเดิม — scale contract เดียวกับ export (`utils/image-to-pdf.ts`) ให้ zoom %/fit-width clamp 0.5–3/fontSize % ทำงานเหมือนหน้า A4; TIFF decode ผ่าน `utif2` **dynamic import เฉพาะไฟล์ tif** (pattern เดียวกับ invariant #6) → หนึ่ง PNG blob URL ต่อเฟรม (**หลายเฟรม = หลายหน้า**) และ **revoke ทุก blob URL ตอน cleanup ของ load effect**; เฟรมที่ decode พัง = `src: null` → placeholder เทาแต่ขนาดหน้ายังเอาจาก IFD header ได้
|
||||
- **N3 ไฟล์รูปภาพ (jpg/jpeg/png/tif — `fileKindFromUrl` จาก `utils/file-kind.ts`):** รูป**โหลดจาก static `pdfUrl` ตรง ๆ ไม่ผ่าน `/api/pdf`** (ไม่มี ToUnicode ให้ซ่อม — route นั้นมี defensive branch คืน bytes ดิบ + content-type รูป กัน stray call เข้า `fixPdfActualText`) — หน้ารูป render เป็น `<img>` แทน canvas ที่ z-1 (`pointer-events:none` เหมือน canvas — invariant #3, DOM order ไม่ขยับ) + **ไม่มี textLayer** (conditional render เฉพาะ pdf) → PdfPage เรียก `onTextLayerRendered(pageIndex, 0)` ให้ hint "ภาพสแกน" + custom selection จอสัมผัส bail เอง — **toolbar ซ่อน tool มาร์กข้อความ (HIGHLIGHT) ทั้งปุ่มและเมนูรูปแบบเมื่อไม่มีข้อความให้คลุม** — ทั้งไฟล์ภาพและ **PDF สแกนล้วน** (คำขอผู้ใช้ 2026-09-22 แทนแผนเดิมที่คงไว้พร้อม hint): `hideHighlightTool` = ไฟล์ภาพ หรือ `scannedOnly` = ทุกหน้าที่ render แล้วไม่มี span เลย (entry ของ `pageSpanCount` สะสมต่อหน้า ไม่ลบตอน virtualization unmount = **latch**: เคยเจอหน้ามีข้อความแม้หน้าเดียว ไฟล์ถือว่ามีข้อความ ปุ่มกลับมาค้าง — ไฟล์ผสมสแกนนำหน้าโผล่ครั้งเดียวพอ ไม่โผล่-หายตามหน้าที่เปิดดู) — กันคีย์ลัด H ที่ `switchTool` + reset กลับ "select" ทั้งตอนสลับมาเป็นไฟล์ภาพขณะ tool นี้ active (dynamic param เปลี่ยน = reuse component ไม่ reset state) และ effect ตอน `scannedOnly` กลายเป็น true; แถบ hint M6 "ภาพสแกน" เหลือเป็น defensive ช่วง transition เท่านั้น; `pageSizes` จาก `naturalWidth/Height` (browser คิด EXIF orientation ให้แล้ว) **normalize กว้าง `IMAGE_PAGE_WIDTH`=595** สัดส่วนเดิม — scale contract เดียวกับ export (`utils/image-to-pdf.ts`) ให้ zoom %/fit-width clamp 0.5–3/fontSize % ทำงานเหมือนหน้า A4; TIFF decode ผ่าน `utif2` **dynamic import เฉพาะไฟล์ tif** (pattern เดียวกับ invariant #6) → หนึ่ง PNG blob URL ต่อเฟรม (**หลายเฟรม = หลายหน้า**) และ **revoke ทุก blob URL ตอน cleanup ของ load effect**; เฟรมที่ decode พัง = `src: null` → placeholder เทาแต่ขนาดหน้ายังเอาจาก IFD header ได้
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue