FIX: Đã sắp xếp lại (v202608061030)
This commit is contained in:
+22
-10
@@ -7082,6 +7082,18 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
|||||||
}, []);
|
}, []);
|
||||||
const [keyTargetRoot, setKeyTargetRoot] = React.useState('C');
|
const [keyTargetRoot, setKeyTargetRoot] = React.useState('C');
|
||||||
const [keyTargetScale, setKeyTargetScale] = React.useState('major');
|
const [keyTargetScale, setKeyTargetScale] = React.useState('major');
|
||||||
|
// Auto-detect scale khi MỞ midi item → hiển thị ở dropdown chuyển giọng.
|
||||||
|
// Key theo st.target_id (item id) — sửa note cùng item KHÔNG reset lựa chọn
|
||||||
|
// của user; mở item khác → detect lại.
|
||||||
|
React.useEffect(() => {
|
||||||
|
const itemNotes = st.notes || [];
|
||||||
|
if (itemNotes.length) {
|
||||||
|
const k = detectKey(itemNotes);
|
||||||
|
setKeyTargetRoot(k.root);
|
||||||
|
setKeyTargetScale(k.scale);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [st.target_id]);
|
||||||
const applyTransposeToKey = React.useCallback(() => {
|
const applyTransposeToKey = React.useCallback(() => {
|
||||||
if (!notes || !notes.length) { showToast('Không có nốt nào để chuyển giọng.', 'warning'); return; }
|
if (!notes || !notes.length) { showToast('Không có nốt nào để chuyển giọng.', 'warning'); return; }
|
||||||
const srcKey = detectKey(notes);
|
const srcKey = detectKey(notes);
|
||||||
@@ -8550,7 +8562,13 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
|||||||
return showGhostNotes ? base + 'bg-purple-900/60 text-purple-300 border border-purple-700' : base + 'text-zinc-500 hover:text-zinc-300';
|
return showGhostNotes ? base + 'bg-purple-900/60 text-purple-300 border border-purple-700' : base + 'text-zinc-500 hover:text-zinc-300';
|
||||||
}(),
|
}(),
|
||||||
title: "Toggle ghost notes visibility"
|
title: "Toggle ghost notes visibility"
|
||||||
}, "\\uD83D\\uDC7B MIDI ghost notes"), React.createElement("div", {
|
}, "👻 MIDI ghost notes"), React.createElement("button", {
|
||||||
|
onClick: onClose,
|
||||||
|
className: "px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 border border-zinc-700 rounded text-xs flex items-center gap-1 transition ml-auto"
|
||||||
|
}, React.createElement("i", {
|
||||||
|
"data-lucide": "x",
|
||||||
|
className: "w-3 h-3"
|
||||||
|
}), "Đóng"), React.createElement("div", {
|
||||||
style: { flexBasis: "100%", height: 0 }
|
style: { flexBasis: "100%", height: 0 }
|
||||||
}), React.createElement("button", {
|
}), React.createElement("button", {
|
||||||
onClick: applyHumanize,
|
onClick: applyHumanize,
|
||||||
@@ -8588,8 +8606,8 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
|||||||
key: "btn", onClick: applyTransposeToKey,
|
key: "btn", onClick: applyTransposeToKey,
|
||||||
className: "px-2 py-1 rounded text-xs bg-violet-900/40 text-violet-300 border border-violet-700/60 hover:bg-violet-800/50 transition",
|
className: "px-2 py-1 rounded text-xs bg-violet-900/40 text-violet-300 border border-violet-700/60 hover:bg-violet-800/50 transition",
|
||||||
title: "Chuyển giọng: map degree hiện tại sang giọng đích (auto-detect key nguồn)"
|
title: "Chuyển giọng: map degree hiện tại sang giọng đích (auto-detect key nguồn)"
|
||||||
}, "\uD83C\uDFB5 Chuy\u1EC3n gi\u1ECDng")), React.createElement("div", {
|
}, "🎵 Chuyển giọng")), React.createElement("div", {
|
||||||
className: "flex items-center gap-1"
|
className: "flex items-center gap-1 ml-auto"
|
||||||
}, React.createElement("button", {
|
}, React.createElement("button", {
|
||||||
onClick: () => onSaveNotes(st.id, st.trackId, st.target_id, notes),
|
onClick: () => onSaveNotes(st.id, st.trackId, st.target_id, notes),
|
||||||
className: "px-2.5 py-1 bg-emerald-600 hover:bg-emerald-500 text-white rounded text-xs flex items-center gap-1 transition font-semibold"
|
className: "px-2.5 py-1 bg-emerald-600 hover:bg-emerald-500 text-white rounded text-xs flex items-center gap-1 transition font-semibold"
|
||||||
@@ -8643,13 +8661,7 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
|||||||
showToast('Đã xuất file MIDI!', 'success');
|
showToast('Đã xuất file MIDI!', 'success');
|
||||||
},
|
},
|
||||||
className: "px-2.5 py-1 bg-amber-700 hover:bg-amber-600 text-white rounded text-xs flex items-center gap-1 transition font-semibold"
|
className: "px-2.5 py-1 bg-amber-700 hover:bg-amber-600 text-white rounded text-xs flex items-center gap-1 transition font-semibold"
|
||||||
}, React.createElement("i", { "data-lucide": "file-down", className: "w-3 h-3" }), "Export"), React.createElement("button", {
|
}, React.createElement("i", { "data-lucide": "file-down", className: "w-3 h-3" }), "Export MIDI"))),
|
||||||
onClick: onClose,
|
|
||||||
className: "px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 border border-zinc-700 rounded text-xs flex items-center gap-1 transition"
|
|
||||||
}, React.createElement("i", {
|
|
||||||
"data-lucide": "x",
|
|
||||||
className: "w-3 h-3"
|
|
||||||
}), "Đóng"))),
|
|
||||||
|
|
||||||
/* 2. BAR RULER */
|
/* 2. BAR RULER */
|
||||||
React.createElement("div", {
|
React.createElement("div", {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -24,7 +24,7 @@
|
|||||||
<script src="/static/js/services/midiExtractor.js?v=202607281052"></script>
|
<script src="/static/js/services/midiExtractor.js?v=202607281052"></script>
|
||||||
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
|
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
|
||||||
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
|
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
|
||||||
<script src="/static/js/app.precompiled.js?v=202608060900" defer></script>
|
<script src="/static/js/app.precompiled.js?v=202608061030" defer></script>
|
||||||
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
|
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
|
|||||||
@@ -2022,3 +2022,22 @@
|
|||||||
- **Hàng 2:** 🎚 Humanize + [Nhẹ|Vừa|Mạnh], ±semis Transpose, [C..B][major|minor] 🎵 Chuyển giọng, Lưu, Export, Đóng.
|
- **Hàng 2:** 🎚 Humanize + [Nhẹ|Vừa|Mạnh], ±semis Transpose, [C..B][major|minor] 🎵 Chuyển giọng, Lưu, Export, Đóng.
|
||||||
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608060830), `wiki.md`. Rebuild precompiled.
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608060830), `wiki.md`. Rebuild precompiled.
|
||||||
- **Ghi chú/Test:** `npm run build` → hard refresh → mở piano roll → thấy 2 hàng toolbar; nút edit note (Humanize/Transpose/Chuyển giọng) ở hàng 2.
|
- **Ghi chú/Test:** `npm run build` → hard refresh → mở piano roll → thấy 2 hàng toolbar; nút edit note (Humanize/Transpose/Chuyển giọng) ở hàng 2.
|
||||||
|
|
||||||
|
### [2026-08-06 09:30] Task: Fix emoji double-escape — nút "MIDI ghost notes" hiện text \uD83D\uDC7B
|
||||||
|
- **Báo cáo user:** nút MIDI ghost notes hiện ký tự lạ "\uD83D\uDC7B" (text literal thay vì 👻).
|
||||||
|
- **Nguyên nhân:** file app.jsx có `"\\uD83D\\uDC7B MIDI ghost notes"` (escape KÉP → runtime render text literal).
|
||||||
|
- **FIX:** thay bằng emoji thật `"👻 MIDI ghost notes"`. Kiểm tra: các emoji khác (Humanize 🎚, Chuyển giọng 🎵, Session 🌐/Isolated 📋, Nhẹ/Vừa/Mạnh) đều single-escape ✓ — chỉ nút Ghost bị lỗi.
|
||||||
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608060930), `wiki.md`. Rebuild precompiled.
|
||||||
|
- **Ghi chú/Test:** `npm run build` → hard refresh → nút hiện "👻 MIDI ghost notes".
|
||||||
|
|
||||||
|
### [2026-08-06 10:00] Task: Auto-detect scale khi mở midi item → hiển thị ở dropdown chuyển giọng
|
||||||
|
- **Yêu cầu user:** mở midi item trong piano roll → detect scale + hiển thị ở dropdown scale chuyển giọng.
|
||||||
|
- **FIX (app.jsx):** effect trong PianoRollTabEditor — key `[st.target_id]` (item id): khi mở item → `detectKey(st.notes)` → `setKeyTargetRoot/KeyTargetScale` = giọng detected → dropdown chuyển giọng hiển thị đúng giọng của item. Sửa note cùng item KHÔNG reset (target_id không đổi); mở item khác → detect lại.
|
||||||
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608061000), `wiki.md`. Rebuild precompiled.
|
||||||
|
- **Ghi chú/Test:** `npm run build` → hard refresh → mở midi item → dropdown hiện giọng detected (vd D minor) → bấm Chuyển giọng sang giọng khác → Ctrl+Z.
|
||||||
|
|
||||||
|
### [2026-08-06 10:30] Task: Toolbar — Đóng sang cuối hàng TRÊN (phải), Lưu + Export MIDI cuối hàng DƯỚI (phải)
|
||||||
|
- **Yêu cầu user:** move Lưu/Export (đổi tên → Export MIDI) cuối hàng bên phải; Đóng → cuối hàng trên bên phải.
|
||||||
|
- **FIX (app.jsx):** nút Đóng chuyển từ cuối toolbar → SAU nút MIDI ghost notes (hàng 1) + `ml-auto` (đẩy phải); nhóm Lưu/Export giữ cuối hàng 2 + `ml-auto`; Export → **Export MIDI**. Emoji 🎵 Chuyển giọng bị patch tool double-escape → sửa bằng emoji thật (verify: 0 double-escape còn lại).
|
||||||
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608061030), `wiki.md`. Rebuild precompiled.
|
||||||
|
- **Ghi chú/Test:** `npm run build` → hard refresh → hàng 1 phải có [Đóng]; hàng 2 phải: [Lưu] [Export MIDI] ở cuối bên phải.
|
||||||
|
|||||||
Reference in New Issue
Block a user