Files
SonicForgeStudio/FIX_DRAG_DROP_WINDOWS.md

3.6 KiB

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