feat(workspace): find tonight's first range on the roadmap - #1147
feat(workspace): find tonight's first range on the roadmap#1147seonghobae wants to merge 5 commits into
Conversation
The ready map already names tonight's first playable range. Players still
had to hunt the section roadmap for the chord, cue, and clash on that
part. The range card now offers Find {section} for {role} on the roadmap
and highlights the matching unique section and part without starting
playback.
Fail closed on duplicate section or part identity. Repeated Find clicks
scroll again. Replacing the loaded song cannot inherit a previous
highlight. Roadmap scrolling honors prefers-reduced-motion.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (13)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughready workspace가 첫 연습 구간을 표시하고, 버튼으로 해당 역할과 섹션을 로드맵에서 찾습니다. 로드맵은 대상 카드를 스크롤하고 강조 표시합니다. 중복되거나 유효하지 않은 식별자는 기능을 비활성화합니다. Changes첫 연습 구간 로드맵 찾기
Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: ⚪ Minimal · up to This UI-only change locates and highlights a uniquely matched roadmap item without starting playback, changing persistent state, or invoking external services. No actionable merge-blocking risk remains beyond normal checks and review. Sequence Diagram(s)sequenceDiagram
participant 연주자
participant Workspace
participant firstRangeRoadmap
participant SectionRoadmap
participant DOM
연주자->>Workspace: 첫 연습 구간 로드맵 찾기 클릭
Workspace->>firstRangeRoadmap: song과 firstRange 전달
firstRangeRoadmap-->>Workspace: 검증된 sectionId와 roleId 반환
Workspace->>SectionRoadmap: 포커스 요청 전달
SectionRoadmap->>DOM: 대상 섹션으로 스크롤
SectionRoadmap->>DOM: 섹션과 역할 강조
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 6 files. (7 skipped: 7 unsupported.) ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Preservation child of canonical first-range navigation owner #1143. The base is intentionally retargeted to Preserve the unique |
| const targetSectionId = meaningfulRangeText(rangeSqueeze.sectionId); | ||
| const targetRoleId = meaningfulRangeText(rangeSqueeze.roleId); | ||
| if (!targetSectionId || !targetRoleId) { | ||
| return null; | ||
| } | ||
|
|
||
| const runtimeSong: unknown = rehearsalSong; | ||
| if (!isRuntimeObject(runtimeSong) || !Array.isArray(runtimeSong.sections)) { | ||
| return null; | ||
| } | ||
|
|
||
| let sectionIdOccurrences = 0; | ||
| let targetSection: Record<string, unknown> | null = null; | ||
| for (const sectionValue of runtimeSong.sections) { | ||
| if (!isRuntimeObject(sectionValue)) { | ||
| continue; | ||
| } | ||
| if (meaningfulRangeText(sectionValue.id) === targetSectionId) { | ||
| sectionIdOccurrences += 1; | ||
| targetSection = sectionValue; | ||
| } | ||
| } | ||
|
|
||
| if (sectionIdOccurrences !== 1 || !targetSection || !Array.isArray(targetSection.roles)) { | ||
| return null; | ||
| } | ||
|
|
||
| let roleIdOccurrences = 0; | ||
| let targetRole: Record<string, unknown> | null = null; | ||
| for (const roleValue of targetSection.roles) { | ||
| if (!isRuntimeObject(roleValue)) { | ||
| continue; | ||
| } | ||
| if (meaningfulRangeText(roleValue.id) === targetRoleId) { | ||
| roleIdOccurrences += 1; | ||
| targetRole = roleValue; | ||
| } | ||
| } | ||
|
|
||
| if (roleIdOccurrences !== 1 || !targetRole) { | ||
| return null; | ||
| } | ||
|
|
||
| const sectionLabel = meaningfulRangeText(targetSection.label); | ||
| const roleName = meaningfulRangeText(targetRole.name); | ||
| if (!sectionLabel || !roleName) { | ||
| return null; | ||
| } | ||
|
|
||
| return { | ||
| sectionId: targetSectionId, | ||
| roleId: targetRoleId, | ||
| sectionLabel, | ||
| roleName | ||
| }; |
| /** Request the first-range roadmap cell on every activation, even when it is already highlighted. */ | ||
| const handleFindFirstRangeRoadmap = () => { | ||
| if (!firstRangeBoard) { | ||
| return; | ||
| } | ||
| setRoadmapFocusRequest((previousFocusRequest) => ({ | ||
| rehearsalSongId: song.id, | ||
| sectionId: firstRangeBoard.sectionId, | ||
| roleId: firstRangeBoard.roleId, | ||
| requestSequence: | ||
| previousFocusRequest?.rehearsalSongId === song.id | ||
| ? previousFocusRequest.requestSequence + 1 | ||
| : 1 | ||
| })); | ||
| }; |
| } | ||
| ) | ||
| : t("workspaceFirstRangeMissing"); | ||
| const firstRangeBoard = firstRangeRoadmap(song, firstRange); |
| () => safeProjectBootstrapSummary(sourceBootstrap), | ||
| [sourceBootstrap] | ||
| ); | ||
| const rehearsalSourceIdentity = parsedSourceBootstrap?.projectId ?? song.id; |
There was a problem hiding this comment.
🟡 Loaded songs inherit stale roadmap focus
When a loaded song ID equals the prior project ID, rehearsalSourceIdentity treats both sources as identical. The new song retains the old roadmap highlight.
| const rehearsalSourceIdentity = parsedSourceBootstrap?.projectId ?? song.id; | |
| const rehearsalSourceIdentity = parsedSourceBootstrap | |
| ? `project:${parsedSourceBootstrap.projectId}` | |
| : `song:${song.id}`; |
Was this helpful? React with 👍 or 👎 to provide feedback.
Superseded by canonical first-range navigation owner #1143
This stacked PR is closed only after verifying that its valid product, test, and documentation requirements are preserved on the canonical owner branch. It is not being treated as merged, and no review/check evidence from this head transfers.
Verified source head before closure:
54d8ddfc0d76e5c70ae07d3b4a72663d762f99c5.Verified successor branch after transfer/repair:
feat/workspace-find-first-range-section@d657b8d17222e23e7acf95c43766016bb3f013fain #1143, still based on protecteddevelop@749511c3ad4000090048718f685c6bee6b3d2c25.Succession evidence
#1143 now preserves and extends the valid roadmap behavior from this PR:
firstRangeSqueezekeeps the originating exact section/role IDs while playable-range presentation remains independent from navigation admission.firstRangeRoadmapnavigates by unique section/role identity; repeated display labels/names remain valid and duplicate/noncanonical IDs fail closed.aria-currentstate;project:/song:), repairing this PR's final unresolved collision finding;song.id = "analyzed-song";The canonical branch also corrected two stale regression assertions to match the shipped role-card accessibility contract (
aria-current="true") and consolidated the roadmap capability intoCHANGELOG.mdanddocs/architecture/overview.mdalongside timeline navigation.Evidence boundary
#1143 exact-head workflows must run again on its own unchanged head. This closure does not import this PR's absent/stale checks, review state, or approvals. #961 remains the Active Player/transport owner; this navigation slice does not start playback.