mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-28 23:54:32 +00:00
UIFix: Window Shadows and Notch Shadows
This commit is contained in:
parent
80d132a85f
commit
3bba53c583
4 changed files with 68 additions and 17 deletions
|
|
@ -126,6 +126,20 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
return cornerRadiusInsets
|
return cornerRadiusInsets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var currentShadowPadding: CGFloat {
|
||||||
|
notchShadowPaddingValue(isMinimalistic: enableMinimalisticUI)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var currentNotchShape: NotchShape {
|
||||||
|
let topRadius = (vm.notchState == .open && Defaults[.cornerRadiusScaling])
|
||||||
|
? activeCornerRadiusInsets.opened.top
|
||||||
|
: activeCornerRadiusInsets.closed.top
|
||||||
|
let bottomRadius = (vm.notchState == .open && Defaults[.cornerRadiusScaling])
|
||||||
|
? activeCornerRadiusInsets.opened.bottom
|
||||||
|
: activeCornerRadiusInsets.closed.bottom
|
||||||
|
return NotchShape(topCornerRadius: topRadius, bottomCornerRadius: bottomRadius)
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let interactionsEnabled = !lockScreenManager.isLocked
|
let interactionsEnabled = !lockScreenManager.isLocked
|
||||||
|
|
@ -139,16 +153,20 @@ struct ContentView: View {
|
||||||
)
|
)
|
||||||
.padding([.horizontal, .bottom], vm.notchState == .open ? 12 : 0)
|
.padding([.horizontal, .bottom], vm.notchState == .open ? 12 : 0)
|
||||||
.background(.black)
|
.background(.black)
|
||||||
.mask {
|
.clipShape(currentNotchShape)
|
||||||
((vm.notchState == .open) && Defaults[.cornerRadiusScaling])
|
.compositingGroup()
|
||||||
? NotchShape(topCornerRadius: activeCornerRadiusInsets.opened.top, bottomCornerRadius: activeCornerRadiusInsets.opened.bottom)
|
.shadow(
|
||||||
.drawingGroup()
|
color: ((vm.notchState == .open || isHovering) && Defaults[.enableShadow])
|
||||||
: NotchShape(topCornerRadius: activeCornerRadiusInsets.closed.top, bottomCornerRadius: activeCornerRadiusInsets.closed.bottom)
|
? .black.opacity(0.6)
|
||||||
.drawingGroup()
|
: .clear,
|
||||||
}
|
radius: Defaults[.cornerRadiusScaling] ? 10 : 5
|
||||||
.padding(.bottom, vm.notchState == .open && Defaults[.extendHoverArea] ? 0 : (vm.effectiveClosedNotchHeight == 0)
|
)
|
||||||
? zeroHeightHoverPadding
|
.padding(.bottom,
|
||||||
: 0
|
currentShadowPadding + (
|
||||||
|
vm.notchState == .open && Defaults[.extendHoverArea]
|
||||||
|
? 0
|
||||||
|
: (vm.effectiveClosedNotchHeight == 0 ? zeroHeightHoverPadding : 0)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
mainLayout
|
mainLayout
|
||||||
|
|
@ -280,7 +298,11 @@ struct ContentView: View {
|
||||||
// .keyboardShortcut("E", modifiers: .command)
|
// .keyboardShortcut("E", modifiers: .command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: dynamicNotchSize.width, maxHeight: dynamicNotchSize.height, alignment: .top)
|
.frame(
|
||||||
|
maxWidth: dynamicNotchSize.width,
|
||||||
|
maxHeight: dynamicNotchSize.height + currentShadowPadding,
|
||||||
|
alignment: .top
|
||||||
|
)
|
||||||
.animation(dynamicNotchResizeAnimation, value: dynamicNotchSize)
|
.animation(dynamicNotchResizeAnimation, value: dynamicNotchSize)
|
||||||
.animation(.easeInOut(duration: 0.4), value: coordinator.currentView)
|
.animation(.easeInOut(duration: 0.4), value: coordinator.currentView)
|
||||||
.environmentObject(privacyManager)
|
.environmentObject(privacyManager)
|
||||||
|
|
@ -291,7 +313,6 @@ struct ContentView: View {
|
||||||
vm.shouldRecheckHover.toggle()
|
vm.shouldRecheckHover.toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.shadow(color: ((vm.notchState == .open || isHovering) && Defaults[.enableShadow]) ? .black.opacity(0.6) : .clear, radius: Defaults[.cornerRadiusScaling] ? 10 : 5)
|
|
||||||
.background(dragDetector)
|
.background(dragDetector)
|
||||||
.environmentObject(vm)
|
.environmentObject(vm)
|
||||||
.environmentObject(webcamManager)
|
.environmentObject(webcamManager)
|
||||||
|
|
|
||||||
|
|
@ -278,11 +278,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
// Use minimalistic or normal size based on settings, then adjust for stats layout
|
// Use minimalistic or normal size based on settings, then adjust for stats layout
|
||||||
let baseSize = Defaults[.enableMinimalisticUI] ? minimalisticOpenNotchSize : openNotchSize
|
let baseSize = Defaults[.enableMinimalisticUI] ? minimalisticOpenNotchSize : openNotchSize
|
||||||
return statsAdjustedNotchSize(
|
let adjustedContentSize = statsAdjustedNotchSize(
|
||||||
from: baseSize,
|
from: baseSize,
|
||||||
isStatsTabActive: coordinator.currentView == .stats,
|
isStatsTabActive: coordinator.currentView == .stats,
|
||||||
secondRowProgress: coordinator.statsSecondRowExpansion
|
secondRowProgress: coordinator.statsSecondRowExpansion
|
||||||
)
|
)
|
||||||
|
return addShadowPadding(
|
||||||
|
to: adjustedContentSize,
|
||||||
|
isMinimalistic: Defaults[.enableMinimalisticUI]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureWindowSize(_ size: CGSize, animated: Bool, force: Bool = false) {
|
func ensureWindowSize(_ size: CGSize, animated: Bool, force: Bool = false) {
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,11 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
self.notchSize = updatedTarget
|
self.notchSize = updatedTarget
|
||||||
}
|
}
|
||||||
if let delegate = AppDelegate.shared {
|
if let delegate = AppDelegate.shared {
|
||||||
delegate.ensureWindowSize(updatedTarget, animated: true, force: false)
|
delegate.ensureWindowSize(
|
||||||
|
addShadowPadding(to: updatedTarget, isMinimalistic: Defaults[.enableMinimalisticUI]),
|
||||||
|
animated: true,
|
||||||
|
force: false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
@ -106,7 +110,11 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
self.notchSize = updatedTarget
|
self.notchSize = updatedTarget
|
||||||
}
|
}
|
||||||
if let delegate = AppDelegate.shared {
|
if let delegate = AppDelegate.shared {
|
||||||
delegate.ensureWindowSize(updatedTarget, animated: true, force: false)
|
delegate.ensureWindowSize(
|
||||||
|
addShadowPadding(to: updatedTarget, isMinimalistic: Defaults[.enableMinimalisticUI]),
|
||||||
|
animated: true,
|
||||||
|
force: false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
@ -123,7 +131,11 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
self.notchSize = updatedTarget
|
self.notchSize = updatedTarget
|
||||||
}
|
}
|
||||||
if let delegate = AppDelegate.shared {
|
if let delegate = AppDelegate.shared {
|
||||||
delegate.ensureWindowSize(updatedTarget, animated: false, force: false)
|
delegate.ensureWindowSize(
|
||||||
|
addShadowPadding(to: updatedTarget, isMinimalistic: Defaults[.enableMinimalisticUI]),
|
||||||
|
animated: false,
|
||||||
|
force: false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
@ -184,7 +196,11 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||||
|
|
||||||
let applyWindowResize: () -> Void = {
|
let applyWindowResize: () -> Void = {
|
||||||
guard let delegate = AppDelegate.shared else { return }
|
guard let delegate = AppDelegate.shared else { return }
|
||||||
delegate.ensureWindowSize(targetSize, animated: false, force: true)
|
delegate.ensureWindowSize(
|
||||||
|
addShadowPadding(to: targetSize, isMinimalistic: Defaults[.enableMinimalisticUI]),
|
||||||
|
animated: false,
|
||||||
|
force: true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ private let minimalisticBaseOpenNotchSize: CGSize = .init(width: 420, height: 18
|
||||||
private let minimalisticLyricsExtraHeight: CGFloat = 40
|
private let minimalisticLyricsExtraHeight: CGFloat = 40
|
||||||
let statsSecondRowContentHeight: CGFloat = 120
|
let statsSecondRowContentHeight: CGFloat = 120
|
||||||
let statsGridSpacingHeight: CGFloat = 12
|
let statsGridSpacingHeight: CGFloat = 12
|
||||||
|
let notchShadowPaddingStandard: CGFloat = 18
|
||||||
|
let notchShadowPaddingMinimalistic: CGFloat = 12
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
var minimalisticOpenNotchSize: CGSize {
|
var minimalisticOpenNotchSize: CGSize {
|
||||||
|
|
@ -71,6 +73,14 @@ func statsAdjustedNotchSize(
|
||||||
return adjustedSize
|
return adjustedSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func notchShadowPaddingValue(isMinimalistic: Bool) -> CGFloat {
|
||||||
|
isMinimalistic ? notchShadowPaddingMinimalistic : notchShadowPaddingStandard
|
||||||
|
}
|
||||||
|
|
||||||
|
func addShadowPadding(to size: CGSize, isMinimalistic: Bool) -> CGSize {
|
||||||
|
CGSize(width: size.width, height: size.height + notchShadowPaddingValue(isMinimalistic: isMinimalistic))
|
||||||
|
}
|
||||||
|
|
||||||
enum MusicPlayerImageSizes {
|
enum MusicPlayerImageSizes {
|
||||||
static let cornerRadiusInset: (opened: CGFloat, closed: CGFloat) = (opened: 13.0, closed: 4.0)
|
static let cornerRadiusInset: (opened: CGFloat, closed: CGFloat) = (opened: 13.0, closed: 4.0)
|
||||||
static let size = (opened: CGSize(width: 90, height: 90), closed: CGSize(width: 20, height: 20))
|
static let size = (opened: CGSize(width: 90, height: 90), closed: CGSize(width: 20, height: 20))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue