feat(#248): 壁紙ローディングインジケータを回転する金のジオデシック球体に刷新#286
Conversation
プレーンな Progress(.circular) を、Lyra の ripple と歌詞ハイライトの ゴールドグラデーションを踏襲した「ソナーリング」インジケータに置き換え。 - Canvas + TimelineView(.animation) で GPU 駆動描画(RippleView と同方式) - 同心リングが core から rim へ拡散しながらフェード(明滅は sin で対称) - ダークハロー + ゴールドグラデの二重ストローク、frosted disc 背景 + 影で、明るい壁紙でも暗い壁紙でも視認可能 - #252 の条件付きツリー除去(showLoadingIndicator==false で完全に消す)を維持。 accessibilityIdentifier / allowsHitTesting(false) も維持 - 中央配置で top-leading の歌詞領域を侵さない - 出現/消滅は scale+opacity でフェード - 明暗 2 背景の #Preview を追加
Replace the gold sonar rings with a slowly rotating gold geodesic sphere — a Goldberg polyhedron (12 pentagons + 30 hexagons, "a soccer ball with a few extra faces"), the dual of a freq-2 icosphere. The thin gold wireframe is depth-cued (near struts brighter/thicker, far ones fainter/thinner) and each strut carries a soft dark halo so it reads over both bright and dark wallpapers WITHOUT any backing disc. A subtle "Downloading wallpaper" caption sits below the sphere — thin, letter-spaced gold with a dark shadow, telling the user what the wait is for without pulling focus from the wireframe. The wireframe geometry is rotation-independent, so it is built once (GeodesicGeometry.edges) and only the per-frame projection changes (#252 spirit). Conditional inclusion (not .opacity(0)) is preserved so no idle TimelineView burns GPU when not loading. GeodesicGeometry / Vertex3D are exposed as internal (not private) so the pure geometry is unit-tested via @testable import Views: exactly 120 dual edges, every endpoint on the unit sphere, no degenerate struts.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📝 WalkthroughWalkthroughReplaces the plain ChangesGeodesic Loading Indicator
Version Bump
Sequence Diagram(s)sequenceDiagram
participant WallpaperPresenter
participant WallpaperLoadingOverlay
participant LoadingIndicatorContent
participant GeodesicLoadingIndicator
participant GeodesicGeometry
participant Canvas
WallpaperPresenter-->>WallpaperLoadingOverlay: showLoadingIndicator = true
WallpaperLoadingOverlay->>LoadingIndicatorContent: insert into ZStack (scale+opacity transition)
LoadingIndicatorContent->>GeodesicLoadingIndicator: render
GeodesicLoadingIndicator->>GeodesicGeometry: buildEdges()
GeodesicGeometry-->>GeodesicLoadingIndicator: [(Vertex3D, Vertex3D)] × 120
loop TimelineView tick
GeodesicLoadingIndicator->>GeodesicLoadingIndicator: rotate + project vertices
GeodesicLoadingIndicator->>Canvas: drawEdge (depth-sorted, GeodesicGold halo+stroke)
end
WallpaperPresenter-->>WallpaperLoadingOverlay: showLoadingIndicator = false
WallpaperLoadingOverlay->>LoadingIndicatorContent: remove from ZStack (fade+scale out)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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 |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
Sources/Views/Overlay/OverlayContentView.swift (1)
171-268: ⚡ Quick winExtract geometry-generation feature logic from
OverlayContentView.swift.
GeodesicGeometry/Vertex3Dand related construction logic are substantial feature logic in a*View.swiftfile. Please move them to dedicated non-view source files (keepingGeodesicLoadingIndicatoras the view layer) so the view file stays composition-focused.As per coding guidelines,
**/*View.swift: “Views do not own business logic... do not add feature logic to SwiftUI views.”🤖 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 `@Sources/Views/Overlay/OverlayContentView.swift` around lines 171 - 268, Move the geometric construction logic out of the view file to maintain separation of concerns. Extract GeodesicGeometry, Vertex3D, GeodesicMetrics, and GeodesicGold to a dedicated non-view source file (e.g., GeodesicGeometry.swift), keeping only the GeodesicLoadingIndicator view component and any view-specific code in OverlayContentView.swift. Update imports in OverlayContentView.swift to reference the moved types from their new location.Source: Coding guidelines
🤖 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 `@Sources/Views/Overlay/OverlayContentView.swift`:
- Around line 171-268: Move the geometric construction logic out of the view
file to maintain separation of concerns. Extract GeodesicGeometry, Vertex3D,
GeodesicMetrics, and GeodesicGold to a dedicated non-view source file (e.g.,
GeodesicGeometry.swift), keeping only the GeodesicLoadingIndicator view
component and any view-specific code in OverlayContentView.swift. Update imports
in OverlayContentView.swift to reference the moved types from their new
location.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 98ef545f-1ba9-4905-ac67-b99739da2153
📒 Files selected for processing (3)
Sources/VersionHandler/Resources/version.txtSources/Views/Overlay/OverlayContentView.swiftTests/ViewsTests/GeodesicGeometryTests.swift
|
CodeRabbit の nitpick(
|
#287)        ## 概要 `#286`(#248) で導入したジオデシック球体ローディングインジケータの**幾何生成ロジック**を、`OverlayContentView.swift`(`*View.swift`)から専用ファイル `GeodesicGeometry.swift` へ抽出する。 CodeRabbit が `#286` で残した nitpick への後続対応: > **Extract geometry-generation feature logic from `OverlayContentView.swift`.** > `GeodesicGeometry`/`Vertex3D` and related construction logic are substantial feature logic in a `*View.swift` file. リポジトリの `.coderabbit.yaml` ガイドライン(`**/*View.swift`: "Views do not own business logic")に沿い、View ファイルを SwiftUI View 型のみに保つ。 ## 変更点 | 種別 | 内容 | |---|---| | 移動 | `Vertex3D`(unit-sphere 頂点)+ `GeodesicGeometry`(Goldberg 多面体のエッジ生成)→ `GeodesicGeometry.swift` | | 残置 | `GeodesicMetrics` / `GeodesicGold` は描画専用の `private` 定数 → Canvas 描画のみが参照するため View 側に残し、access control を不必要に広げない | | 保持 | `GeodesicGeometry` は `internal` のまま → `GeodesicGeometryTests` が `@testable import Views` で到達可能 | ## 動作・テスト - 振る舞い変更なし(純粋なファイル分割) - `swift build` 成功 - `GeodesicGeometryTests`(120 edges / unit-sphere / 非退化)3件合格 - フルスイート **942 tests** 全合格 Refs #248
Closes #248
壁紙ローディングインジケータを、ゆっくり回転する金のジオデシック球体へ刷新しました。Goldberg 多面体(正五角形 12 + 正六角形 30 — 「サッカーボールに面をちょっと足した」形、freq-2 アイコスフィアの双対)を細い金のワイヤーフレームで描き、奥行きに応じて線幅と明度を変化させています。
採用デザイン
実機(UTM macOS ゲスト)で、実際の壁紙 DL 中に表示させたところ:
#B8942D → #EDCF73 → #FFEB99 → #CCA64D → #A68038)と同系。Lyra の世界観に揃えています。Downloading wallpaperキャプション: 球体の下に金の細字・トラッキング広め・暗い影で、何を待っているかを伝えつつミニマルさは維持。動きはこちら(回転ループ):
実機(UTM)動作確認
UTM macOS ゲストでのフルスクリーンショット
ヘッダーの曲情報("The Quiet Call" / David Arkenstone)と球体 + キャプションが、デスクトップ壁紙の上にデスクトップレベルのオーバーレイとして描画されているのが確認できます。トリクルサーバで壁紙 DL を永続的に「進行中」に保ち、インジケータを画面に留めて撮影しています(通常は DL 中のみ表示)。
没になった候補たち(慰霊)
採用に至るまでの試行錯誤の記録です。
散っていったデザイン案を見る
元祖案 — Sonar rings(最初の没案)
金のソナーリングが核から広がるデザイン。「もっとかっこいいのがいい」で却下。
初期4案 — A/B/C/D
A: Orbit dots / B: Equalizer / C: Conic ring / D: Mesh sphere。D(メッシュ球体) が選ばれ、A・B・C は散りました。
球体の試行錯誤
D を磨く過程。緯度経度メッシュ → Goldberg(太線)→ 採用(細線)。
緯度経度メッシュ(「四角をつなぐメッシュじゃない方がいい」で却下):
Goldberg だが線が太い版(「軸を細く」で却下):
技術メモ
GeodesicGeometry.edges)し、毎フレームは射影だけを再計算(bug: パフォーマンス低下と電力消費・発熱・ファン回転の悪化 #252 の精神)。.opacity(0)ではなく 条件付き挿入を維持 — 非表示時にアイドルなTimelineViewが GPU を焼かないように(bug: パフォーマンス低下と電力消費・発熱・ファン回転の悪化 #252)。GeodesicGeometry/Vertex3Dをinternal(非private)にし、純粋な幾何ロジックを@testable import Viewsでユニットテスト。テスト
GeodesicGeometryTests: 双対エッジがちょうど 120 本、全端点が単位球面上、退化ストラット無し、を検証。swift test全 942 tests green。make format済み。