Edit mode: guard editLoadSeq chong race nap trang (chuyen trang/zoom nhanh - luot cham khong duoc de luot moi) + docs vong 5
Build Windows portable / build (push) Canceled after 0s
Build Windows portable / build (push) Canceled after 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -460,10 +460,12 @@ function scheduleEditSharpRender() {
|
|||||||
clearTimeout(editSharpTimer);
|
clearTimeout(editSharpTimer);
|
||||||
editSharpTimer = setTimeout(async () => {
|
editSharpTimer = setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
|
const seq = editLoadSeq;
|
||||||
const p = state.pages[state.editPage];
|
const p = state.pages[state.editPage];
|
||||||
const url = await invoke("render_page", {
|
const url = await invoke("render_page", {
|
||||||
path: state.editBase, page: state.editPage, width: editStageWidth(p),
|
path: state.editBase, page: state.editPage, width: editStageWidth(p),
|
||||||
});
|
});
|
||||||
|
if (seq !== editLoadSeq) return; // trang/file đã đổi trong lúc render
|
||||||
$("editImg").src = url;
|
$("editImg").src = url;
|
||||||
} catch (_) { /* giữ ảnh cũ (đã co giãn CSS) */ }
|
} catch (_) { /* giữ ảnh cũ (đã co giãn CSS) */ }
|
||||||
}, 220);
|
}, 220);
|
||||||
@@ -2185,7 +2187,11 @@ async function onViewerDblClick(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Đọc lại object + render ảnh trang hiện tại từ editBase, dựng overlay box.
|
// Đọc lại object + render ảnh trang hiện tại từ editBase, dựng overlay box.
|
||||||
|
// Guard số thứ tự: chuyển trang/zoom nhanh tạo nhiều lượt nạp song song —
|
||||||
|
// chỉ lượt MỚI NHẤT được ghi vào DOM/state (lượt chậm về sau bị bỏ).
|
||||||
|
let editLoadSeq = 0;
|
||||||
async function loadEditPage() {
|
async function loadEditPage() {
|
||||||
|
const mySeq = ++editLoadSeq;
|
||||||
const p = state.pages[state.editPage];
|
const p = state.pages[state.editPage];
|
||||||
const stageW = editStageWidth(p);
|
const stageW = editStageWidth(p);
|
||||||
state.editScale = stageW / p.widthPt;
|
state.editScale = stageW / p.widthPt;
|
||||||
@@ -2194,6 +2200,7 @@ async function loadEditPage() {
|
|||||||
invoke("render_page", { path: state.editBase, page: state.editPage, width: stageW }),
|
invoke("render_page", { path: state.editBase, page: state.editPage, width: stageW }),
|
||||||
invoke("edit_list_objects", { path: state.editBase, page: state.editPage, password: null }),
|
invoke("edit_list_objects", { path: state.editBase, page: state.editPage, password: null }),
|
||||||
]);
|
]);
|
||||||
|
if (mySeq !== editLoadSeq) return; // đã có lượt nạp mới hơn — bỏ lượt này
|
||||||
// Object nằm TRONG Form XObject (file Canva/Illustrator): sửa/xoá text
|
// Object nằm TRONG Form XObject (file Canva/Illustrator): sửa/xoá text
|
||||||
// được xử lý bằng PHẪU THUẬT stream ở engine (trong suốt với UI) — không
|
// được xử lý bằng PHẪU THUẬT stream ở engine (trong suốt với UI) — không
|
||||||
// cần mở gói trang.
|
// cần mở gói trang.
|
||||||
|
|||||||
@@ -77,6 +77,28 @@ Máy dev không có Rust nên **CI là nơi duy nhất chạy test**: workflow t
|
|||||||
bước `cargo test -p ff-engine` TRƯỚC khi build release (fail test = fail
|
bước `cargo test -p ff-engine` TRƯỚC khi build release (fail test = fail
|
||||||
build, không publish bản hỏng); cache thêm `target/` gốc workspace.
|
build, không publish bản hỏng); cache thêm `target/` gốc workspace.
|
||||||
|
|
||||||
|
### Vòng 5 — zoom/chuyển trang trong chế độ sửa + dòng lẫn nhiều style
|
||||||
|
Ba vấn đề user báo (kiểm chứng E2E build 29 trên file dịch 3 trang):
|
||||||
|
- **Zoom**: stage sửa hết cứng 820px — `editZoom` riêng (kế thừa zoom viewer),
|
||||||
|
Ctrl+wheel/nút ±/dropdown %/Vừa rộng/Vừa trang đều chạy; co giãn CSS ngay,
|
||||||
|
render nét sau 220ms; `margin:auto` fix flex-center overflow. Kiểm: 794→1191px.
|
||||||
|
- **Chuyển trang**: ▲▼/ô nhập trang nhận biết edit mode (`switchEditPage` —
|
||||||
|
giữ undo/thay đổi trang khác vì chung editBase); guard `editLoadSeq` cho
|
||||||
|
loadEditPage/sharp-render: lượt nạp chậm không đè lượt mới (race khi
|
||||||
|
chuyển trang/zoom nhanh). Kiểm: Trang 2 · 114 đối tượng.
|
||||||
|
- **Dòng lẫn style (thường + mono-đậm…)**: ô sửa dựng SPAN theo nhóm run
|
||||||
|
cùng style (styleKeyOf/styleGroupsOfLine) — WYSIWYG từng phần; commit đọc
|
||||||
|
đoạn-style (`readRich`, text node trần mượn span kề), ≥2 style gửi
|
||||||
|
`richLines`. Engine: `ReflowText.rich` — resolve thang giữ-font RIÊNG cho
|
||||||
|
từng style-run, token hoá theo từ (giữ glue giữa đoạn dính liền), bẻ dòng
|
||||||
|
chung, vẽ mỗi cụm cùng-style 1 object đúng font/cỡ/màu + tự kiểm/fallback
|
||||||
|
từng từ. Tầng-0 token gốc tắt khi KHỐI có run nested (token vô hiệu sau
|
||||||
|
mở lại document hậu phẫu thuật — trước chỉ xét anchor). Kiểm trên dòng
|
||||||
|
"Hiển thị `vmDetails.vm.windowsInitialPassword`.": ô sửa 3 span đúng
|
||||||
|
style; sau commit mono giữ NotoSansMono-Bold, "." giữ NotoSans-Regular
|
||||||
|
(token gốc), phần sửa sang Arial hợp lệ (subset gốc thiếu glyph Ể hoa).
|
||||||
|
Test engine: fixture Helvetica + Courier-Bold cùng dòng.
|
||||||
|
|
||||||
### CỔNG AN TOÀN + giới hạn ghi nhận (iteration 4 v1)
|
### CỔNG AN TOÀN + giới hạn ghi nhận (iteration 4 v1)
|
||||||
Kiểm chứng E2E trên file Canva THẬT (CV, 1149 object sau mở gói) phát hiện:
|
Kiểm chứng E2E trên file Canva THẬT (CV, 1149 object sau mở gói) phát hiện:
|
||||||
**generator của PDFium ghi lại cả trang là LOSSY với file phức tạp**:
|
**generator của PDFium ghi lại cả trang là LOSSY với file phức tạp**:
|
||||||
|
|||||||
Reference in New Issue
Block a user