Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ All notable changes to Pullo are listed here, newest first. The format follows [
### Changed
- Pullo no longer wakes up on every mouse move: it only follows the pointer while it is over the notch, which cuts its CPU use while you move the mouse elsewhere by about 95%.

### Fixed
- Opening the panel with the glass style no longer briefly takes about 300 MB of memory. The glass background stays the same size while the panel animates, so it peaks under 30 MB.

## [0.11.3] - 2026-10-25

### Fixed
Expand Down
17 changes: 16 additions & 1 deletion Sources/Pullo/Features/Notch/NotchBackground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ struct NotchBackground<S: Shape>: View {
let height: CGFloat
var style: PanelStyle?
var scale: CGFloat = 1
var glassSize: CGSize?

private var currentStyle: PanelStyle { style ?? settings.panelStyle }

var body: some View {
if usesGlass, #available(macOS 26, *) {
ZStack {
Color.clear.glassEffect(.regular, in: shape)
glass
if currentStyle == .glassDarkTop {
darkTop
}
Expand All @@ -27,6 +28,20 @@ struct NotchBackground<S: Shape>: View {
}
}

@available(macOS 26, *)
@ViewBuilder
private var glass: some View {
if let glassSize {
Color.clear
.glassEffect(.regular, in: Rectangle())
.frame(width: glassSize.width, height: glassSize.height)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.transaction { $0.animation = nil }
} else {
Color.clear.glassEffect(.regular, in: shape)
}
}

private var darkTop: some View {
RadialGradient(
stops: [
Expand Down
19 changes: 18 additions & 1 deletion Sources/Pullo/Features/Notch/NotchRootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ struct NotchRootView: View {
@Environment(AccountStore.self) private var accounts
@Environment(AppSettings.self) private var settings
@Environment(\.accessibilityReduceTransparency) private var reduceTransparency
@State private var lastShown: NotchState = .open

var body: some View {
let state = notch.state
Expand All @@ -23,6 +24,22 @@ struct NotchRootView: View {
.hintLayer(within: CGSize(width: size.width + radii.top * 2, height: size.height))
.animation(Motion.peek, value: notch.liveCI)
.environment(\.panelGlass, settings.panelStyle.usesGlass(reduceTransparency: reduceTransparency))
.onChange(of: state) { _, new in
if new != .closed { lastShown = new }
}
}

private func background(state: NotchState, shape: NotchShape, height: CGFloat) -> some View {
let glassState = state == .closed ? lastShown : state
let glassSize = notch.layout.size(for: glassState)
let glassRadii = notch.layout.radii(for: glassState)
return NotchBackground(
state: state,
shape: shape,
notchWidth: notch.geometry.notchSize.width,
height: height,
glassSize: CGSize(width: glassSize.width + glassRadii.top * 2, height: glassSize.height)
)
}

private func panel(state: NotchState, size: CGSize, radii: (top: CGFloat, bottom: CGFloat), shape: NotchShape) -> some View {
Expand All @@ -40,7 +57,7 @@ struct NotchRootView: View {
}
.frame(width: size.width, height: size.height, alignment: .top)
.padding(.horizontal, radii.top)
.background { NotchBackground(state: state, shape: shape, notchWidth: notch.geometry.notchSize.width, height: size.height) }
.background { background(state: state, shape: shape, height: size.height) }
.clipShape(shape)
.compositingGroup()
.shadow(color: .black.opacity(state == .closed ? 0 : 0.55), radius: state == .open ? 26 : 14, y: 8)
Expand Down
Loading