Skip to content

refactor(editor): move the input layer to src/input.js (R2, step 36) - #188

Merged
byrongamatos merged 2 commits into
mainfrom
refactor/r2-step36-input
Jul 10, 2026
Merged

refactor(editor): move the input layer to src/input.js (R2, step 36)#188
byrongamatos merged 2 commits into
mainfrom
refactor/r2-step36-input

Conversation

@byrongamatos

@byrongamatos byrongamatos commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

What

Step 36 of the R2 module-extraction refactor: move the entire remaining input layer out of src/main.js into a new native ES module src/input.js. The "Mouse interactions" banner is now empty and gone.

Covers: the keyboard shortcut dispatch (onKeyDown), all the _editorX command implementations, the bookmarks / duplicate / section-cmds command clusters, the shortcut panel, and the canvas context menu (onContextMenu / showSectionMenu).

Enabled by tab-preview (#187)

Landing tab-preview first turned its two couplings (_editorShowTabPreview, _tabPreviewKeyPolicyPure) into plain module imports instead of awkward host hooks — that's why this cut is clean.

How the seam is drawn

  • src/input.js (~1,240 lines): imports across ~20 modules; 7 symbols exported backonKeyDown + onContextMenu (wired onto the canvas by main.js init()); _editorCurrentNoteIndices / _editorSeekToTime / _editorSnapStepSeconds (host hooks); _bookmarks + the editorWaveformVisible live binding (both read by the draw path).
  • 5 new host hooks for the composition-root symbols the commands call: editorCycleViewMode, editorMovePart, editorToggleKeyHighlight, editorTogglePartsView, tempoResolvedMeasureIdx.
  • The 4 @pure blocks (shortcut-panel-hint, bookmarks, duplicate, section-cmds) and the command classes inside them stay export-free (internal), so the JS suite's new Function slices stay valid.
  • Removed 72 now-dead main.js imports (used only by the moved layer) — strict no-undef confirmed no over-removal.
  • 4 tests retargeted to slice from input.js (bookmarks, duplicate_selection, section_undo, roll_position_cycle).

main.js drops ~1,243 lines. 37 modules.

Verification

  • 90/90 JS suites pass; ESLint gate clean (0 errors); strict no-undef clean on input.js.
  • Codex preflight: 0 regressions (init() attachment + editorWaveformVisible live binding confirmed).
  • New headless harness (verify_input.py) drives real input: right-click opens the context menu (onContextMenu), the shortcut panel toggles, editorRunShortcutCommand routes 'toggleKeyHighlight'/'togglePartsView' into their new host hooks (distinct status each), and a real Shift+A keypress routes through onKeyDown to the parts-view command — zero page errors. The two new hooks + onKeyDown negative-checked.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a centralized editor input layer for comprehensive keyboard shortcuts, global command dispatch, and right-click context actions (notes, sections, tempo map, tones, anchors, handshapes).
    • Introduced numbered bookmarks with persistent storage plus quick navigation and jump support.
    • Expanded authoring and editing commands (undoable section/phrase/tone-handshape changes, timing adjustments, duplication, copy/paste).
    • Added editor view/parts/key-highlight controls and tempo-measure resolution support.
  • Tests

    • Updated editor behavior tests to reflect the new input handling entry points.

Extract the entire remaining "Mouse interactions" banner — the keyboard shortcut
dispatch (onKeyDown), all the _editorX command implementations, the
bookmarks/duplicate/section-cmds command clusters, the shortcut panel, and the
canvas context menu (onContextMenu/showSectionMenu) — out of the src/main.js
monolith into a new native ES module. The banner is now empty and gone.

Enabled by landing tab-preview first (#187): the two tab-preview couplings
(_editorShowTabPreview, _tabPreviewKeyPolicyPure) are now plain module imports.

- src/input.js (~1240 lines): imports across ~20 modules; 7 symbols exported back
  (onKeyDown + onContextMenu, wired onto the canvas by main.js init();
  _editorCurrentNoteIndices/_editorSeekToTime/_editorSnapStepSeconds host hooks;
  _bookmarks + the editorWaveformVisible live binding, read by the draw path).
- 5 new host hooks for the composition-root symbols the commands call:
  editorCycleViewMode, editorMovePart, editorToggleKeyHighlight,
  editorTogglePartsView, tempoResolvedMeasureIdx.
- The 4 @pure blocks (shortcut-panel-hint, bookmarks, duplicate, section-cmds)
  and the command classes inside them stay export-free (internal), so the JS
  suite's new-Function slices stay valid.
- Removed 72 now-dead main.js imports (used only by the moved layer) — strict
  no-undef confirmed no over-removal.
- 4 tests retargeted to slice from input.js (bookmarks, duplicate_selection,
  section_undo, roll_position_cycle).

main.js drops ~1243 lines. 37 modules.

Verified: 90/90 JS suites pass, ESLint gate clean (0 errors), strict no-undef
clean on input.js, Codex preflight 0 regressions (init() attachment +
editorWaveformVisible live binding confirmed). New headless harness drives REAL
input: right-click opens the context menu (onContextMenu), the shortcut panel
toggles, editorRunShortcutCommand routes 'toggleKeyHighlight'/'togglePartsView'
into their new host hooks (distinct status each), and a real Shift+A keypress
routes through onKeyDown to the parts-view command — zero page errors. The two
new hooks + onKeyDown negative-checked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4af2ef0d-18c0-454e-aa43-c18ea1098069

📥 Commits

Reviewing files that changed from the base of the PR and between b453e78 and f59f31d.

📒 Files selected for processing (2)
  • src/host.js
  • src/input.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/host.js
  • src/input.js

📝 Walkthrough

Walkthrough

The editor input layer is moved into src/input.js, adding shortcut, keyboard, context-menu, bookmark, selection, section, and tempo-map operations. src/main.js wires the new handlers and host callbacks, while tests extract pure helpers from the new module.

Changes

Editor input and integration

Layer / File(s) Summary
Input-layer state and shortcut dispatch
src/input.js
Adds shortcut-panel controls, waveform state, note-selection helpers, snap navigation, and shortcut command dispatch.
Bookmarks, selection, and authoring commands
src/input.js
Adds local bookmarks, selection duplication and resnapping, undoable section commands, and cursor-based authoring actions.
Tempo and command routing
src/input.js
Adds tempo-map editing, EOF/profile shortcut dispatch, and context-menu routing for notes, lanes, and sections.
Keyboard editing flow
src/input.js
Adds modal, recording, parts-view, transport, clipboard, undo/redo, note-edit, drum-edit, and tempo-map keyboard handling.
Host and window API integration
src/host.js, src/main.js
Adds host callback defaults, wires editor and tempo hooks, reattaches shortcut handlers, and updates imports.
Input source extraction tests
tests/bookmarks.test.mjs, tests/duplicate_selection.test.mjs, tests/roll_position_cycle.test.mjs, tests/section_undo.test.mjs
Updates pure-block extraction tests and messages to load implementations from src/input.js.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant onKeyDown
  participant editorRunEofCommand
  participant EditorCommand
  participant host
  User->>onKeyDown: keyboard shortcut or edit event
  onKeyDown->>editorRunEofCommand: dispatch command id
  editorRunEofCommand->>EditorCommand: execute editor operation
  EditorCommand->>host: update editor state or tempo hooks
  host->>User: refresh editor state
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: extracting the editor input layer into src/input.js as part of the refactor.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/r2-step36-input

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 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.

Inline comments:
In `@src/host.js`:
- Line 78: The default tempoResolvedMeasureIdx resolver should be inert rather
than selecting measure zero. Update the resolver in the host configuration to
return a negative value (such as -1), so input.js will not apply the
time-signature edit when no measure has been resolved.

In `@src/input.js`:
- Around line 934-940: Replace the HTML-string construction in the section-menu
builder with DOM button creation and textContent assignments, especially in the
nearSection rename and delete actions. Preserve the existing classes and
data-action attributes, append the buttons to menu, and ensure nearSection.name
is only inserted as text rather than interpolated into innerHTML.
- Around line 1147-1153: Update the guitar/keys delete guard in the keyboard
handler to also require Tempo Map mode to be inactive, using the same tempo-mode
predicate as the duplicate, copy, and paste handlers; ensure stale S.sel notes
are not passed to DeleteNotesCmd when no sync point is selected during Tempo Map
mode.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f82ad9c8-c11f-4b7c-a93b-b437d04d0efe

📥 Commits

Reviewing files that changed from the base of the PR and between 51be9a0 and b453e78.

📒 Files selected for processing (7)
  • src/host.js
  • src/input.js
  • src/main.js
  • tests/bookmarks.test.mjs
  • tests/duplicate_selection.test.mjs
  • tests/roll_position_cycle.test.mjs
  • tests/section_undo.test.mjs

Comment thread src/host.js Outdated
Comment thread src/input.js Outdated
Comment thread src/input.js
…n-menu XSS, tempo-mode delete guard

- host.js: tempoResolvedMeasureIdx default 0 -> -1 so an unwired hook is inert
  (callers apply the time-signature edit only on >= 0). This one is a regression
  from this PR's new hook.
- input.js showSectionMenu: build the buttons as DOM nodes with textContent
  instead of interpolating the user-authored section name into innerHTML —
  removes a stored-XSS sink. (Pre-existing, moved verbatim; hardened here.)
- input.js Delete key: add the !S.tempoMapMode guard (matching duplicate/copy/
  paste) so a stale selection can't delete hidden notes while Tempo Map mode is
  active. (Pre-existing, moved verbatim.)

Co-Authored-By: Claude Opus 4.8 (1M context) <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.

1 participant