# 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()`)