FIX: Media Explorer panel preview nút Synth cho phép lọc nhanh nhạc cụ
This commit is contained in:
+40
-2
@@ -9311,6 +9311,7 @@ const MediaExplorerPanel = ({ height, clipboardRef }) => {
|
||||
return saved ? JSON.parse(saved) : null;
|
||||
}());
|
||||
const [synthOpen, setSynthOpen] = React.useState(false);
|
||||
const [synthFilter, setSynthFilter] = React.useState('');
|
||||
const [synthList, setSynthList] = React.useState(null);
|
||||
const [synthLoading, setSynthLoading] = React.useState(false);
|
||||
const synthListRef = React.useRef(null);
|
||||
@@ -9840,6 +9841,7 @@ const MediaExplorerPanel = ({ height, clipboardRef }) => {
|
||||
|
||||
const toggleSynthDropdown = () => {
|
||||
if (synthOpen) { setSynthOpen(false); return; }
|
||||
setSynthFilter(''); // Clear search filter on open
|
||||
setSynthOpen(true);
|
||||
if (synthListRef.current) return;
|
||||
setSynthLoading(true);
|
||||
@@ -9874,6 +9876,19 @@ const MediaExplorerPanel = ({ height, clipboardRef }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const filteredSynthList = React.useMemo(() => {
|
||||
if (!synthList) return [];
|
||||
if (!synthFilter.trim()) return synthList;
|
||||
const query = synthFilter.toLowerCase().trim();
|
||||
return synthList.map(group => {
|
||||
const presets = (group.presets || []).filter(p =>
|
||||
(p.name || '').toLowerCase().includes(query) ||
|
||||
String(p.program).includes(query)
|
||||
);
|
||||
return { ...group, presets };
|
||||
}).filter(group => group.presets.length > 0);
|
||||
}, [synthList, synthFilter]);
|
||||
|
||||
const playMidiPreview = async (f, token) => {
|
||||
// Play real MIDI file through selected synth instrument (SonicSF)
|
||||
if (!f || !window.SonicSF) return;
|
||||
@@ -10451,10 +10466,30 @@ const MediaExplorerPanel = ({ height, clipboardRef }) => {
|
||||
</button>
|
||||
{synthOpen && (
|
||||
<div className="absolute bottom-8 left-0 z-40 w-64 bg-white border border-[#808080] shadow-xl rounded-sm text-xs text-slate-800 font-sans max-h-72 overflow-y-auto">
|
||||
<div className="sticky top-0 bg-[#e0e0e0] px-2 py-1 font-bold border-b border-[#a0a0a0] flex items-center justify-between">
|
||||
<div className="sticky top-0 bg-[#e0e0e0] px-2 py-1 font-bold border-b border-[#a0a0a0] flex items-center justify-between z-20">
|
||||
<span>Select Instrument</span>
|
||||
<button onClick={() => setSynthOpen(false)} className="text-slate-500 hover:text-slate-900"><i className="fa-solid fa-xmark"></i></button>
|
||||
</div>
|
||||
{/* SEARCH INPUT */}
|
||||
<div className="sticky top-[23px] bg-white p-1 border-b border-[#c0c0c0] z-20 flex items-center gap-1">
|
||||
<i className="fa-solid fa-magnifying-glass text-slate-400 pl-1 text-[10px]"></i>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Tìm nhạc cụ..."
|
||||
value={synthFilter}
|
||||
onChange={e => setSynthFilter(e.target.value)}
|
||||
onClick={e => e.stopPropagation()}
|
||||
className="w-full px-1 py-0.5 border border-[#c0c0c0] rounded-sm text-xs font-sans focus:outline-none focus:border-blue-500"
|
||||
/>
|
||||
{synthFilter && (
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); setSynthFilter(''); }}
|
||||
className="text-slate-400 hover:text-slate-700 px-1"
|
||||
>
|
||||
<i className="fa-solid fa-xmark text-[10px]"></i>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{synthLoading && <div className="px-2 py-2 text-slate-400 italic">Loading...</div>}
|
||||
{!synthLoading && (!synthList || synthList.length === 0) && (
|
||||
<div className="px-2 py-2 text-slate-400 italic">Không có SoundFont nào</div>
|
||||
@@ -10462,7 +10497,7 @@ const MediaExplorerPanel = ({ height, clipboardRef }) => {
|
||||
<div className={`flex items-center gap-1 px-2 py-1 cursor-pointer hover:bg-blue-100 ${!synthInst ? 'bg-slate-200' : ''}`} onClick={() => selectSynthInst(null)}>
|
||||
<i className="fa-solid fa-ban text-slate-400"></i> None (mặc định)
|
||||
</div>
|
||||
{!synthLoading && synthList && synthList.map(group => (
|
||||
{!synthLoading && filteredSynthList && filteredSynthList.map(group => (
|
||||
<div key={group.sf.id || group.sf.name}>
|
||||
<div className="px-2 py-1 bg-[#f0f0f0] font-semibold text-slate-600 border-t border-[#e0e0e0] truncate">{group.sf.display || group.sf.name || group.sf.id}</div>
|
||||
{(group.presets || []).slice(0, 200).map((p, pi) => {
|
||||
@@ -10476,6 +10511,9 @@ const MediaExplorerPanel = ({ height, clipboardRef }) => {
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
{!synthLoading && filteredSynthList && filteredSynthList.length === 0 && synthFilter && (
|
||||
<div className="px-2 py-2 text-slate-400 italic">Không tìm thấy nhạc cụ trùng khớp</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user