Skip to content

editor: snap-grid upgrade wired through the shortcut-profile system (supersedes #46) - #62

Closed
ChrisBeWithYou wants to merge 1 commit into
mainfrom
feat/snap-grid-on-profile-stack
Closed

editor: snap-grid upgrade wired through the shortcut-profile system (supersedes #46)#62
ChrisBeWithYou wants to merge 1 commit into
mainfrom
feat/snap-grid-on-profile-stack

Conversation

@ChrisBeWithYou

Copy link
Copy Markdown
Contributor

Re-does #46 (editor-snap-navigation) on top of the shortcut-profile stack (#53#54#55#56), resolving the Alt+Arrow collision between them.

The conflict

#46 hardcoded Alt+Arrow → anchor-jump in a profile-agnostic onKeyDown switch. #55's FeedBack Native profile binds Alt+Arrow → note-jump (anchor moves to Ctrl+Alt+Arrow). Two independent modern schemes for one key — not legacy-vs-modern (EOF Legacy never uses Alt+Arrow; it uses Alt+PageUp/Dn for anchors). Merged as-is they'd silently shadow each other (note in the Native profile, anchor in EOF). Resolution: the profile system owns all key bindings; #46 contributes only its engine.

Kept from #46

  • Expanded snap gridSNAP_OPTIONS with straight + triplet divisions and a split-out S.snapEnabled on/off toggle (button + JS-populated select + persistence); snapTime() rewritten onto the pure _snapTimeToGrid.
  • Interval-aware grid math_editorJumpGrid now uses _nextGridTime (the grid point in the beat interval containing the cursor, correct across tempo changes) instead of a fixed step add, seeking via _editorSeekToTime so playback follows like every other jump.

Dropped from #46

  • The hardcoded Alt/Shift/Ctrl+Arrow onKeyDown block — Alt+Arrow now resolves per active profile via the command-ID tables.
  • Its redundant stateful jump engine (_navigateTimeline/_jumpCursorTo/_maxScrollX/_currentNoteTimes/_currentAnchorTimes) — the profile's _editorJump* already own beat/note/anchor.

Also fixes a guaranteed integration break

#46 removed SNAP_VALUES, but the stack's _editorSnapStepSeconds (which also powers sustain-resize) and the snapUp command still read it — both migrated to SNAP_OPTIONS[idx].step + S.snapEnabled.

Testing

All 20 editor test suites pass — snap_navigation 8/8, eof_shortcuts 11/11, node --check screen.js.

Supersedes #46 (please close it in favor of this). Stacked on #56.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 70b7219b-57e6-4580-af3e-bbf6a50cffc4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/snap-grid-on-profile-stack

Comment @coderabbitai help to get the list of available commands.

@ChrisBeWithYou

Copy link
Copy Markdown
Contributor Author

Integration note — from a full-queue dry-run that merged every open org PR into a next-version test build.

This PR can't be merged alongside #55/#56, which already ship a full snap-to-grid system on main: schema {value, subdivisions} via SNAP_OPTIONS/SNAP_VALUES, _editorSnapStepSeconds/_editorToggleSnapEnabled, the editor-snap-enabled checkbox, prevGrid/nextGrid shortcut cases, and a passing snap_options.test.js. This PR reimplements the same subsystem with an incompatible {step} schema and a different UI (editor-snap-toggle button + updateSnapUI/_persistSnapPrefs/localStorage). They collide hard — redeclared const SNAP_OPTIONS (SyntaxError), duplicate window.editorSetSnap, conflicting screen.html markup — on all 8 conflict hunks.

Recommend: close this and re-submit just the delta — the triplet divisions (1/3T, 1/6T, 1/12T, 1/48T, 1/96T) added as entries in the existing SNAP_OPTIONS. That's the only user-facing gain here over what's already on main, and it's a ~5-line change against the shipped system instead of a competing rewrite.

…stem

Re-does PR 46 (editor-snap-navigation) on top of the 53–56 shortcut-profile
stack, resolving the Alt+Arrow collision between them. PR 46 hardcoded Alt+Arrow
to anchor-jump in a profile-agnostic onKeyDown switch; PR 55's FeedBack Native
profile binds Alt+Arrow to note-jump (anchor → Ctrl+Alt+Arrow). That's two
independent modern schemes for one key (EOF Legacy never uses Alt+Arrow), so the
fix is: the profile system owns all key bindings, and 46 contributes only its
engine.

Kept from PR 46:
- Expanded snap grid: SNAP_OPTIONS with straight + triplet divisions and a
  split-out S.snapEnabled on/off toggle (button + JS-populated select +
  persistence); snapTime() rewritten onto the pure _snapTimeToGrid.
- Interval-aware grid math: _editorJumpGrid now uses _nextGridTime (the grid
  point in the beat interval CONTAINING the cursor, correct across tempo
  changes) instead of a fixed step add, seeking via _editorSeekToTime so
  playback follows like every other jump.

Dropped from PR 46:
- The hardcoded Alt/Shift/Ctrl+Arrow onKeyDown block — Alt+Arrow now resolves
  per active profile via the command-ID tables (Native = note, anchor on
  Ctrl+Alt+Arrow; EOF = Alt+PageUp/Dn for anchors).
- Its redundant stateful jump engine (_navigateTimeline/_jumpCursorTo/
  _maxScrollX/_currentNoteTimes/_currentAnchorTimes): the profile's _editorJump*
  already own beat/note/anchor jumps.

Also fixes a guaranteed integration break: PR 46 removed SNAP_VALUES, but the
stack's _editorSnapStepSeconds (which also powers sustain-resize) and the snapUp
command still read it — both migrated to SNAP_OPTIONS[idx].step + S.snapEnabled.

Supersedes #46. All 20 editor test suites pass (snap_navigation 8/8,
eof_shortcuts 11/11).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@byrongamatos
byrongamatos force-pushed the feat/shortcut-interaction-settings branch from 37ded33 to 1d4a60c Compare July 5, 2026 12:24
@byrongamatos
byrongamatos force-pushed the feat/snap-grid-on-profile-stack branch from 7d38178 to f74c86d Compare July 5, 2026 12:25
@byrongamatos
byrongamatos deleted the branch main July 5, 2026 12:38
@byrongamatos byrongamatos reopened this Jul 5, 2026
@byrongamatos
byrongamatos changed the base branch from feat/shortcut-interaction-settings to main July 5, 2026 12:44
@byrongamatos

Copy link
Copy Markdown
Collaborator

Heads-up @ChrisBeWithYou — the rest of the editor stack (#47#69) and #45 are now merged to main. This PR was auto-closed when its base branch got cleaned up during the merge; I've reopened it and retargeted it to main, so its work is preserved.

It now needs a decision. #62 reworks the snap grid via the shortcut-profile system ("supersedes #46"), but the linear line that merged already includes #57 (expand snap grid options) + #58 (snap enable toggle) — effectively a second snap-grid implementation. The two touch the same screen.html / screen.js regions and conflict, which is why this now shows CONFLICTING against main.

Two paths, your call:

  1. editor: snap-grid upgrade wired through the shortcut-profile system (supersedes #46) #62 supersedes feat(editor): expand snap grid options #57/feat(editor): add snap enable toggle #58 too — then we revert feat(editor): expand snap grid options #57/feat(editor): add snap enable toggle #58 from main and rebase editor: snap-grid upgrade wired through the shortcut-profile system (supersedes #46) #62 on top. (feat(editor): clamp timeline scroll bounds #59+ were built on feat(editor): expand snap grid options #57/feat(editor): add snap enable toggle #58, so that path needs a re-check.)
  2. feat(editor): expand snap grid options #57/feat(editor): add snap enable toggle #58 stand — then editor: snap-grid upgrade wired through the shortcut-profile system (supersedes #46) #62 is redundant and can be closed, or trimmed to only what it adds beyond them.

Not merging either way until you confirm which snap-grid approach is the keeper.

@ChrisBeWithYou

Copy link
Copy Markdown
Contributor Author

Decision: closing #62 in favor of the merged #57/#58 standalone snap-grid options.

#57/#58 are already on main, tested, and carry the fine triplet subdivisions (1/12–1/96). Adopting #62's shortcut-profile {step} model would mean reworking a working, merged subsystem for little net gain.

The one thing #62 adds that main lacks — the coarse triplet steps 1/3T (quarter-note triplet) and 1/6T — will be ported as a tiny follow-up onto the merged {value, subdivisions} options (plus optional T labels on the existing triplet entries).

Your work here isn't lost — it's preserved on feat/snap-grid-on-profile-stack. Thanks for the clean reconciliation; the profile-stack approach is on record if we revisit unifying snap with the hotkey system later.

byrongamatos pushed a commit that referenced this pull request Jul 5, 2026
The snap grid jumped from 1/4 straight to 1/8 with no quarter- or
eighth-note triplet resolution, so triplet passages could only snap at
1/12T or finer. Add 1/3T (value 1/3) and 1/6T (value 1/6) in value order,
and label the triplet-family divisions (3/6/12/24/48/96) with a T suffix
so the grid reads clearly against the binary options.

The snap <select> options are static in screen.html and index-mapped via
editorSetSnap(selectedIndex), so screen.html, SNAP_OPTIONS, and the
snapIdx default are kept in lockstep; 1/4 shifts from index 2 to 3, so the
S.snapIdx default and snap_options.test.js move with it. snapIdx is not
persisted, so no migration is needed.

Ports the one division set #62 (feat/snap-grid-on-profile-stack) had over
the merged #57/#58 snap options, without adopting its {step} engine.

Tests: snap_options.test.js updated (+1/3, +1/6 subdivisions, new label
list, default index); full editor JS suite green (24 files).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UR2Cr7GEu3yMY7SrfxH6c1
byrongamatos pushed a commit that referenced this pull request Jul 5, 2026
The snap grid jumped from 1/4 straight to 1/8 with no quarter- or
eighth-note triplet resolution, so triplet passages could only snap at
1/12T or finer. Add 1/3T (value 1/3) and 1/6T (value 1/6) in value order,
and label the triplet-family divisions (3/6/12/24/48/96) with a T suffix
so the grid reads clearly against the binary options.

The snap <select> options are static in screen.html and index-mapped via
editorSetSnap(selectedIndex), so screen.html, SNAP_OPTIONS, and the
snapIdx default are kept in lockstep; 1/4 shifts from index 2 to 3, so the
S.snapIdx default and snap_options.test.js move with it. snapIdx is not
persisted, so no migration is needed.

Ports the one division set #62 (feat/snap-grid-on-profile-stack) had over
the merged #57/#58 snap options, without adopting its {step} engine.

Tests: snap_options.test.js updated (+1/3, +1/6 subdivisions, new label
list, default index); full editor JS suite green (24 files).


Claude-Session: https://claude.ai/code/session_01UR2Cr7GEu3yMY7SrfxH6c1

Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ChrisBeWithYou added a commit that referenced this pull request Jul 22, 2026
…t manifest entries (#345)

The /save_song drum block rebuilds every type:"drums" pointer entry
from scratch as {id, name, type, drum_tab} whenever the client ships
drum_parts (any drum-dirty save). A pack whose drum entries carry
additive spec fields the editor doesn't author — feedpak-spec 1.18.0's
per-arrangement `tones` sound binding (spec #62), or any extension key
— lost them silently on the next drum edit + save.

The rebuild now merges each entry ONTO its prior same-id entry through
the same _merge_manifest_entry rule the pitched pipeline has followed
since the merge-not-rebuild save: authored/additive keys survive
verbatim, the editor-owned keys always take the rebuilt value, and a
part with no predecessor (or no id match after a rename) yields exactly
the clean four-key entry — so single-drum packs stay byte-identical.

Extracted as module-level _drum_pointer_entry for pytest, mirroring how
the create-mode twin (_create_build_drum_entries) is pinned. Create
mode itself builds fresh packs with no prior manifest, so it has
nothing to preserve and is untouched.


Claude-Session: https://claude.ai/code/session_017xGPjDBF8NTwTK7VQvizix

Co-authored-by: ChrisBeWithYou <chris@rifflarr.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants