Skip to content

Commit aa93d16

Browse files
authored
Merge pull request #160 from espadonne/main
fix Activity 4 preset unlock and take duration display
2 parents f6c16e2 + 5645486 commit aa93d16

2 files changed

Lines changed: 39 additions & 10 deletions

File tree

components/audio/DAW/Multitrack/ClipEffectsRack.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,18 @@ export default function ClipEffectsRack({ show, onHide, selectedClipId, logOpera
356356
clips: selectedTrack.clips.map(c => c.id === selectedClipId ? updatedClip : c)
357357
});
358358

359-
// Log for study protocol (Activity 3)
359+
// Log for study protocol
360360
if (logOperation) {
361+
// eq_preset_applied unlocks Activity 3 Q5
361362
logOperation('eq_preset_applied', {
362363
clipId: selectedClipId,
363364
presetName: presetName
364365
});
366+
// Applying a preset is also applying an effect (Activity 4 requirement)
367+
logOperation('effect_applied', {
368+
clipId: selectedClipId,
369+
effectType: 'preset:' + presetName
370+
});
365371
}
366372
}, [selectedClip, selectedClipId, selectedTrack, updateTrack, logOperation]);
367373

components/audio/DAW/Multitrack/TakesImportModal.js

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,49 @@ export default function TakesImportModal({ show, onHide, takes = [] }) {
1717
useEffect(() => {
1818
if (!show || takes.length === 0) return;
1919

20+
const audioElements = [];
21+
2022
takes.forEach((take) => {
2123
if (take.duration > 0 || !take.audioURL || resolvedDurations[take.id] != null) return;
24+
25+
// For proxy / HTTP URLs, resolve duration via fetch + AudioContext decode
26+
// since <audio> preload='metadata' needs range-request support
27+
if (take.audioURL.startsWith('/api/') || take.audioURL.startsWith('http')) {
28+
fetch(take.audioURL)
29+
.then((r) => {
30+
if (!r.ok) throw new Error(`${r.status}`);
31+
return r.arrayBuffer();
32+
})
33+
.then((buf) => new AudioContext().decodeAudioData(buf))
34+
.then((decoded) => {
35+
if (decoded.duration && isFinite(decoded.duration)) {
36+
setResolvedDurations((prev) => ({ ...prev, [take.id]: decoded.duration }));
37+
}
38+
})
39+
.catch((err) =>
40+
console.warn(`TakesImportModal: duration resolve failed for ${take.id}:`, err.message),
41+
);
42+
return;
43+
}
44+
45+
// Blob URLs work fine with the Audio element approach
2246
const audio = new Audio();
2347
audio.preload = 'metadata';
2448
audio.onloadedmetadata = () => {
2549
if (audio.duration && isFinite(audio.duration)) {
2650
setResolvedDurations((prev) => ({ ...prev, [take.id]: audio.duration }));
2751
}
2852
};
53+
audio.onerror = () => {
54+
console.warn(`TakesImportModal: Audio metadata load failed for ${take.id}`);
55+
};
2956
audio.src = take.audioURL;
57+
audioElements.push(audio);
3058
});
59+
60+
return () => {
61+
audioElements.forEach((a) => { a.src = ''; });
62+
};
3163
}, [show, takes]);
3264

3365
// Update track name when take is selected
@@ -213,17 +245,8 @@ export default function TakesImportModal({ show, onHide, takes = [] }) {
213245
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
214246
};
215247

216-
// Mock data for testing if no takes provided
217248
const displayTakes = takes.length > 0 ? takes : [];
218249

219-
console.log('🎹 TakesImportModal: Received takes:', takes);
220-
console.log('🎹 TakesImportModal: Display takes:', displayTakes);
221-
222-
// Show helpful message if no takes
223-
if (displayTakes.length === 0 && takes.length === 0) {
224-
console.log('No takes available in TakesImportModal');
225-
}
226-
227250
return (
228251
<Modal show={show} onHide={onHide} size="lg" className="takes-import-modal">
229252
<Modal.Header closeButton className="bg-dark text-white">

0 commit comments

Comments
 (0)