mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
BugFix: Focus Live Activity
This commit is contained in:
parent
793a07795f
commit
78ae27a7fe
1 changed files with 65 additions and 27 deletions
|
|
@ -22,7 +22,6 @@ struct DoNotDisturbLiveActivity: View {
|
|||
@State private var scaleResetTask: Task<Void, Never>?
|
||||
@State private var collapseTask: Task<Void, Never>?
|
||||
@State private var cleanupTask: Task<Void, Never>?
|
||||
@State private var labelIntrinsicWidth: CGFloat = 0
|
||||
|
||||
private enum ToastTiming {
|
||||
static let activeDisplay: UInt64 = 1800 // focus enabled toast linger
|
||||
|
|
@ -119,14 +118,17 @@ struct DoNotDisturbLiveActivity: View {
|
|||
}
|
||||
|
||||
private var desiredLabelWidth: CGFloat {
|
||||
let measuredWidth = labelIntrinsicWidth + 8 // horizontal padding inside the label
|
||||
let fallbackWidth = max(collapsedNotchWidth * 0.52, 136)
|
||||
var width = max(measuredWidth, fallbackWidth)
|
||||
var width = fallbackWidth
|
||||
|
||||
if focusMode == .doNotDisturb && shouldShowLabel {
|
||||
width = max(width, 164)
|
||||
}
|
||||
|
||||
if !shouldMarqueeLabel {
|
||||
width = max(width, labelIntrinsicWidth + 8)
|
||||
}
|
||||
|
||||
return width
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +136,31 @@ struct DoNotDisturbLiveActivity: View {
|
|||
focusToastMode ? (isExpanded && !labelText.isEmpty) : (showLabelSetting && isExpanded && !labelText.isEmpty)
|
||||
}
|
||||
|
||||
private var labelIntrinsicWidth: CGFloat {
|
||||
guard !labelText.isEmpty else { return 0 }
|
||||
return (labelText as NSString).size(withAttributes: [.font: focusLabelNSFont]).width
|
||||
}
|
||||
|
||||
private var shouldMarqueeLabel: Bool {
|
||||
shouldShowLabel && labelIntrinsicWidth > focusLabelBaselineWidth
|
||||
}
|
||||
|
||||
private var marqueeFrameWidth: CGFloat {
|
||||
max(48, labelWingWidth - 8)
|
||||
}
|
||||
|
||||
private var focusLabelFont: Font {
|
||||
.system(size: 12, weight: .semibold, design: .rounded)
|
||||
}
|
||||
|
||||
private var focusLabelNSFont: NSFont {
|
||||
NSFont.systemFont(ofSize: 12, weight: .semibold)
|
||||
}
|
||||
|
||||
private var focusLabelBaselineWidth: CGFloat {
|
||||
FocusLabelMetrics.baselineWidth
|
||||
}
|
||||
|
||||
// MARK: - Focus metadata
|
||||
|
||||
private var focusMode: FocusModeType {
|
||||
|
|
@ -247,25 +274,31 @@ struct DoNotDisturbLiveActivity: View {
|
|||
Color.clear
|
||||
.overlay(alignment: .trailing) {
|
||||
if shouldShowLabel {
|
||||
Text(labelText)
|
||||
.font(.system(size: 12, weight: .semibold, design: .rounded))
|
||||
.foregroundColor(labelColor)
|
||||
.lineLimit(1)
|
||||
.minimumScaleFactor(0.8)
|
||||
.contentTransition(.opacity)
|
||||
.background(
|
||||
GeometryReader { proxy in
|
||||
Color.clear
|
||||
.preference(key: FocusLabelWidthPreferenceKey.self, value: proxy.size.width)
|
||||
}
|
||||
)
|
||||
.padding(.horizontal, 4)
|
||||
Group {
|
||||
if shouldMarqueeLabel {
|
||||
MarqueeText(
|
||||
.constant(labelText),
|
||||
font: focusLabelFont,
|
||||
nsFont: .caption1,
|
||||
textColor: labelColor,
|
||||
minDuration: 0.4,
|
||||
frameWidth: marqueeFrameWidth
|
||||
)
|
||||
.frame(width: marqueeFrameWidth, alignment: .trailing)
|
||||
} else {
|
||||
Text(labelText)
|
||||
.font(focusLabelFont)
|
||||
.foregroundColor(labelColor)
|
||||
.lineLimit(1)
|
||||
.minimumScaleFactor(0.8)
|
||||
.contentTransition(.opacity)
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 4)
|
||||
}
|
||||
}
|
||||
.animation(.smooth(duration: 0.3), value: shouldShowLabel)
|
||||
.onPreferenceChange(FocusLabelWidthPreferenceKey.self) { value in
|
||||
labelIntrinsicWidth = value
|
||||
}
|
||||
}
|
||||
|
||||
private var labelColor: Color {
|
||||
|
|
@ -385,14 +418,6 @@ struct DoNotDisturbLiveActivity: View {
|
|||
.background(Color.black)
|
||||
}
|
||||
|
||||
private struct FocusLabelWidthPreferenceKey: PreferenceKey {
|
||||
static var defaultValue: CGFloat = 0
|
||||
|
||||
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
|
||||
value = max(value, nextValue())
|
||||
}
|
||||
}
|
||||
|
||||
private final class SymbolAvailabilityCache {
|
||||
static let shared = SymbolAvailabilityCache()
|
||||
private var cache: [String: Bool] = [:]
|
||||
|
|
@ -418,3 +443,16 @@ private final class SymbolAvailabilityCache {
|
|||
return available
|
||||
}
|
||||
}
|
||||
|
||||
private enum FocusLabelMetrics {
|
||||
static let baselineText = "Do Not Disturb"
|
||||
|
||||
static let baselineWidth: CGFloat = {
|
||||
#if canImport(AppKit)
|
||||
let font = NSFont.systemFont(ofSize: 12, weight: .semibold)
|
||||
return (baselineText as NSString).size(withAttributes: [.font: font]).width
|
||||
#else
|
||||
return 0
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue