Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
c8fa702382
commit
2d4d76cc8d
@ -207,6 +207,34 @@ enum FontUtils {
|
||||
)
|
||||
}
|
||||
|
||||
/// Get weight multiplier for visual consistency with font weight
|
||||
/// - Parameter weight: Font weight name
|
||||
/// - Returns: Multiplier for dot size (0.7 to 1.3)
|
||||
static func weightMultiplier(for weight: String) -> CGFloat {
|
||||
switch weight {
|
||||
case "Ultra Light":
|
||||
return 0.7
|
||||
case "Thin":
|
||||
return 0.75
|
||||
case "Light":
|
||||
return 0.8
|
||||
case "Regular":
|
||||
return 0.85
|
||||
case "Medium":
|
||||
return 0.9
|
||||
case "Semibold":
|
||||
return 1.0
|
||||
case "Bold":
|
||||
return 1.1
|
||||
case "Heavy":
|
||||
return 1.2
|
||||
case "Black":
|
||||
return 1.3
|
||||
default:
|
||||
return 1.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a UIFont with specified parameters for measurements
|
||||
/// - Parameters:
|
||||
/// - size: Font size
|
||||
|
||||
@ -22,7 +22,7 @@ struct ClockView: View {
|
||||
|
||||
GeometryReader { geometry in
|
||||
ZStack {
|
||||
// Time display - fills available space within safe areas
|
||||
// Time display - fills entire available space
|
||||
TimeDisplayView(
|
||||
date: viewModel.currentTime,
|
||||
use24Hour: viewModel.style.use24Hour,
|
||||
@ -37,7 +37,6 @@ struct ClockView: View {
|
||||
fontWeight: viewModel.style.fontWeight,
|
||||
fontDesign: viewModel.style.fontDesign
|
||||
)
|
||||
.frame(width: geometry.size.width, height: geometry.size.height)
|
||||
.transition(.opacity)
|
||||
|
||||
// Top overlay - positioned at top with safe area consideration
|
||||
@ -60,6 +59,7 @@ struct ClockView: View {
|
||||
.animation(UIConstants.AnimationCurves.smooth, value: viewModel.isDisplayMode)
|
||||
}
|
||||
}
|
||||
.ignoresSafeArea(.all, edges: viewModel.isDisplayMode ? .bottom : [])
|
||||
.navigationTitle(viewModel.isDisplayMode ? "" : "Clock")
|
||||
.toolbar {
|
||||
if !viewModel.isDisplayMode {
|
||||
|
||||
@ -66,29 +66,26 @@ struct TimeDisplayView: View {
|
||||
let size = proxy.size
|
||||
let portrait = size.height >= size.width
|
||||
|
||||
// Get safe area information to avoid Dynamic Island overlap
|
||||
let safeAreaInsets = proxy.safeAreaInsets
|
||||
let availableWidth = size.width - safeAreaInsets.leading - safeAreaInsets.trailing
|
||||
let availableHeight = size.height - safeAreaInsets.top - safeAreaInsets.bottom
|
||||
|
||||
// Use available space within safe areas for font sizing calculations
|
||||
let availableSize = CGSize(width: availableWidth, height: availableHeight)
|
||||
|
||||
// Use full GeometryReader size for frame (to fill entire space)
|
||||
// Use the full GeometryReader size for maximum space usage
|
||||
let fullScreenSize = size
|
||||
|
||||
// Use optimal font sizing that maximizes space usage within safe areas
|
||||
// Get safe area information for font sizing to avoid Dynamic Island overlap
|
||||
let safeAreaInsets = proxy.safeAreaInsets
|
||||
let _ = size.width - safeAreaInsets.leading - safeAreaInsets.trailing // availableWidth
|
||||
let _ = size.height - safeAreaInsets.top - safeAreaInsets.bottom // availableHeight
|
||||
|
||||
// Use optimal font sizing that maximizes space usage with full screen
|
||||
let baseFontSize = stretched ?
|
||||
FontUtils.maximumStretchedFontSize(
|
||||
containerWidth: availableSize.width,
|
||||
containerHeight: availableSize.height,
|
||||
containerWidth: fullScreenSize.width,
|
||||
containerHeight: fullScreenSize.height,
|
||||
isPortrait: portrait,
|
||||
showSeconds: showSeconds,
|
||||
showAmPm: !use24Hour && showAmPmBadge
|
||||
) :
|
||||
FontUtils.optimalFontSize(
|
||||
containerWidth: availableSize.width,
|
||||
containerHeight: availableSize.height,
|
||||
containerWidth: fullScreenSize.width,
|
||||
containerHeight: fullScreenSize.height,
|
||||
isPortrait: portrait,
|
||||
showSeconds: showSeconds,
|
||||
showAmPm: !use24Hour && showAmPmBadge
|
||||
@ -146,10 +143,10 @@ struct TimeDisplayView: View {
|
||||
showAMPM: showAMPM
|
||||
)
|
||||
|
||||
// Calculate scale with maximum space utilization using available space
|
||||
// Calculate scale with maximum space utilization using full screen
|
||||
let safeInset = AppConstants.Defaults.safeInset
|
||||
let availableW = max(1, availableSize.width - safeInset * 2)
|
||||
let availableH = max(1, availableSize.height - safeInset * 2)
|
||||
let availableW = max(1, fullScreenSize.width - safeInset * 2)
|
||||
let availableH = max(1, fullScreenSize.height - safeInset * 2)
|
||||
|
||||
// Calculate scaling factors
|
||||
let widthScale = availableW / max(totalWidth, 1)
|
||||
@ -170,11 +167,11 @@ struct TimeDisplayView: View {
|
||||
if showAMPM {
|
||||
TimeSegment(text: ampmText, fontSize: ampmFontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign)
|
||||
} else {
|
||||
HorizontalColon(dotDiameter: dotDiameter, spacing: hSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity)
|
||||
HorizontalColon(dotDiameter: dotDiameter, spacing: hSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight)
|
||||
}
|
||||
TimeSegment(text: minute, fontSize: baseFontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign)
|
||||
if showSeconds {
|
||||
HorizontalColon(dotDiameter: dotDiameter, spacing: hSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity)
|
||||
HorizontalColon(dotDiameter: dotDiameter, spacing: hSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight)
|
||||
TimeSegment(text: secondsText, fontSize: baseFontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign)
|
||||
} else {
|
||||
// Invisible placeholder to maintain consistent spacing
|
||||
@ -188,11 +185,11 @@ struct TimeDisplayView: View {
|
||||
if showAMPM {
|
||||
TimeSegment(text: ampmText, fontSize: ampmFontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign)
|
||||
} else {
|
||||
VerticalColon(dotDiameter: dotDiameter, spacing: vSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity)
|
||||
VerticalColon(dotDiameter: dotDiameter, spacing: vSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight)
|
||||
}
|
||||
TimeSegment(text: minute, fontSize: baseFontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign)
|
||||
if showSeconds {
|
||||
VerticalColon(dotDiameter: dotDiameter, spacing: vSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity)
|
||||
VerticalColon(dotDiameter: dotDiameter, spacing: vSpacing, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight)
|
||||
TimeSegment(text: secondsText, fontSize: baseFontSize, opacity: clockOpacity, digitColor: digitColor, glowIntensity: glowIntensity, fontFamily: fontFamily, fontWeight: fontWeight, fontDesign: fontDesign)
|
||||
} else {
|
||||
// Invisible placeholder to maintain consistent spacing
|
||||
@ -331,12 +328,13 @@ private struct HorizontalColon: View {
|
||||
let opacity: Double
|
||||
let digitColor: Color
|
||||
let glowIntensity: Double
|
||||
let fontWeight: String
|
||||
|
||||
var body: some View {
|
||||
let clamped = ColorUtils.clampOpacity(opacity)
|
||||
HStack(spacing: spacing) {
|
||||
DotCircle(size: dotDiameter, opacity: clamped, digitColor: digitColor, glowIntensity: glowIntensity)
|
||||
DotCircle(size: dotDiameter, opacity: clamped, digitColor: digitColor, glowIntensity: glowIntensity)
|
||||
DotCircle(size: dotDiameter, opacity: clamped, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight)
|
||||
DotCircle(size: dotDiameter, opacity: clamped, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight)
|
||||
}
|
||||
.fixedSize(horizontal: true, vertical: true)
|
||||
.accessibilityHidden(true)
|
||||
@ -349,12 +347,13 @@ private struct VerticalColon: View {
|
||||
let opacity: Double
|
||||
let digitColor: Color
|
||||
let glowIntensity: Double
|
||||
let fontWeight: String
|
||||
|
||||
var body: some View {
|
||||
let clamped = ColorUtils.clampOpacity(opacity)
|
||||
VStack(spacing: spacing) {
|
||||
DotCircle(size: dotDiameter, opacity: clamped, digitColor: digitColor, glowIntensity: glowIntensity)
|
||||
DotCircle(size: dotDiameter, opacity: clamped, digitColor: digitColor, glowIntensity: glowIntensity)
|
||||
DotCircle(size: dotDiameter, opacity: clamped, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight)
|
||||
DotCircle(size: dotDiameter, opacity: clamped, digitColor: digitColor, glowIntensity: glowIntensity, fontWeight: fontWeight)
|
||||
}
|
||||
.fixedSize(horizontal: true, vertical: true)
|
||||
.accessibilityHidden(true)
|
||||
@ -366,17 +365,21 @@ private struct DotCircle: View {
|
||||
let opacity: Double
|
||||
let digitColor: Color
|
||||
let glowIntensity: Double
|
||||
let fontWeight: String
|
||||
|
||||
var body: some View {
|
||||
let weightMultiplier = FontUtils.weightMultiplier(for: fontWeight)
|
||||
let adjustedSize = size * weightMultiplier
|
||||
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(digitColor)
|
||||
.frame(width: size, height: size)
|
||||
.frame(width: adjustedSize, height: adjustedSize)
|
||||
.blur(radius: ColorUtils.glowRadius(intensity: glowIntensity))
|
||||
.opacity(ColorUtils.glowOpacity(intensity: glowIntensity) * opacity)
|
||||
Circle()
|
||||
.fill(digitColor)
|
||||
.frame(width: size, height: size)
|
||||
.frame(width: adjustedSize, height: adjustedSize)
|
||||
.opacity(opacity)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user