Update Liquid Glass for Lock Screen Widgets

This commit is contained in:
Hariharan Mudaliar 2026-01-22 15:57:17 +05:30
commit 2d86127175
No known key found for this signature in database
GPG key ID: 025583EB0BE5640E
5 changed files with 31 additions and 162 deletions

View file

@ -7,7 +7,7 @@
"location" : "https://github.com/Ebullioscopic/AtollExtensionKit",
"state" : {
"branch" : "main",
"revision" : "a1303629e532337594787b981b499560a99c6c93"
"revision" : "ebe35277572a349fad26abeb6fc552cb5251d584"
}
},
{

View file

@ -556,20 +556,6 @@ struct ContentView: View {
.frame(width: 76, alignment: .trailing)
}
.frame(height: vm.effectiveClosedNotchHeight + (isHovering ? 8 : 0), alignment: .center)
} else if coordinator.sneakPeek.show,
case let .extensionLiveActivity(bundleID, activityID) = coordinator.sneakPeek.type,
activeSneakPeekStyle == .inline,
vm.notchState == .closed,
!vm.hideOnClosed {
let inlinePayload = extensionLiveActivityManager.payload(bundleIdentifier: bundleID, activityID: activityID)
ExtensionInlineSneakPeekView(
payload: inlinePayload,
accentColor: coordinator.sneakPeek.accentColor ?? .gray,
notchHeight: vm.effectiveClosedNotchHeight,
closedNotchWidth: vm.closedNotchSize.width,
isHovering: isHovering
)
.transition(AnyTransition.move(edge: .trailing).combined(with: .opacity))
} else if coordinator.sneakPeek.show && Defaults[.inlineHUD] && (coordinator.sneakPeek.type != .music) && (coordinator.sneakPeek.type != .battery) && (coordinator.sneakPeek.type != .timer) && (coordinator.sneakPeek.type != .reminder) && (coordinator.sneakPeek.type != .volume || vm.notchState == .closed) {
InlineHUD(type: $coordinator.sneakPeek.type, value: $coordinator.sneakPeek.value, icon: $coordinator.sneakPeek.icon, hoverAnimation: $isHovering, gestureProgress: $gestureProgress)
.transition(
@ -1956,7 +1942,10 @@ struct ContentView: View {
}
private func resolvedSneakPeekStyle() -> SneakPeekStyle {
coordinator.sneakPeek.styleOverride ?? Defaults[.sneakPeekStyles]
if case .extensionLiveActivity = coordinator.sneakPeek.type {
return .standard
}
return coordinator.sneakPeek.styleOverride ?? Defaults[.sneakPeekStyles]
}
}

View file

@ -304,148 +304,6 @@ struct ExtensionNotchSectionView: View {
}
}
struct ExtensionInlineSneakPeekView: View {
let payload: ExtensionLiveActivityPayload?
let accentColor: Color
let notchHeight: CGFloat
let closedNotchWidth: CGFloat
let isHovering: Bool
private let wingPadding: CGFloat = 16
private var descriptor: AtollLiveActivityDescriptor? { payload?.descriptor }
private var resolvedAccent: Color {
guard let descriptor else { return accentColor }
return descriptor.accentColor.resolvedColor(fallback: accentColor)
}
private var trailingRenderable: ExtensionTrailingRenderable? {
descriptor.map { resolvedExtensionTrailingRenderable(for: $0) }
}
private var contentHeight: CGFloat {
max(0, notchHeight - (isHovering ? 0 : 12))
}
private var centerWidth: CGFloat {
max(closedNotchWidth + (isHovering ? 8 : 0), 120)
}
private var iconDiameter: CGFloat {
max(contentHeight - 8, 28)
}
private var leftWingWidth: CGFloat {
wingPadding + iconDiameter
}
private var baseTrailingWidth: CGFloat {
max(iconDiameter, 56)
}
private var trailingContentWidth: CGFloat {
guard let payload else { return baseTrailingWidth }
return ExtensionLayoutMetrics.trailingWidth(
for: payload,
baseWidth: baseTrailingWidth,
maxWidth: baseTrailingWidth + centerWidth * 0.6
)
}
private var rightWingWidth: CGFloat {
wingPadding + trailingContentWidth
}
private var trailingContentAvailableWidth: CGFloat {
max(0, trailingContentWidth - wingPadding)
}
var body: some View {
HStack(spacing: 0) {
leadingWing
centerSection
trailingWing
}
.frame(height: notchHeight + (isHovering ? 8 : 0), alignment: .center)
}
private var leadingWing: some View {
Color.clear
.frame(width: leftWingWidth, height: contentHeight)
.background(alignment: .leading) {
Group {
if let descriptor {
ExtensionLeadingContentView(
content: resolvedExtensionLeadingContent(for: descriptor),
badge: descriptor.badgeIcon,
accent: resolvedAccent,
frameWidth: iconDiameter,
frameHeight: iconDiameter,
defaultIcon: descriptor.leadingIcon
)
} else {
RoundedRectangle(cornerRadius: iconDiameter * 0.25, style: .continuous)
.fill(resolvedAccent.gradient)
.frame(width: iconDiameter, height: iconDiameter)
}
}
.frame(width: iconDiameter, height: iconDiameter)
.frame(maxHeight: .infinity, alignment: .center)
.padding(.leading, wingPadding / 2)
}
}
private var centerSection: some View {
Rectangle()
.fill(Color.black)
.frame(width: centerWidth, height: contentHeight)
}
@ViewBuilder
private var trailingWing: some View {
Color.clear
.frame(width: rightWingWidth, height: contentHeight)
.background(alignment: .trailing) {
if let descriptor, let trailingRenderable {
VStack(alignment: .trailing, spacing: 6) {
switch trailingRenderable {
case let .content(content):
if case .none = content {
Spacer(minLength: 0)
} else {
ExtensionEdgeContentView(
content: content,
accent: resolvedAccent,
availableWidth: trailingContentAvailableWidth,
alignment: .trailing
)
.frame(maxWidth: trailingContentAvailableWidth, alignment: .trailing)
}
case let .indicator(indicator):
ExtensionProgressIndicatorView(
indicator: indicator,
progress: descriptor.progress,
accent: resolvedAccent,
estimatedDuration: descriptor.estimatedDuration,
maxVisualHeight: contentHeight
)
}
Spacer(minLength: 0)
}
.padding(.trailing, wingPadding / 2)
.padding(.vertical, 6)
} else {
RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(resolvedAccent.opacity(0.25))
.frame(width: max(32, trailingContentAvailableWidth * 0.6), height: max(16, contentHeight * 0.4))
.padding(.trailing, wingPadding / 2)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .trailing)
.padding(.vertical, 6)
}
}
}
}
struct ExtensionNotchSectionHeader: View {
let section: AtollNotchContentSection

View file

@ -83,7 +83,9 @@ struct ExtensionLockScreenWidgetView: View {
@ViewBuilder
private func backgroundLayer(shape: RoundedRectangle) -> some View {
if shouldUseGlassBackdrop {
if descriptor.material == .liquid {
liquidGlassBackground(shape: shape)
} else if shouldUseGlassHighlight {
if #available(macOS 26.0, *) {
ZStack {
shape
@ -110,6 +112,18 @@ struct ExtensionLockScreenWidgetView: View {
}
}
@ViewBuilder
private func liquidGlassBackground(shape: RoundedRectangle) -> some View {
LiquidGlassBackground(variant: requestedLiquidGlassVariant, cornerRadius: descriptor.cornerRadius) {
Color.black.opacity(0.08)
}
.overlay {
tintOverlay(shape: shape)
}
.allowsHitTesting(false)
.accessibilityHidden(true)
}
private var baseMaterialStyle: AnyShapeStyle {
switch descriptor.material {
case .frosted:
@ -160,8 +174,15 @@ struct ExtensionLockScreenWidgetView: View {
}
}
private var shouldUseGlassBackdrop: Bool {
descriptor.material == .liquid || (appearance?.enableGlassHighlight ?? false)
private var shouldUseGlassHighlight: Bool {
(appearance?.enableGlassHighlight ?? false) && descriptor.material != .liquid
}
private var requestedLiquidGlassVariant: LiquidGlassVariant {
guard let requested = appearance?.liquidGlassVariant?.rawValue else {
return LiquidGlassVariant.defaultVariant
}
return LiquidGlassVariant.clamped(requested)
}
@ViewBuilder

View file

@ -172,7 +172,8 @@ final class ExtensionLiveActivityManager: ObservableObject {
guard let requestedStyle = config.style else { return nil }
switch requestedStyle {
case .inline:
return .inline
logDiagnostics("Inline sneak peek requested for \(descriptor.id); host will show standard mode instead")
return .standard
case .standard:
return .standard
}