// // FontModifier.swift // SodaLive // // Created by klaus on 1/23/26. // import SwiftUI enum SodaTypography { case heading1 case heading2 case heading3 case heading4 case body1 case body2 case body3 case body4 case body5 case body6 case caption1 case caption2 case caption3 var size: CGFloat { switch self { case .heading1: return 24 case .heading2: return 22 case .heading3: return 20 case .heading4: return 18 case .body1, .body2, .body3: return 16 case .body4, .body5, .body6: return 14 case .caption1, .caption2, .caption3: return 12 } } var weight: SwiftUI.Font.Weight { switch self { case .heading1, .heading2, .heading3, .heading4, .body1, .body4, .caption1: return .bold case .body2, .body5, .caption2: return .medium case .body3, .body6, .caption3: return .regular } } } enum SodaFontFamily { case localized case pattaya case phosphate } private func resolvedLanguageCode(currentLocale: Locale) -> String? { if let raw = UserDefaults.standard.string(forKey: "app.language"), let option = LanguageOption(rawValue: raw), option != .system { return option.rawValue } return currentLocale.language.languageCode?.identifier } private func koreanFontName(for weight: SwiftUI.Font.Weight) -> String { switch weight { case .bold: return "Pretendard-Bold" case .medium: return "Pretendard-Medium" case .light: return "Pretendard-Light" default: return "Pretendard-Regular" } } private func japaneseFontName(for weight: SwiftUI.Font.Weight) -> String { switch weight { case .bold: return "NotoSansJP-Bold" case .medium: return "NotoSansJP-Medium" case .light: return "NotoSansJP-Light" default: return "NotoSansJP-Regular" } } private func fontName(for family: SodaFontFamily, weight: SwiftUI.Font.Weight, locale: Locale) -> String? { switch family { case .localized: switch resolvedLanguageCode(currentLocale: locale) { case "ko": return koreanFontName(for: weight) case "ja": return japaneseFontName(for: weight) default: return nil } case .pattaya: return "Pattaya-Regular" case .phosphate: return "PhosphateSolid" } } struct FontModifier: ViewModifier { @Environment(\.locale) private var locale let size: CGFloat let weight: SwiftUI.Font.Weight let family: SodaFontFamily func body(content: Content) -> some View { if let fontName = fontName(for: family, weight: weight, locale: locale) { content.font(.custom(fontName, size: size)) } else { content.font(.system(size: size, weight: weight)) } } } extension View { func appFont( size: CGFloat, weight: SwiftUI.Font.Weight = .regular, family: SodaFontFamily = .localized ) -> some View { self.modifier(FontModifier(size: size, weight: weight, family: family)) } func appFont(_ typography: SodaTypography, family: SodaFontFamily = .localized) -> some View { appFont(size: typography.size, weight: typography.weight, family: family) } } extension Text { func appFont( size: CGFloat, weight: SwiftUI.Font.Weight = .regular, family: SodaFontFamily = .localized ) -> Text { if let fontName = fontName(for: family, weight: weight, locale: .autoupdatingCurrent) { return self.font(.custom(fontName, size: size)) } return self.font(.system(size: size, weight: weight)) } func appFont(_ typography: SodaTypography, family: SodaFontFamily = .localized) -> Text { appFont(size: typography.size, weight: typography.weight, family: family) } }