Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AIProject/iCOWidget/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
153 changes: 153 additions & 0 deletions AIProject/iCo/Core/Util/Font+Util.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
//
// Font+Util.swift
// iCo
//
// Created by 백현진 on 10/14/25.
//

import SwiftUI

extension Font {
/// 시스템 다이내믹 타입 설정에 따라 자동으로 크기가 조정되는 폰트를 반환합니다.
/// 폰트 두께(weight)와 접근성 글자 크기 설정을 모두 지원하며,
/// 과도한 라인 높이(line height) 증가를 자동으로 보정합니다.
/// - Parameters:
/// - targetSize: 기본 폰트 크기(pt)
/// - weight: 폰트 두께 (예: .regular, .bold 등)
/// - textStyle: 다이내믹 타입 기준 스타일 (기본값: .body)
/// - maxLineHeightScale: 라인 높이 확장 제한 비율 (기본값: 1.8)
static func dynamic(
size targetSize: CGFloat,
weight: UIFont.Weight = .regular,
textStyle: UIFont.TextStyle = .body,
maxLineHeightScale: CGFloat = 1.8
) -> Font {
let baseFont = UIFont.systemFont(ofSize: targetSize, weight: weight)

let scaledFont = UIFontMetrics(forTextStyle: textStyle).scaledFont(for: baseFont)

// 폰트가 너무 커졌을 경우, 기본 대비 maxLineHeightScale까지만 확장
let scaleRatio = scaledFont.pointSize / baseFont.pointSize
let clampedScale = min(scaleRatio, maxLineHeightScale)
let adjustedFont = baseFont.withSize(baseFont.pointSize * clampedScale)

return Font(adjustedFont)
}

// 10pt
static var ico10 = Font.dynamic(size: 10, weight: .regular)
static var ico10L = Font.dynamic(size: 10, weight: .light)
static var ico10M = Font.dynamic(size: 10, weight: .medium)
static var ico10Sb = Font.dynamic(size: 10, weight: .semibold)
static var ico10B = Font.dynamic(size: 10, weight: .bold)
static var ico10H = Font.dynamic(size: 10, weight: .heavy)
static var ico10Bl = Font.dynamic(size: 10, weight: .black)

// 11pt
static var ico11 = Font.dynamic(size: 11, weight: .regular)
static var ico11L = Font.dynamic(size: 11, weight: .light)
static var ico11M = Font.dynamic(size: 11, weight: .medium)
static var ico11Sb = Font.dynamic(size: 11, weight: .semibold)
static var ico11B = Font.dynamic(size: 11, weight: .bold)
static var ico11H = Font.dynamic(size: 11, weight: .heavy)
static var ico11Bl = Font.dynamic(size: 11, weight: .black)

// 12pt
static var ico12 = Font.dynamic(size: 12, weight: .regular)
static var ico12L = Font.dynamic(size: 12, weight: .light)
static var ico12M = Font.dynamic(size: 12, weight: .medium)
static var ico12Sb = Font.dynamic(size: 12, weight: .semibold)
static var ico12B = Font.dynamic(size: 12, weight: .bold)
static var ico12H = Font.dynamic(size: 12, weight: .heavy)
static var ico12Bl = Font.dynamic(size: 12, weight: .black)

// 13pt
static var ico13 = Font.dynamic(size: 13, weight: .regular)
static var ico13L = Font.dynamic(size: 13, weight: .light)
static var ico13M = Font.dynamic(size: 13, weight: .medium)
static var ico13Sb = Font.dynamic(size: 13, weight: .semibold)
static var ico13B = Font.dynamic(size: 13, weight: .bold)
static var ico13H = Font.dynamic(size: 13, weight: .heavy)
static var ico13Bl = Font.dynamic(size: 13, weight: .black)

// 14pt
static var ico14 = Font.dynamic(size: 14, weight: .regular)
static var ico14L = Font.dynamic(size: 14, weight: .light)
static var ico14M = Font.dynamic(size: 14, weight: .medium)
static var ico14Sb = Font.dynamic(size: 14, weight: .semibold)
static var ico14B = Font.dynamic(size: 14, weight: .bold)
static var ico14H = Font.dynamic(size: 14, weight: .heavy)
static var ico14Bl = Font.dynamic(size: 14, weight: .black)

// 15pt
static var ico15 = Font.dynamic(size: 15, weight: .regular)
static var ico15L = Font.dynamic(size: 15, weight: .light)
static var ico15M = Font.dynamic(size: 15, weight: .medium)
static var ico15Sb = Font.dynamic(size: 15, weight: .semibold)
static var ico15B = Font.dynamic(size: 15, weight: .bold)
static var ico15H = Font.dynamic(size: 15, weight: .heavy)
static var ico15Bl = Font.dynamic(size: 15, weight: .black)

// 16pt
static var ico16 = Font.dynamic(size: 16, weight: .regular)
static var ico16L = Font.dynamic(size: 16, weight: .light)
static var ico16M = Font.dynamic(size: 16, weight: .medium)
static var ico16Sb = Font.dynamic(size: 16, weight: .semibold)
static var ico16B = Font.dynamic(size: 16, weight: .bold)
static var ico16H = Font.dynamic(size: 16, weight: .heavy)
static var ico16Bl = Font.dynamic(size: 16, weight: .black)

// 17pt
static var ico17 = Font.dynamic(size: 17, weight: .regular)
static var ico17L = Font.dynamic(size: 17, weight: .light)
static var ico17M = Font.dynamic(size: 17, weight: .medium)
static var ico17Sb = Font.dynamic(size: 17, weight: .semibold)
static var ico17B = Font.dynamic(size: 17, weight: .bold)
static var ico17H = Font.dynamic(size: 17, weight: .heavy)
static var ico17Bl = Font.dynamic(size: 17, weight: .black)

// 18pt
static var ico18 = Font.dynamic(size: 18, weight: .regular)
static var ico18L = Font.dynamic(size: 18, weight: .light)
static var ico18M = Font.dynamic(size: 18, weight: .medium)
static var ico18Sb = Font.dynamic(size: 18, weight: .semibold)
static var ico18B = Font.dynamic(size: 18, weight: .bold)
static var ico18H = Font.dynamic(size: 18, weight: .heavy)
static var ico18Bl = Font.dynamic(size: 18, weight: .black)

// 19pt
static var ico19 = Font.dynamic(size: 19, weight: .regular)
static var ico19L = Font.dynamic(size: 19, weight: .light)
static var ico19M = Font.dynamic(size: 19, weight: .medium)
static var ico19Sb = Font.dynamic(size: 19, weight: .semibold)
static var ico19B = Font.dynamic(size: 19, weight: .bold)
static var ico19H = Font.dynamic(size: 19, weight: .heavy)
static var ico19Bl = Font.dynamic(size: 19, weight: .black)

// 20pt
static var ico20 = Font.dynamic(size: 20, weight: .regular)
static var ico20L = Font.dynamic(size: 20, weight: .light)
static var ico20M = Font.dynamic(size: 20, weight: .medium)
static var ico20Sb = Font.dynamic(size: 20, weight: .semibold)
static var ico20B = Font.dynamic(size: 20, weight: .bold)
static var ico20H = Font.dynamic(size: 20, weight: .heavy)
static var ico20Bl = Font.dynamic(size: 20, weight: .black)

// 24pt
static var ico24 = Font.dynamic(size: 24, weight: .regular)
static var ico24L = Font.dynamic(size: 24, weight: .light)
static var ico24M = Font.dynamic(size: 24, weight: .medium)
static var ico24Sb = Font.dynamic(size: 24, weight: .semibold)
static var ico24B = Font.dynamic(size: 24, weight: .bold)
static var ico24H = Font.dynamic(size: 24, weight: .heavy)
static var ico24Bl = Font.dynamic(size: 24, weight: .black)

// 35pt
static var ico35 = Font.dynamic(size: 35, weight: .regular)
static var ico35L = Font.dynamic(size: 35, weight: .light)
static var ico35M = Font.dynamic(size: 35, weight: .medium)
static var ico35Sb = Font.dynamic(size: 35, weight: .semibold)
static var ico35B = Font.dynamic(size: 35, weight: .bold)
static var ico35H = Font.dynamic(size: 35, weight: .heavy)
static var ico35Bl = Font.dynamic(size: 35, weight: .black)
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ struct BookmarkView: View {
.padding(.horizontal, 16)

Text(String.aiGeneratedContentNotice)
.font(.system(size: 11))
.font(.ico11)
.foregroundColor(.iCoNeutral)
.lineSpacing(5)
.frame(maxWidth: .infinity, alignment: .leading)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,25 @@ struct BriefingSectionView: View {
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text("분석 결과")
.font(.system(size: 14))
.fontWeight(.semibold)
.font(.ico14Sb)
.foregroundColor(Color(.iCoAccent))

briefing.briefing
.byCharWrapping
.highlightTextForNumbersOperator()
.font(.system(size: 14))
.fontWeight(.regular)
.font(.ico14)
.lineSpacing(6)

Spacer(minLength: 20)

Text("전략 제안")
.font(.system(size: 14))
.fontWeight(.semibold)
.font(.ico14Sb)
.foregroundColor(Color(.iCoAccent))

briefing.strategy
.byCharWrapping
.highlightTextForNumbersOperator()
.font(.system(size: 14))
.fontWeight(.regular)
.font(.ico14)
.lineSpacing(6)
}
}
Expand Down
3 changes: 1 addition & 2 deletions AIProject/iCo/Features/MyPage/View/CoinListSectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ struct CoinListSectionView: View {
}
}
.padding(.horizontal, 16)
.fontWeight(.regular)
.font(.system(size: 12))
.font(.ico12)
.foregroundStyle(.iCoLabel)

ForEach(sortedCoins, id: \.coinID) { coin in
Expand Down
5 changes: 3 additions & 2 deletions AIProject/iCo/Features/MyPage/View/CoinRowView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ struct CoinRowView: View {

HStack(spacing: 8) {
Text(coin.coinKoreanName)
.font(.system(size: 15, weight: .semibold))
.font(.ico15Sb)
.lineLimit(1)
.foregroundColor(.primary)

Text(coin.coinSymbol)
.font(.caption)
.font(.ico12)
.foregroundColor(.secondary)
}

Expand Down
Loading