diff --git a/FIX_DRAG_DROP_WINDOWS.md b/FIX_DRAG_DROP_WINDOWS.md new file mode 100644 index 0000000..bfcadd1 --- /dev/null +++ b/FIX_DRAG_DROP_WINDOWS.md @@ -0,0 +1,67 @@ +# Fix: Drag & drop MIDI file từ Explorer vào track (Windows/Tauri) + +Ngày: 2026-08-15 +Phạm vi: chỉ ghi đề xuất, chưa sửa code. Pull về Windows rồi sửa. + +## Triệu chứng +Trên Windows (bản Tauri), kéo file `.mid` từ Explorer vào timeline: +- Không tạo track, không toast, không console error. + +## Nguyên nhân gốc +1. Tauri default bật `drag_drop_handler_enabled = true`; app không gọi + `disable_drag_drop_handler()`. + - `tauri-2.11.1/src/webview/mod.rs:973-977` — doc ghi rõ: + "Disables the drag and drop handler. **This is required to use HTML5 + drag and drop APIs on the frontend on Windows.**" +2. Khi handler bật, `tauri-runtime-wry` bắt sự kiện drop và emit `DragDropEvent` + sang Rust (`tauri-runtime-wry-2.11.1/src/lib.rs:4861`), không đẩy vào DOM. +3. `wry-0.55.1/src/webview2/mod.rs:150-155` — khi có drag_drop_handler thì gọi + `SetAllowExternalDrop(false)` (comment: "Disable file drops, so our handler + can capture it"). +4. Kết quả: drop file OS vào WebView2 → HTML5 DnD không hoạt động → + `e.dataTransfer.files` rỗng tại `app/static/js/app.jsx:29994` và `:30034` + → `if (!f) return;` → im lặng. +5. App không xử lý `WindowEvent::DragDrop` ở Rust, không cài + `tauri-plugin-drag-drop` → drop OS file bị nuốt hoàn toàn. + +## Đã verify +- Logic JS drop đúng: chạy engine + headless chromium, dispatch drop event với + DataTransfer chứa `/static/midi/MIDI_Loop_01.mid` → tạo track + toast + "Đã tải MIDI: 1 track(s)" (ROWS 1→2). `parseMidiFile` OK (1 item, 48 notes). +- Drop từ Media Explorer trong app (dùng `window.__mediaExplorerDragFile` + + `resolveMediaExplorerDropFile`, app.jsx:24629, 15029) KHÔNG dùng + `dataTransfer.files` → không bị ảnh hưởng bởi `SetAllowExternalDrop(false)`, + vẫn hoạt động trên Windows. +- Drop trong browser thường (Linux dev): hoạt động. +- Section-tab/sub-tab timeline (~app.jsx:30600): KHÔNG có onDrop — drop vào + section tab không làm gì (bug phụ; wiki.md:1806 tuyên bố hỗ trợ nhưng code + không có). + +## Đề xuất sửa (chọn 1 trong 2; làm trên Windows) + +### Phương án A — Bật HTML5 DnD (đơn giản nhất) +Gọi `disable_drag_drop_handler()` khi tạo cửa sổ trong code Rust +(ví dụ `src-tauri/src/lib.rs`, trong builder WebviewWindow). Không có option +trong `tauri.conf.json` — phải sửa code. + +Sau khi gọi, WebView2 nhận drop như browser bình thường, JS handler tại +`app.jsx:29980` (container) và `:30024` (track row) tự chạy, không đổi JS. + +Lưu ý: mất event `WindowEvent::DragDrop` ở Rust (hiện không dùng). + +### Phương án B — Xử lý ở Rust, đẩy path sang JS +Giữ drag_drop_handler default, thêm `.on_window_event` (hoặc dùng +`tauri-plugin-drag-drop`) lắng nghe `WindowEvent::DragDrop(DragDropEvent::Drop(path))`, +emit path sang frontend (vd `emit("midi-drop", path)`), JS nhận và chạy nhánh +giống `resolveMediaExplorerDropFile` (dùng `mef.path`). +Phức tạp hơn A, cần thêm listener + code JS. + +## Bug phụ (nếu muốn sửa luôn) +Thêm `onDrop` cho section-tab/sub-tab timeline (~app.jsx:30600) giống handler +container/track row, để drop vào section tab cũng tạo track. + +## Vị trí file liên quan +- `app/static/js/app.jsx:29980` (onDrop container), `:30024` (onDrop track row) +- `app/static/js/app.jsx:29994`, `:30034` (điểm `dataTransfer.files[0]` check) +- `app/static/js/app.jsx:24629` `resolveMediaExplorerDropFile` +- `src-tauri/src/lib.rs` (nơi cần gọi `disable_drag_drop_handler()`)