fix(note): address code review findings
- restoreVersion: ผ่าน validateAnnotationData ก่อน insert สาขา "ต้นทางถูกลบ" ให้สมมาตรกับสาขา update (invariant #8) - PDFViewer: track timer ล้าง exportError ใน ref — กัน export พัง สองรอบติดกันแล้ว timer รอบแรกเคลียร์ error รอบหลังก่อนเวลา - useHistory: เพิ่ม onError — undo/redo ล้มแสดง toast ผ่าน showActionError แทนหายเงียบ ๆ - DebugConsole: ไม่โหลด Eruda จาก CDN ใน production build (ระบบ intranet + token อยู่ใน origin เดียวกัน) - NoteHome: ตัด dead state session ที่ render ไม่ได้อ่าน - note-auth: export SSO_REQUIRED_BANNER ให้หน้า gate ใช้ตรง ๆ ถอด non-null assertion ใน AnnotateView + bookmarkDepthOf Verify: npx tsc --noEmit ผ่าน · vitest 317/317 ผ่าน Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
d37bc2a3f0
commit
2d466efd4f
7 changed files with 50 additions and 17 deletions
|
|
@ -1335,6 +1335,7 @@ export default function PDFViewer({
|
|||
// F8: Export PDF ดาวน์โหลดในแท็บเดิม (fetch → blob → <a download>) ไม่เปิดแท็บใหม่
|
||||
const [exporting, setExporting] = useState(false);
|
||||
const [exportError, setExportError] = useState<string | null>(null);
|
||||
const exportErrorTimerRef = useRef<number | null>(null);
|
||||
/** H1 (UX audit 2026-09-16): error ล่าสุดของการบันทึก/แก้ไข/ลบ annotation — เดิม catch
|
||||
* ทุกตัวมีแต่ console.error ผู้ใช้เห็นรายการหายเงียบ ๆ (React rollback optimistic)
|
||||
* โดยไม่รู้เลยว่าบันทึกไม่สำเร็จ */
|
||||
|
|
@ -1448,7 +1449,14 @@ export default function PDFViewer({
|
|||
redo: redoHistory,
|
||||
canUndo,
|
||||
canRedo,
|
||||
} = useHistory();
|
||||
} = useHistory({
|
||||
onError: (_err, kind) =>
|
||||
showActionError(
|
||||
kind === "undo"
|
||||
? "เรียกคืนไม่สำเร็จ — ตรวจสอบการเชื่อมต่อแล้วลองอีกครั้ง"
|
||||
: "ทำซ้ำไม่สำเร็จ — ตรวจสอบการเชื่อมต่อแล้วลองอีกครั้ง",
|
||||
),
|
||||
});
|
||||
|
||||
// Optimistic update (invariant #9): ใช้ useOptimistic ภายใน startTransition
|
||||
// React ถอด optimistic row ออกอัตโนมัติเมื่อ action เสร็จ + rollback เองเมื่อล้มเหลว
|
||||
|
|
@ -1690,7 +1698,13 @@ export default function PDFViewer({
|
|||
} catch (err) {
|
||||
console.error("export PDF ไม่สำเร็จ", err);
|
||||
setExportError("Export PDF ไม่สำเร็จ — ลองอีกครั้ง (ไฟล์อาจใหญ่เกินหรือต้นฉบับเสียหาย)");
|
||||
window.setTimeout(() => setExportError(null), 6000);
|
||||
// track handle เหมือน actionErrorTimerRef — กัน export พังสองรอบติดกันแล้ว
|
||||
// timer รอบแรกเคลียร์ error ของรอบหลังก่อนเวลา
|
||||
if (exportErrorTimerRef.current !== null) window.clearTimeout(exportErrorTimerRef.current);
|
||||
exportErrorTimerRef.current = window.setTimeout(() => {
|
||||
exportErrorTimerRef.current = null;
|
||||
setExportError(null);
|
||||
}, 6000);
|
||||
} finally {
|
||||
setExporting(false);
|
||||
}
|
||||
|
|
@ -2461,8 +2475,12 @@ export default function PDFViewer({
|
|||
function bookmarkDepthOf(b: BookmarkDTO): number {
|
||||
let depth = 1;
|
||||
let cur: BookmarkDTO | undefined = b;
|
||||
while (cur?.parentId && depth <= 100) {
|
||||
const parent = optimisticBookmarks.find((x) => x.id === cur!.parentId);
|
||||
while (cur !== undefined && depth <= 100) {
|
||||
// annotate ชัดกัน TS7022 — inference ของ cur วนอ้าง parent ที่อ้าง
|
||||
// optimisticBookmarks ซึ่งยัง infer ไม่เสร็จ (function ถูกใช้ก่อนประกาศ)
|
||||
const pid: string | null = cur.parentId;
|
||||
if (!pid) break;
|
||||
const parent: BookmarkDTO | undefined = optimisticBookmarks.find((x) => x.id === pid);
|
||||
if (!parent) break;
|
||||
depth += 1;
|
||||
cur = parent;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue