เลือก annotation บนหน้า PDF → sidebar ตามไปเน้นรายการนั้น + สร้างเสร็จเลือกให้ทันที + กัน duplicate ชั่วขณะตอนสร้าง: (1) ส่ง selectedId ให้ AnnotationSidebar — ไฮไลต์แถว (ทั้งลิสต์หลักและผลค้นหา) + scrollIntoView block:nearest + สลับมาแท็บ Annotations ให้เองถ้ากำลังอยู่ Bookmarks (rAF รอแถว render หลังสลับแท็บค่อยเลื่อน) (2) AUTO_SELECT_TYPES — สร้าง DRAW/SHAPE/TEXTBOX/STAMP/HIGHLIGHT/REDACTION เสร็จ = เลือกตัวใหม่ทันทีด้วย saved.id (กรอบ selection + sidebar ตามไปเลย; COMMENT ยกเว้นเพราะ composer/pin ทำหน้าที่นั้นอยู่แล้ว) — แก้ปัญหา "วาดเสร็จคลิกที่เส้น tool ยังเป็นวาด sidebar นิ่ง" (3) กันอาการ row โผล่แล้วหาย (0→2→1): เดิม optimistic row กับ row จาก server คนละ id ทำให้ SSE event มาก่อน action เสร็จ dedupe ไม่ได้ — ตอนนี้ client ส่ง id ของ optimistic row ให้ createAnnotation ใช้ซ้ำ (validate UUID, ไม่ส่ง = สุ่มเองตามเดิมสำหรับ redo path) ทุกชั้น dedupe ด้วย id เดียวกันตั้งแต่แรก — sync PLAN.md §4 + rules/realtime.md ให้ตรงพฤติกรรมใหม่
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
4934b9d0b3
commit
6ddc35d6d5
5 changed files with 67 additions and 12 deletions
|
|
@ -40,6 +40,9 @@ export type CreateAnnotationInput = {
|
|||
userName: string;
|
||||
type: AnnotationType;
|
||||
data: AnnotationData;
|
||||
/** id ที่ client สร้าง (crypto.randomUUID) ของ optimistic row — ให้ server ใช้ id เดียวกัน
|
||||
* จะได้ไม่เห็นรายการ duplicate ชั่วขณะ (row ชั่วคราว + row จริงคนละ id) — ไม่ส่ง = สร้างใหม่ */
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type CreateBookmarkInput = {
|
||||
|
|
@ -407,11 +410,19 @@ export async function createAnnotation(input: CreateAnnotationInput): Promise<An
|
|||
}
|
||||
const type = raw.type as AnnotationType;
|
||||
const data = validateAnnotationData(type, raw?.data);
|
||||
// id จาก client (ถ้ามา) = id ของ optimistic row — SSE event/dedupe ทุกฝั่งเทียบ id เดียวกัน
|
||||
const id = typeof raw?.id === "string" ? vUuid(raw.id, "id") : undefined;
|
||||
|
||||
const [row] = await db
|
||||
.insert(annotations)
|
||||
.values({ fileId, pageIndex, userId, userName, type, data })
|
||||
.returning();
|
||||
const values: typeof annotations.$inferInsert = {
|
||||
fileId,
|
||||
pageIndex,
|
||||
userId,
|
||||
userName,
|
||||
type,
|
||||
data,
|
||||
};
|
||||
if (id) values.id = id;
|
||||
const [row] = await db.insert(annotations).values(values).returning();
|
||||
const dto = toAnnotationDTO(row);
|
||||
publishAnnotateEvent(fileId, { table: "annotations", action: "create", row: dto });
|
||||
revalidateFilePages(fileId);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue