Skip to content

refactor(#23): SpectrumView を struct/geometry/rendering に分割#305

Merged
GeneralD merged 7 commits into
mainfrom
refactor/spectrum-geometry-split
Jul 5, 2026
Merged

refactor(#23): SpectrumView を struct/geometry/rendering に分割#305
GeneralD merged 7 commits into
mainfrom
refactor/spectrum-geometry-split

Conversation

@GeneralD

@GeneralD GeneralD commented Jul 5, 2026

Copy link
Copy Markdown
Owner

agent type breaking scope diff files tests review

概要

SpectrumView.swift純粋な SwiftUI View struct のみに削ぎ落とし、ジオメトリ計算と Canvas 描画をロジックとして分離する純粋なファイル再編。挙動は不変、テスト網羅を1つ追加。

変更内容

  • SpectrumView.swiftstruct SpectrumView: Viewbody)のみを残す。drawBars/fillBars メソッドと全自由関数を撤去し、body は分離先を呼ぶだけに。
  • SpectrumGeometry.swift(新規)— size/style → rect・point・alignment・Path の純粋関数群(spectrumBarRectsbarStripDepthgradientEndsbarsPath ほか)。GraphicsContext 非依存でユニットテスト可能。
  • SpectrumRendering.swift(新規)— 還元不能な Canvas 描画(drawSpectrumBars/fillSpectrumBars)を自由関数化。実 context 無しでは動かないので設計上テスト対象外だが、描く値は全て tested な geometry 由来なので薄い。
  • barsPath のジオメトリテストを追加(空/単一/複数 bar の union 境界)。従来は透過的にしか通っていなかった経路を直接テスト。
  • .claude/rules/swift-idioms.mdView ファイル構成ルールXxxxView.swift は純粋 struct のみ・ロジックは Geometry/Rendering 兄弟ファイルへ)を明文化。
  • バージョン 2.20.0 → 2.20.1(refactor → patch)。

背景・動機

計算を抱えた View ファイルは、テスト不能な宣言部の周りに tested なロジックを引きずり、テスタビリティを下げる。ロジックを自由関数として外へ出せばテスト可能になり("Untestable = 抽象化不足" 原則)、struct は何を描画するか一目で読める。テスタビリティでファイルを分けることで、カバレッジ境界がそのままファイル境界になる。

テスト計画

  • swift build 成功
  • swift test --filter ViewsTests 全101テスト green(新規 barsPath スイート含む)
  • make format 適用済み

備考

  • 純粋な内部再編でモジュール構成・CLI・config・アーキテクチャ境界に変化なし。Mermaid グラフや Layer Summary の更新は不要。
  • version.txt は並行中の他 spectrum PR と衝突しうる。マージ順で解消する。

Summary by CodeRabbit

  • New Features
    • Enhanced spectrum rendering with optional background fill, bar opacity, and richer gradients (single-color and multi-color across level, frequency, and amplitude).
    • Improved spectrum layout consistency across placements/orientations via separated geometry + rendering.
  • Bug Fixes
    • Refined bar rectangle/path calculations, clamping, anchoring, and corner-radius behavior; invisible bars are reliably omitted.
  • Documentation
    • Added SwiftUI file organization guidance for view vs. non-view logic separation.
  • Tests
    • Expanded geometry and view rendering test coverage, including deterministic rendering branches.

GeneralD added 4 commits July 5, 2026 15:48
View ファイルは純粋な SwiftUI struct のみを残し、bar ジオメトリを
SpectrumGeometry.swift(純粋・テスト可能)、Canvas 描画を
SpectrumRendering.swift(GraphicsContext 依存・薄い)へ自由関数として分離。
body はそれらを呼ぶだけで計算・描画メソッドを持たない。
分離した barsPath 自由関数を直接テスト(空/単一/複数 bar の union 境界)。
XxxxView.swift は純粋 struct のみ・ロジックは Geometry/Rendering 兄弟ファイルへ、を明文化。
Copilot AI review requested due to automatic review settings July 5, 2026 06:50
@GeneralD GeneralD self-assigned this Jul 5, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extracts Spectrum view geometry and Canvas drawing into SpectrumGeometry and SpectrumRenderer, updates SpectrumView to delegate to them, migrates related tests to the new instance APIs, adds a Swift idioms note, and bumps the package version.

Changes

Spectrum view refactor

Layer / File(s) Summary
SpectrumGeometry data shapes and computations
Sources/Views/Spectrum/SpectrumGeometry.swift
Adds SpectrumBar and SpectrumGeometry with barRects, autoCornerRadius, barsPath, stripDepth, layout and orientation helpers, gradient endpoint resolution, and private barRect anchoring logic.
SpectrumRenderer drawing logic
Sources/Views/Spectrum/SpectrumRenderer.swift
Adds @MainActor SpectrumRenderer that uses SpectrumGeometry to compute bar rectangles and paths, then paints background, solid fills, and gradient fills into a GraphicsContext.
SpectrumView delegation to geometry and renderer
Sources/Views/Spectrum/SpectrumView.swift
Updates SpectrumView to store SpectrumGeometry and SpectrumRenderer, replaces inline layout and drawing with delegated calls, and updates the track-length change handler.
SpectrumGeometry test suite migration
Tests/ViewsTests/SpectrumBarRectsTests.swift
Migrates geometry tests to the new instance API and adds coverage for barsPath alongside barRects, stripDepth, gradientEnds, and helper behavior.
Idioms documentation and version bump
.claude/rules/swift-idioms.md, Sources/VersionHandler/Resources/version.txt
Adds a SwiftUI view-organization note and increments the version to 2.20.1.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SpectrumView
  participant SpectrumGeometry
  participant SpectrumRenderer

  SpectrumView->>SpectrumGeometry: stripDepth / alignment / trackExtent(placement, style)
  SpectrumGeometry-->>SpectrumView: layout metrics
  SpectrumView->>SpectrumRenderer: draw(context, size, heights, style)
  SpectrumRenderer->>SpectrumGeometry: barRects(size, heights, placement)
  SpectrumGeometry-->>SpectrumRenderer: [SpectrumBar]
  SpectrumRenderer-->>SpectrumView: filled GraphicsContext
Loading

Possibly related PRs

  • GeneralD/lyra#296: Builds on the earlier SpectrumView and spectrum pipeline work that this PR splits into geometry and renderer types.
  • GeneralD/lyra#298: Also touches Spectrum bar layout and gradient-endpoint behavior extracted from SpectrumView.
🚥 Pre-merge checks | ✅ 4
✅ 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 summarizes the main change: splitting SpectrumView into struct, geometry, and rendering components.
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/spectrum-geometry-split

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.

❤️ Share

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

SpectrumView.swift を「宣言だけの SwiftUI View」に保ちつつ、スペクトラム描画のジオメトリ計算Canvas 描画をそれぞれ別ファイルへ分離して、テスタビリティと見通しを改善するリファクタです。既存挙動は維持しつつ、barsPath のユニットテストを追加しています。

Changes:

  • SpectrumView.swift からジオメトリ計算・描画ロジックを除去し、drawSpectrumBars 呼び出しに集約
  • 純粋関数のジオメトリ群を SpectrumGeometry.swift に、Canvas 描画を SpectrumRendering.swift に分離
  • barsPath の幾何テスト追加 + patch バージョン更新(2.20.0 → 2.20.1)

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Tests/ViewsTests/SpectrumBarRectsTests.swift barsPath の境界(空/単一/複数)を直接テストしてジオメトリの保証を強化
Sources/Views/Spectrum/SpectrumView.swift View を宣言中心に整理し、描画を drawSpectrumBars に委譲
Sources/Views/Spectrum/SpectrumRendering.swift GraphicsContext に依存する Canvas 描画ロジックを集約
Sources/Views/Spectrum/SpectrumGeometry.swift 描画に必要な rect/point/path/alignment 生成を純粋関数として切り出し
Sources/VersionHandler/Resources/version.txt patch バンプ(2.20.1)
.claude/rules/swift-idioms.md View/Geometry/Rendering のファイル分割方針をドキュメント化

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .claude/rules/swift-idioms.md Outdated
Comment on lines +52 to +56
**A `XxxxView.swift` file must contain only the pure SwiftUI `View` struct.**
Everything else — bar/rect geometry, gradient math, alignment helpers, and even
`GraphicsContext` drawing — is *logic*, not view declaration, so it lives in
sibling files. The `View` struct's `body` calls out to those free functions; it
never defines them or the drawing methods.
@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

GeneralD added 2 commits July 5, 2026 16:41
グローバル空間の自由関数ではなく cohesive な struct にまとめ、Swift の OO
基盤に沿わせる。SpectrumGeometry は純粋メソッドの struct、SpectrumRenderer は
@mainactor struct で resolver を @dependency で保持。SpectrumView は両者の
インスタンスを持ち body から委譲。型名が名前空間を与えるのでメソッド名から
spectrum 接頭辞を落とす(geometry.barRects 等)。テストはインスタンス経由に更新。
自由関数の袋ではなく struct にまとめ View がインスタンスを持つ方式、および
これは Presenter ロジックではなく View 層の値→ピクセル写像である旨を明記。

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

codecov が指摘した未カバー箇所への対応。NSHostingView + ImageRenderer で
実際に Canvas を走らせ、SpectrumRenderer.draw/fill の全分岐(solid 塗り・
level/frequency/amplitude グラデーション・background 塗り・無音時の
no-bars ガード)を通す。既存の HeaderView/RippleView テストと同じ render()
パターンを踏襲。

結果: SpectrumRenderer/SpectrumGeometry/SpectrumView の3ファイルとも
region/function/line カバレッジ 100% を達成。

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

🧹 Nitpick comments (2)
Tests/ViewsTests/SpectrumViewRenderingTests.swift (2)

43-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use let for magnitudesValue.

magnitudesValue is only ever assigned in init and never mutated elsewhere in this file. As per coding guidelines, "Every var should have a real reason to exist."

♻️ Proposed fix
-    var magnitudesValue: [Float]
+    let magnitudesValue: [Float]
🤖 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/ViewsTests/SpectrumViewRenderingTests.swift` around lines 43 - 48,
`magnitudesValue` in `SpectrumViewRenderingTests` is never mutated after
initialization, so replace the stored `var` with a `let` and keep the assignment
only in the `init(style:magnitudes:)` initializer. Update the
`SpectrumViewRenderingTests` fixture to use an immutable property while
preserving the existing `spectrumStyle` and `magnitudesValue` setup.

Source: Coding guidelines


18-26: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Remove the unused NSHostingView setup

ImageRenderer snapshots view.frame(...) directly, so the NSHostingView layout work here has no effect. Drop it, or update the comment if this helper is meant to rely on some other side effect.

🤖 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/ViewsTests/SpectrumViewRenderingTests.swift` around lines 18 - 26, The
unused NSHostingView setup in renderHosting is dead code because ImageRenderer
already snapshots the SwiftUI view directly. Remove the hostingView creation,
frame assignment, and layoutSubtreeIfNeeded call from renderHosting, and keep
the helper centered on the ImageRenderer path unless you intend to document a
different side effect in the comment.
🤖 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/ViewsTests/SpectrumViewRenderingTests.swift`:
- Around line 43-48: `magnitudesValue` in `SpectrumViewRenderingTests` is never
mutated after initialization, so replace the stored `var` with a `let` and keep
the assignment only in the `init(style:magnitudes:)` initializer. Update the
`SpectrumViewRenderingTests` fixture to use an immutable property while
preserving the existing `spectrumStyle` and `magnitudesValue` setup.
- Around line 18-26: The unused NSHostingView setup in renderHosting is dead
code because ImageRenderer already snapshots the SwiftUI view directly. Remove
the hostingView creation, frame assignment, and layoutSubtreeIfNeeded call from
renderHosting, and keep the helper centered on the ImageRenderer path unless you
intend to document a different side effect in the comment.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a30dc3b2-0fb0-4a54-a101-8a91e853abca

📥 Commits

Reviewing files that changed from the base of the PR and between f594d6d and d5bd5ee.

📒 Files selected for processing (1)
  • Tests/ViewsTests/SpectrumViewRenderingTests.swift

@GeneralD GeneralD merged commit e62daa5 into main Jul 5, 2026
4 checks passed
@GeneralD GeneralD deleted the refactor/spectrum-geometry-split branch July 5, 2026 08:59
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