-
Notifications
You must be signed in to change notification settings - Fork 0
Polish: album-art accent + liquid-glass clock + blurred backdrop #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tirthfx
wants to merge
18
commits into
phase-9-volume-gesture
Choose a base branch
from
polish-accent-glass-blur
base: phase-9-volume-gesture
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
53a512c
Polish: album-art accent, liquid-glass clock, blurred lock-screen bac…
tirthfx 8ca1e43
Polish: reference lock-screen look + custom wallpaper picker
tirthfx 762df5f
Polish: clear Liquid Glass player card + softer glass clock
tirthfx 0c6198c
Polish: expand zoom animation, blur adjuster, SF Pro clock, matched pill
tirthfx 2f633d6
Revert "Polish: expand zoom animation, blur adjuster, SF Pro clock, m…
tirthfx 2c4fb6b
Reapply "Polish: expand zoom animation, blur adjuster, SF Pro clock, …
tirthfx fbc93a8
Polish: match L2 reference — bigger cover, compact mini pill, neutral…
tirthfx 2cf9ef1
Polish: clear-glass mini pill, 480pt cover, bare hour:minute clock
tirthfx 601af0f
Polish: reference clock glyphs, squarer cover edges, working grow zoom
tirthfx 90cf461
Polish: bigger compact clock (78 -> 96) to match reference proportions
tirthfx ba733c1
Phase 5 visual spec: persistent morphing cluster + LockScreenLayout c…
tirthfx 0415ef2
Lock-screen fix: idle = Large Clock + corner chip, tap grows into card
tirthfx f355a78
Round 2: measured clock scale-ups, centered idle mini-player, tighter…
tirthfx e54d5d4
Round 3: bigger idle clock, minimal left-aligned idle chip, taller pill
tirthfx b02d699
ui: add regular LiquidGlassStyle and support macOS 26 glassEffect
tirthfx ce3a247
layout: support dynamic screen-relative idle chip sizing and adjust l…
tirthfx 7e3270a
Round 4: absolute specs, real Liquid Glass pill, clock snaps not tweens
tirthfx ce2ce0d
Revert round-4 lock-screen changes
tirthfx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,62 @@ | ||||||||||||||||||||||||
| import AppKit | ||||||||||||||||||||||||
| import SwiftUI | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| extension NSImage { | ||||||||||||||||||||||||
| /// A vibrant accent color sampled from the album art, used to tint the glass | ||||||||||||||||||||||||
| /// edge glow and the current lyric line on both surfaces (creative polish, | ||||||||||||||||||||||||
| /// PRD "dynamic album-art accent color"). | ||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||
| /// Downsamples to a small bitmap, averages the reasonably saturated, | ||||||||||||||||||||||||
| /// mid-bright pixels (so near-black/near-white backgrounds don't dominate), | ||||||||||||||||||||||||
| /// then normalizes saturation/brightness so the result always reads as an | ||||||||||||||||||||||||
| /// accent rather than a muddy or washed-out tone. Falls back to white. | ||||||||||||||||||||||||
| func accentColor() -> Color { | ||||||||||||||||||||||||
| let side = 24 | ||||||||||||||||||||||||
| guard let rep = downsampledBitmap(side: side) else { return .white } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| var rSum = 0.0, gSum = 0.0, bSum = 0.0, weight = 0.0 | ||||||||||||||||||||||||
| for y in 0..<side { | ||||||||||||||||||||||||
| for x in 0..<side { | ||||||||||||||||||||||||
| guard let pixel = rep.colorAt(x: x, y: y)?.usingColorSpace(.sRGB) else { continue } | ||||||||||||||||||||||||
| let s = Double(pixel.saturationComponent) | ||||||||||||||||||||||||
| let v = Double(pixel.brightnessComponent) | ||||||||||||||||||||||||
| // Favor colorful, mid-bright pixels; heavily discount flat | ||||||||||||||||||||||||
| // dark/bright areas (letterboxing, white sleeves, shadows). | ||||||||||||||||||||||||
| let w = s * ((v > 0.12 && v < 0.97) ? 1.0 : 0.08) | ||||||||||||||||||||||||
| rSum += Double(pixel.redComponent) * w | ||||||||||||||||||||||||
| gSum += Double(pixel.greenComponent) * w | ||||||||||||||||||||||||
| bSum += Double(pixel.blueComponent) * w | ||||||||||||||||||||||||
| weight += w | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| guard weight > 0.0001 else { return .white } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| let base = NSColor( | ||||||||||||||||||||||||
| srgbRed: rSum / weight, green: gSum / weight, blue: bSum / weight, alpha: 1 | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| // Normalize so the tint always pops, even from desaturated art. | ||||||||||||||||||||||||
| let boosted = NSColor( | ||||||||||||||||||||||||
| hue: base.hueComponent, | ||||||||||||||||||||||||
| saturation: min(max(base.saturationComponent, 0.55), 0.9), | ||||||||||||||||||||||||
| brightness: max(base.brightnessComponent, 0.78), | ||||||||||||||||||||||||
| alpha: 1 | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| return Color(nsColor: boosted) | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private func downsampledBitmap(side: Int) -> NSBitmapImageRep? { | ||||||||||||||||||||||||
| guard let rep = NSBitmapImageRep( | ||||||||||||||||||||||||
| bitmapDataPlanes: nil, pixelsWide: side, pixelsHigh: side, | ||||||||||||||||||||||||
| bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, | ||||||||||||||||||||||||
| colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0 | ||||||||||||||||||||||||
| ) else { return nil } | ||||||||||||||||||||||||
| rep.size = NSSize(width: side, height: side) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| NSGraphicsContext.saveGraphicsState() | ||||||||||||||||||||||||
| NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep) | ||||||||||||||||||||||||
| draw(in: NSRect(x: 0, y: 0, width: side, height: side), | ||||||||||||||||||||||||
| from: .zero, operation: .copy, fraction: 1) | ||||||||||||||||||||||||
| NSGraphicsContext.restoreGraphicsState() | ||||||||||||||||||||||||
|
Comment on lines
+55
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In AppKit,
Suggested change
|
||||||||||||||||||||||||
| return rep | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Downsampling to a 24x24 grid requires 576 iterations of
colorAt(x:y:)andusingColorSpace(.sRGB)on the main thread, which is highly inefficient and can cause noticeable UI micro-stutters during track changes.By reducing the downsample size to
12(144 pixels) and removing the redundant.usingColorSpace(.sRGB)call (since the bitmap is already initialized indeviceRGB), we can achieve a virtually identical accent color with a fraction of the CPU overhead.