fix(editor): an unsaved project can't inherit phantom barline locks - #294
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughBeat-lock persistence no longer uses a shared localStorage key for unsaved projects. Save and restore paths remove legacy blank-key residue, clear active locks, and tests cover loaded-project restoration and unsaved-project isolation. ChangesBeat-lock persistence
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
0993e40 to
8724902
Compare
9c0a04f to
f7f6f85
Compare
…s, +6 dB Replaces the docked mixer side-panel with #285's bottom mixer DRAWER: a horizontal row of vertical channel strips (one per stem + transcription part), each a live level meter beside a rotated fader, followed by the SOURCE/GUIDE/CLICK utility buses and a dedicated MASTER output strip. Rises on open, falls on close (reduced-motion aware); opens closed each session (a per-screen view toggle, not a saved pref). Metering: an AnalyserNode taps each bus + per-stem gain (a zero-gain sink keeps the browser processing them without a second audible copy); audioMixerMeterLevels reads RMS→−60..0 dBFS levels + peak dB each frame; the panel's rAF tick fills the bars with instant-attack/gravity-decay ballistics and a peak-hold clip readout. A master gain sits post-limiter (limiter → masterGain → destination); the reference joins there too, so the recording is metered and master-trimmed but STILL never through the limiter (a hot recording is never colored). Per-stem taps drop on song switch; bus taps persist. Headroom: the fader range is 0..106 — 0..100 linear to unity, 100..106 a log map to +6 dB. partStripState/clapState resolve vol through _mixerGainForFaderPure, so stems and synth parts alike can be pushed to +6 dB; every fader reads dB. The selected Tracks-column row lights its matching strip. Removed the vestigial edit-blip toggle. Faithful port of #285's mixer design onto the current main. Tests: mixer_meters.test.mjs (level/peak/ballistics/dB pures); mixer_panel reconciled to the +6 dB clamp, dB labels, master bus, animated close, and always-closed init; audio_mixer/loop_ab sliced envs inject the meter-tap stub and assert the new post-limiter ref routing. 184 JS suites, 291 pytest, lint 0 errors. Stacked on fix/editor-beat-lock-guard (#294) → the meters/+6dB correction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q
8724902 to
31c7381
Compare
f7f6f85 to
2ca32ac
Compare
…s, +6 dB Replaces the docked mixer side-panel with #285's bottom mixer DRAWER: a horizontal row of vertical channel strips (one per stem + transcription part), each a live level meter beside a rotated fader, followed by the SOURCE/GUIDE/CLICK utility buses and a dedicated MASTER output strip. Rises on open, falls on close (reduced-motion aware); opens closed each session (a per-screen view toggle, not a saved pref). Metering: an AnalyserNode taps each bus + per-stem gain (a zero-gain sink keeps the browser processing them without a second audible copy); audioMixerMeterLevels reads RMS→−60..0 dBFS levels + peak dB each frame; the panel's rAF tick fills the bars with instant-attack/gravity-decay ballistics and a peak-hold clip readout. A master gain sits post-limiter (limiter → masterGain → destination); the reference joins there too, so the recording is metered and master-trimmed but STILL never through the limiter (a hot recording is never colored). Per-stem taps drop on song switch; bus taps persist. Headroom: the fader range is 0..106 — 0..100 linear to unity, 100..106 a log map to +6 dB. partStripState/clapState resolve vol through _mixerGainForFaderPure, so stems and synth parts alike can be pushed to +6 dB; every fader reads dB. The selected Tracks-column row lights its matching strip. Removed the vestigial edit-blip toggle. Faithful port of #285's mixer design onto the current main. Tests: mixer_meters.test.mjs (level/peak/ballistics/dB pures); mixer_panel reconciled to the +6 dB clamp, dB labels, master bus, animated close, and always-closed init; audio_mixer/loop_ab sliced envs inject the meter-tap stub and assert the new post-limiter ref routing. 184 JS suites, 291 pytest, lint 0 errors. Stacked on fix/editor-beat-lock-guard (#294) → the meters/+6dB correction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q
31c7381 to
2c59788
Compare
2ca32ac to
dc58021
Compare
…s, +6 dB Replaces the docked mixer side-panel with #285's bottom mixer DRAWER: a horizontal row of vertical channel strips (one per stem + transcription part), each a live level meter beside a rotated fader, followed by the SOURCE/GUIDE/CLICK utility buses and a dedicated MASTER output strip. Rises on open, falls on close (reduced-motion aware); opens closed each session (a per-screen view toggle, not a saved pref). Metering: an AnalyserNode taps each bus + per-stem gain (a zero-gain sink keeps the browser processing them without a second audible copy); audioMixerMeterLevels reads RMS→−60..0 dBFS levels + peak dB each frame; the panel's rAF tick fills the bars with instant-attack/gravity-decay ballistics and a peak-hold clip readout. A master gain sits post-limiter (limiter → masterGain → destination); the reference joins there too, so the recording is metered and master-trimmed but STILL never through the limiter (a hot recording is never colored). Per-stem taps drop on song switch; bus taps persist. Headroom: the fader range is 0..106 — 0..100 linear to unity, 100..106 a log map to +6 dB. partStripState/clapState resolve vol through _mixerGainForFaderPure, so stems and synth parts alike can be pushed to +6 dB; every fader reads dB. The selected Tracks-column row lights its matching strip. Removed the vestigial edit-blip toggle. Faithful port of #285's mixer design onto the current main. Tests: mixer_meters.test.mjs (level/peak/ballistics/dB pures); mixer_panel reconciled to the +6 dB clamp, dB labels, master bus, animated close, and always-closed init; audio_mixer/loop_ab sliced envs inject the meter-tap stub and assert the new post-limiter ref routing. 184 JS suites, 291 pytest, lint 0 errors. Stacked on fix/editor-beat-lock-guard (#294) → the meters/+6dB correction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/beat_lock.test.mjs (1)
224-247: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the changed save path.
These tests exercise
_restoreBeatLocks, but do not visibly drive_saveBeatLocks()through its new unsaved-project branch atsrc/tempo.jsLines [3188-3190]. Add a test asserting that saving an unsaved project removes legacyeditorBeatLocks:residue and never writes a blank key; also verify named projects still save under their filename-specific key.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/beat_lock.test.mjs` around lines 224 - 247, Add coverage that invokes _saveBeatLocks for an unsaved project and verifies any legacy editorBeatLocks: residue is removed without writing a blank-key entry. Also invoke the save path with a non-empty S.filename and assert locks are persisted under the filename-specific editorBeatLocks key, preserving existing named-project behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/beat_lock.test.mjs`:
- Around line 224-247: Add coverage that invokes _saveBeatLocks for an unsaved
project and verifies any legacy editorBeatLocks: residue is removed without
writing a blank-key entry. Also invoke the save path with a non-empty S.filename
and assert locks are persisted under the filename-specific editorBeatLocks key,
preserving existing named-project behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 4abf4e09-cba7-4dc7-af31-32862f178e32
📒 Files selected for processing (3)
CHANGELOG.mdsrc/tempo.jstests/beat_lock.test.mjs
b29ba0a to
559d766
Compare
Straggler from #291 (bulk barline locks) — a small beat-lock fix from #285 missed in the re-cut, surfaced when auditing feature parity.
_beatLockStorageKeyPurereturned the shared keyeditorBeatLocks:for a project with no filename yet, so barline locks set while charting one new import leaked into the next new import (both keyed by''). It now returnsnullfor an empty filename;_saveBeatLocks/_restoreBeatLockstreat null as "nowhere to persist" and scrub any legacy blank-key residue, so a fresh project always starts with a clean lock set.Stacked on #293 (the tip of the re-cut chain) for delivery; conceptually belongs to #291.
Tests:
beat_lock.test.mjsupdated — the storage-key case now assertsnullfor empty/nullish filenames (was the leaky bare prefix). 183 JS suites, lint 0 errors.🤖 Generated with Claude Code
https://claude.ai/code/session_01EBQCHCNA81E9tHmSDHSe2Q
Summary by CodeRabbit