Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
6c5e0b4d74
commit
3464cbeb17
@ -5,6 +5,7 @@
|
|||||||
// Created by Matt Bruce on 9/11/25.
|
// Created by Matt Bruce on 9/11/25.
|
||||||
//
|
//
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
enum FontFamily: String, CaseIterable {
|
enum FontFamily: String, CaseIterable {
|
||||||
case system = "System"
|
case system = "System"
|
||||||
@ -33,4 +34,60 @@ enum FontFamily: String, CaseIterable {
|
|||||||
default: self = .system
|
default: self = .system
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fontWeights: [Font.Weight] {
|
||||||
|
guard let weightDict = Self.fontMapWeights[self.rawValue] else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return Array(weightDict.keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fontName(weight: Font.Weight) -> String? {
|
||||||
|
guard let weightDict = Self.fontMapWeights[self.rawValue],
|
||||||
|
let fontName = weightDict[weight] else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fontName
|
||||||
|
}
|
||||||
|
|
||||||
|
static internal var fontMapWeights: [String: [Font.Weight: String]] = [
|
||||||
|
FontFamily.helvetica.rawValue: [
|
||||||
|
.regular: "Helvetica",
|
||||||
|
.light: "Helvetica-Light",
|
||||||
|
.bold: "Helvetica-Bold"
|
||||||
|
],
|
||||||
|
FontFamily.arial.rawValue: [
|
||||||
|
.regular: "ArialMT",
|
||||||
|
.bold: "Arial-BoldMT"
|
||||||
|
],
|
||||||
|
FontFamily.timesNewRoman.rawValue: [
|
||||||
|
.regular: "TimesNewRomanPSMT",
|
||||||
|
.bold: "TimesNewRomanPS-BoldMT"
|
||||||
|
],
|
||||||
|
FontFamily.georgia.rawValue: [
|
||||||
|
.regular: "Georgia",
|
||||||
|
.bold: "Georgia-Bold"
|
||||||
|
],
|
||||||
|
FontFamily.verdana.rawValue: [
|
||||||
|
.regular: "Verdana",
|
||||||
|
.bold: "Verdana-Bold"
|
||||||
|
],
|
||||||
|
FontFamily.courier.rawValue: [
|
||||||
|
.regular: "Courier",
|
||||||
|
.bold: "Courier-Bold"
|
||||||
|
],
|
||||||
|
FontFamily.futura.rawValue: [
|
||||||
|
.regular: "Futura-Medium",
|
||||||
|
.bold: "Futura-Bold"
|
||||||
|
],
|
||||||
|
FontFamily.avenir.rawValue: [
|
||||||
|
.regular: "Avenir-Roman",
|
||||||
|
.bold: "Avenir-Bold"
|
||||||
|
],
|
||||||
|
FontFamily.roboto.rawValue: [
|
||||||
|
.regular: "Roboto-Regular",
|
||||||
|
.bold: "Roboto-Bold"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,7 @@ struct FontUtils {
|
|||||||
return .system(size: size, weight: weight, design: design)
|
return .system(size: size, weight: weight, design: design)
|
||||||
} else {
|
} else {
|
||||||
return .custom(weightedFontName(
|
return .custom(weightedFontName(
|
||||||
name: name.rawValue,
|
name: name,
|
||||||
weight: weight,
|
weight: weight,
|
||||||
design: design
|
design: design
|
||||||
), size: size)
|
), size: size)
|
||||||
@ -75,7 +75,7 @@ struct FontUtils {
|
|||||||
|
|
||||||
if let font = UIFont(
|
if let font = UIFont(
|
||||||
name: weightedFontName(
|
name: weightedFontName(
|
||||||
name: name.rawValue,
|
name: name,
|
||||||
weight: weight,
|
weight: weight,
|
||||||
design: design
|
design: design
|
||||||
),
|
),
|
||||||
@ -111,29 +111,193 @@ struct FontUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static func weightedFontName(
|
private static func weightedFontName(
|
||||||
name: String,
|
name: FontFamily,
|
||||||
weight: Font.Weight,
|
weight: Font.Weight,
|
||||||
design: Font.Design
|
design: Font.Design
|
||||||
) -> String {
|
) -> String {
|
||||||
let weightSuffix = weight.uiFontWeightSuffix
|
|
||||||
|
|
||||||
|
// Use exact name from map if available
|
||||||
|
if let exactName = name.fontName(weight: weight) {
|
||||||
|
return exactName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback design handling
|
||||||
|
var baseName = name.rawValue
|
||||||
switch design {
|
switch design {
|
||||||
case .rounded:
|
case .rounded:
|
||||||
if name.lowercased() == "system" { return "System" }
|
baseName = "ArialRoundedMTBold" // System rounded fallback
|
||||||
return name
|
|
||||||
+ (weightSuffix.isEmpty ? "-Rounded" : weightSuffix + "Rounded")
|
|
||||||
case .monospaced:
|
case .monospaced:
|
||||||
if name.lowercased() == "system" { return "Courier" }
|
baseName = "Courier"
|
||||||
return name == "Courier"
|
|
||||||
? name + weightSuffix
|
|
||||||
: name
|
|
||||||
+ (weightSuffix.isEmpty ? "-Mono" : weightSuffix + "Mono")
|
|
||||||
case .serif:
|
case .serif:
|
||||||
if name.lowercased() == "system" { return "TimesNewRomanPS" }
|
baseName = "TimesNewRomanPSMT"
|
||||||
return name + weightSuffix
|
|
||||||
default:
|
default:
|
||||||
return name + weightSuffix
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let weightSuffix = weight.uiFontWeightSuffix
|
||||||
|
return baseName + (weightSuffix.isEmpty ? "" : "-" + weightSuffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct TestContentView: View {
|
||||||
|
@State private var digit: String = "138"
|
||||||
|
@State private var previewFontSize: CGFloat = 1000
|
||||||
|
@State private var fontWeight: Font.Weight = .bold
|
||||||
|
@State private var fontDesign: Font.Design = .rounded
|
||||||
|
|
||||||
|
private var date: Date {
|
||||||
|
let hours = ["13"].randomElement() ?? "08"
|
||||||
|
let minutes = ["38"].randomElement() ?? "33"
|
||||||
|
let timeString = "\(hours):\(minutes)"
|
||||||
|
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateFormat = "yyyy-MM-dd"
|
||||||
|
let todayString = formatter.string(from: Date())
|
||||||
|
let fullDateString = "\(todayString) \(timeString)"
|
||||||
|
|
||||||
|
formatter.dateFormat = "yyyy-MM-dd HH:mm"
|
||||||
|
return formatter.date(from: fullDateString) ?? Date()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
let newDate = date
|
||||||
|
return ScrollView {
|
||||||
|
VStack(spacing: 20) {
|
||||||
|
ForEach(FontFamily.allCases, id: \.rawValue) { (font: FontFamily) in
|
||||||
|
VStack {
|
||||||
|
Text(font.rawValue)
|
||||||
|
.font(Font.system(size: 16, weight: Font.Weight.bold))
|
||||||
|
.padding(.bottom, 5)
|
||||||
|
|
||||||
|
TimeDisplayView(date: newDate,
|
||||||
|
use24Hour: true,
|
||||||
|
showSeconds: false,
|
||||||
|
digitColor: .primary,
|
||||||
|
glowIntensity: 0.5,
|
||||||
|
manualScale: 1.0,
|
||||||
|
stretched: false,
|
||||||
|
clockOpacity: 1.0,
|
||||||
|
fontFamily: font,
|
||||||
|
fontWeight: fontWeight,
|
||||||
|
fontDesign: fontDesign,
|
||||||
|
forceHorizontalMode: true)
|
||||||
|
|
||||||
|
TimeSegment(
|
||||||
|
text: digit,
|
||||||
|
fontSize: .constant(129), // CGFloat
|
||||||
|
opacity: 1.0, // Double
|
||||||
|
digitColor: Color.primary, // Color
|
||||||
|
glowIntensity: 0.5, // Double
|
||||||
|
fontFamily: font, // FontFamily
|
||||||
|
fontWeight: fontWeight,
|
||||||
|
fontDesign: fontDesign,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.frame(width: 400, height: 200)
|
||||||
|
.border(Color.black)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FontCombinationsPreview: View {
|
||||||
|
// All designs
|
||||||
|
private let designs: [Font.Design] = Font.Design.allCases
|
||||||
|
|
||||||
|
private let columns: [GridItem] = [
|
||||||
|
GridItem(.flexible(), spacing: 20),
|
||||||
|
GridItem(.flexible(), spacing: 20),
|
||||||
|
GridItem(.flexible(), spacing: 20)
|
||||||
|
]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
// Precompute local copies to avoid type-checker stress
|
||||||
|
let fonts: [FontFamily] = FontFamily.allCases.sorted {
|
||||||
|
$0.rawValue.localizedCaseInsensitiveCompare($1.rawValue)
|
||||||
|
== .orderedAscending
|
||||||
|
}
|
||||||
|
let designsLocal: [Font.Design] = designs
|
||||||
|
|
||||||
|
return ScrollView {
|
||||||
|
LazyVGrid(columns: columns, spacing: 20) {
|
||||||
|
ForEach(fonts, id: \.self) { font in
|
||||||
|
ForEach(font.fontWeights, id: \.self) { weight in
|
||||||
|
ForEach(designsLocal, id: \.self) { design in
|
||||||
|
FontSampleCell(font: font, weight: weight, design: design)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct FontSampleCell: View {
|
||||||
|
let font: FontFamily
|
||||||
|
let weight: Font.Weight
|
||||||
|
let design: Font.Design
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .center, spacing: 5) {
|
||||||
|
Text("\(font.rawValue), \(weight.rawValue), \(design.rawValue)")
|
||||||
|
.font(.system(size: 12, weight: .medium))
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.bottom, 5)
|
||||||
|
TimeSegment(
|
||||||
|
text: "38",
|
||||||
|
fontSize: .constant(129), // CGFloat
|
||||||
|
opacity: 1.0, // Double
|
||||||
|
digitColor: Color.primary, // Color
|
||||||
|
glowIntensity: 0.5, // Double
|
||||||
|
fontFamily: font, // FontFamily
|
||||||
|
fontWeight: weight,
|
||||||
|
fontDesign: design)
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
.border(Color.black)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
FontCombinationsPreview()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Descriptions for Font.Weight and Font.Design
|
||||||
|
private extension Font.Weight {
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .ultraLight: return "ultraLight"
|
||||||
|
case .thin: return "thin"
|
||||||
|
case .light: return "light"
|
||||||
|
case .regular: return "regular"
|
||||||
|
case .medium: return "medium"
|
||||||
|
case .semibold: return "semibold"
|
||||||
|
case .bold: return "bold"
|
||||||
|
case .heavy: return "heavy"
|
||||||
|
case .black: return "black"
|
||||||
|
default:
|
||||||
|
// Fallback for any future/unknown cases
|
||||||
|
return "custom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension Font.Design {
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .default: return "default"
|
||||||
|
case .serif: return "serif"
|
||||||
|
case .rounded: return "rounded"
|
||||||
|
case .monospaced: return "monospaced"
|
||||||
|
@unknown default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,42 @@ class ClockViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateStyle(_ newStyle: ClockStyle) {
|
func updateStyle(_ newStyle: ClockStyle) {
|
||||||
style = newStyle
|
DebugLogger.log("ClockViewModel: updateStyle called", category: .settings)
|
||||||
|
DebugLogger.log("ClockViewModel: old fontFamily = \(style.fontFamily)", category: .settings)
|
||||||
|
DebugLogger.log("ClockViewModel: new fontFamily = \(newStyle.fontFamily)", category: .settings)
|
||||||
|
|
||||||
|
// Update properties of the existing style object instead of replacing it
|
||||||
|
// This preserves the @Observable chain
|
||||||
|
style.use24Hour = newStyle.use24Hour
|
||||||
|
style.showSeconds = newStyle.showSeconds
|
||||||
|
style.forceHorizontalMode = newStyle.forceHorizontalMode
|
||||||
|
style.digitColorHex = newStyle.digitColorHex
|
||||||
|
style.glowIntensity = newStyle.glowIntensity
|
||||||
|
style.digitScale = newStyle.digitScale
|
||||||
|
style.stretched = newStyle.stretched
|
||||||
|
style.clockOpacity = newStyle.clockOpacity
|
||||||
|
style.fontFamily = newStyle.fontFamily
|
||||||
|
style.fontWeight = newStyle.fontWeight
|
||||||
|
style.fontDesign = newStyle.fontDesign
|
||||||
|
style.showBattery = newStyle.showBattery
|
||||||
|
style.showDate = newStyle.showDate
|
||||||
|
style.overlayOpacity = newStyle.overlayOpacity
|
||||||
|
style.backgroundHex = newStyle.backgroundHex
|
||||||
|
style.keepAwake = newStyle.keepAwake
|
||||||
|
style.randomizeColor = newStyle.randomizeColor
|
||||||
|
style.selectedColorTheme = newStyle.selectedColorTheme
|
||||||
|
style.nightModeEnabled = newStyle.nightModeEnabled
|
||||||
|
style.autoNightMode = newStyle.autoNightMode
|
||||||
|
style.scheduledNightMode = newStyle.scheduledNightMode
|
||||||
|
style.nightModeStartTime = newStyle.nightModeStartTime
|
||||||
|
style.nightModeEndTime = newStyle.nightModeEndTime
|
||||||
|
style.ambientLightThreshold = newStyle.ambientLightThreshold
|
||||||
|
style.autoBrightness = newStyle.autoBrightness
|
||||||
|
style.dateFormat = newStyle.dateFormat
|
||||||
|
style.respectFocusModes = newStyle.respectFocusModes
|
||||||
|
|
||||||
|
DebugLogger.log("ClockViewModel: after update fontFamily = \(style.fontFamily)", category: .settings)
|
||||||
|
|
||||||
saveStyle()
|
saveStyle()
|
||||||
updateTimersIfNeeded()
|
updateTimersIfNeeded()
|
||||||
updateWakeLockState()
|
updateWakeLockState()
|
||||||
|
|||||||
@ -235,6 +235,15 @@ private struct FontSection: View {
|
|||||||
|
|
||||||
// Use the enum allCases for font options
|
// Use the enum allCases for font options
|
||||||
|
|
||||||
|
// Computed property for available weights based on selected font
|
||||||
|
private var availableWeights: [Font.Weight] {
|
||||||
|
if style.fontFamily == .system {
|
||||||
|
return Font.Weight.allCases
|
||||||
|
} else {
|
||||||
|
return style.fontFamily.fontWeights
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section(header: Text("Font")) {
|
Section(header: Text("Font")) {
|
||||||
// Font Family
|
// Font Family
|
||||||
@ -244,22 +253,36 @@ private struct FontSection: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.pickerStyle(.menu)
|
.pickerStyle(.menu)
|
||||||
|
.onChange(of: style.fontFamily) { _, newFamily in
|
||||||
|
// Auto-set design to default for non-system fonts
|
||||||
|
if newFamily != .system {
|
||||||
|
style.fontDesign = .default
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-set weight to first available weight if current weight is not available
|
||||||
|
let availableWeights = newFamily == .system ? Font.Weight.allCases : newFamily.fontWeights
|
||||||
|
if !availableWeights.contains(style.fontWeight) {
|
||||||
|
style.fontWeight = availableWeights.first ?? .regular
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Font Weight
|
// Font Weight - show available weights for selected font
|
||||||
Picker("Weight", selection: $style.fontWeight) {
|
Picker("Weight", selection: $style.fontWeight) {
|
||||||
ForEach(Font.Weight.allCases, id: \.self) { weight in
|
ForEach(availableWeights, id: \.self) { weight in
|
||||||
Text(weight.rawValue).tag(weight)
|
Text(weight.rawValue).tag(weight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.pickerStyle(.menu)
|
.pickerStyle(.menu)
|
||||||
|
|
||||||
// Font Design
|
// Font Design - only show for system font
|
||||||
Picker("Design", selection: $style.fontDesign) {
|
if style.fontFamily == .system {
|
||||||
ForEach(Font.Design.allCases, id: \.self) { design in
|
Picker("Design", selection: $style.fontDesign) {
|
||||||
Text(design.rawValue).tag(design)
|
ForEach(Font.Design.allCases, id: \.self) { design in
|
||||||
|
Text(design.rawValue).tag(design)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.pickerStyle(.menu)
|
||||||
}
|
}
|
||||||
.pickerStyle(.menu)
|
|
||||||
|
|
||||||
// Font Preview
|
// Font Preview
|
||||||
HStack {
|
HStack {
|
||||||
|
|||||||
@ -17,7 +17,9 @@ struct ClockDisplayContainer: View {
|
|||||||
|
|
||||||
// MARK: - Body
|
// MARK: - Body
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { geometry in
|
DebugLogger.log("ClockDisplayContainer: body called with fontFamily=\(style.fontFamily), fontWeight=\(style.fontWeight), fontDesign=\(style.fontDesign)", category: .general)
|
||||||
|
|
||||||
|
return GeometryReader { geometry in
|
||||||
let isPortrait = geometry.size.height >= geometry.size.width
|
let isPortrait = geometry.size.height >= geometry.size.width
|
||||||
let hasOverlay = style.showBattery || style.showDate
|
let hasOverlay = style.showBattery || style.showDate
|
||||||
let topSpacing = hasOverlay ? (isPortrait ? UIConstants.Spacing.huge : UIConstants.Spacing.large) : 0
|
let topSpacing = hasOverlay ? (isPortrait ? UIConstants.Spacing.huge : UIConstants.Spacing.large) : 0
|
||||||
|
|||||||
@ -11,13 +11,13 @@ import SwiftUI
|
|||||||
struct DigitView: View {
|
struct DigitView: View {
|
||||||
@Environment(\.sizeCategory) private var sizeCategory
|
@Environment(\.sizeCategory) private var sizeCategory
|
||||||
|
|
||||||
@State var digit: String
|
let digit: String
|
||||||
@State var fontName: FontFamily
|
let fontName: FontFamily
|
||||||
@State var weight: Font.Weight
|
let weight: Font.Weight
|
||||||
@State var design: Font.Design
|
let design: Font.Design
|
||||||
@State var opacity: Double
|
let opacity: Double
|
||||||
@State var digitColor: Color
|
let digitColor: Color
|
||||||
@State var glowIntensity: Double
|
let glowIntensity: Double
|
||||||
@Binding var fontSize: CGFloat
|
@Binding var fontSize: CGFloat
|
||||||
|
|
||||||
@State private var lastCalculatedSize: CGSize = .zero
|
@State private var lastCalculatedSize: CGSize = .zero
|
||||||
@ -31,6 +31,7 @@ struct DigitView: View {
|
|||||||
opacity: Double = 1,
|
opacity: Double = 1,
|
||||||
glowIntensity: Double = 0,
|
glowIntensity: Double = 0,
|
||||||
fontSize: Binding<CGFloat>) {
|
fontSize: Binding<CGFloat>) {
|
||||||
|
DebugLogger.log("DigitView: init called with fontName=\(fontName), weight=\(weight), design=\(design)", category: .general)
|
||||||
self.digit = (digit.count == 1 && "0123456789".contains(digit)) ? digit : "0"
|
self.digit = (digit.count == 1 && "0123456789".contains(digit)) ? digit : "0"
|
||||||
self.fontName = fontName
|
self.fontName = fontName
|
||||||
self.weight = weight
|
self.weight = weight
|
||||||
@ -96,6 +97,18 @@ struct DigitView: View {
|
|||||||
.onChange(of: sizeCategory) { _, _ in
|
.onChange(of: sizeCategory) { _, _ in
|
||||||
calculateOptimalFontSize(for: geometry.size)
|
calculateOptimalFontSize(for: geometry.size)
|
||||||
}
|
}
|
||||||
|
.onChange(of: fontName) { _, _ in
|
||||||
|
DebugLogger.log("DigitView: fontName changed to \(fontName)", category: .general)
|
||||||
|
calculateOptimalFontSize(for: geometry.size)
|
||||||
|
}
|
||||||
|
.onChange(of: weight) { _, _ in
|
||||||
|
DebugLogger.log("DigitView: weight changed to \(weight)", category: .general)
|
||||||
|
calculateOptimalFontSize(for: geometry.size)
|
||||||
|
}
|
||||||
|
.onChange(of: design) { _, _ in
|
||||||
|
DebugLogger.log("DigitView: design changed to \(design)", category: .general)
|
||||||
|
calculateOptimalFontSize(for: geometry.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,9 @@ struct TimeDisplayView: View {
|
|||||||
|
|
||||||
// MARK: - Body
|
// MARK: - Body
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { proxy in
|
DebugLogger.log("TimeDisplayView: body called with fontFamily=\(fontFamily), fontWeight=\(fontWeight), fontDesign=\(fontDesign)", category: .general)
|
||||||
|
|
||||||
|
return GeometryReader { proxy in
|
||||||
let containerSize = proxy.size
|
let containerSize = proxy.size
|
||||||
let portraitMode = containerSize.height >= containerSize.width
|
let portraitMode = containerSize.height >= containerSize.width
|
||||||
let portrait = !forceHorizontalMode && containerSize.height >= containerSize.width
|
let portrait = !forceHorizontalMode && containerSize.height >= containerSize.width
|
||||||
|
|||||||
@ -20,7 +20,8 @@ struct TimeSegment: View {
|
|||||||
let fontDesign: Font.Design
|
let fontDesign: Font.Design
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(alignment: .center, spacing: 0) {
|
DebugLogger.log("TimeSegment: body called with fontFamily=\(fontFamily), fontWeight=\(fontWeight), fontDesign=\(fontDesign)", category: .general)
|
||||||
|
return HStack(alignment: .center, spacing: 0) {
|
||||||
ForEach(Array(text.enumerated()), id: \.offset) { index, character in
|
ForEach(Array(text.enumerated()), id: \.offset) { index, character in
|
||||||
DigitView(
|
DigitView(
|
||||||
digit: String(character),
|
digit: String(character),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user