Skip to content

Commit 80fc4a9

Browse files
authored
Merge pull request #656 from ESTiOSAI/refactor/dynamic-font-kh
feat: dynamic font 적용
2 parents 5f40c19 + 01136d2 commit 80fc4a9

5 files changed

Lines changed: 83 additions & 60 deletions

File tree

AIProject/iCo/Features/Market/MarketStore.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,39 +59,39 @@ final class MarketStore: ObservableObject {
5959
}
6060
}
6161

62-
var sortCategory: Market.SortCategory = .volume {
62+
@Published var sortCategory: Market.SortCategory = .volume {
6363
didSet {
6464
Task {
6565
await sortChannel.send(())
6666
}
6767
}
6868
}
6969

70-
var volumeSortOrder: SortOrder = .descending {
70+
@Published var volumeSortOrder: SortOrder = .descending {
7171
didSet {
7272
Task {
7373
await sortChannel.send(())
7474
}
7575
}
7676
}
7777

78-
var rateSortOrder: SortOrder = .none {
78+
@Published var rateSortOrder: SortOrder = .none {
7979
didSet {
8080
Task {
8181
await sortChannel.send(())
8282
}
8383
}
8484
}
8585

86-
var filter: CoinFilter = .none {
86+
@Published var filter: CoinFilter = .none {
8787
didSet {
8888
Task {
8989
await sortChannel.send(())
9090
}
9191
}
9292
}
9393

94-
var sortedCoinIDs: [CoinID] = []
94+
@Published var sortedCoinIDs: [CoinID] = []
9595

9696
/// 아래 멤버들은 View 갱신을 최소화하기 위해 사용
9797
/// 현재 보여지는 코인 구독 최적화를 위한 채널

AIProject/iCo/Features/Market/SubView/CoinCell.swift

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,15 @@ fileprivate struct CoinMetaView: View {
4343
CoinView(symbol: symbol, size: 30)
4444

4545
VStack(alignment: .leading, spacing: 6) {
46-
Text(name.highlighted(searchTerm, font: .system(size: name.count < 8 ? 14 : 12, weight: .bold)))
46+
Text(name.highlighted(searchTerm, font: name.count < 8 ? .ico14B : .ico12B))
4747
.lineLimit(1)
48-
.font(.system(size: name.count < 8 ? 14 : 12))
49-
.fontWeight(.bold)
48+
.font(name.count < 8 ? .ico14B : .ico12B)
5049

5150
Text(symbol.highlighted(searchTerm))
52-
.font(.system(size: 12))
5351
.foregroundStyle(.secondary)
5452
}
5553
}
56-
.font(.system(size: 12))
57-
.fontWeight(.medium)
54+
.font(.ico11M)
5855
.foregroundStyle(.iCoLabel)
5956
}
6057
}
@@ -92,31 +89,30 @@ fileprivate struct CoinPriceView: View {
9289

9390
Text(ticker.snapshot.formatedPrice)
9491
.frame(minWidth: priceWidth, alignment: .trailing)
95-
.font(.system(size: 15))
92+
.font(.ico15M)
9693
.blinkUnderlineOnChange(ticker.snapshot.price)
9794
}
9895
.frame(alignment: .trailing)
9996

10097
HStack(spacing: 0) {
10198
Text("거래")
102-
.font(.system(size: 11))
99+
.font(.ico11M)
103100
Text(ticker.snapshot.formatedVolume)
104101
.frame(minWidth: volumeWidth, alignment: .trailing)
105102
}
106103
}
107-
.font(.system(size: 12))
108-
.fontWeight(.medium)
104+
.font(.ico12M)
109105
.foregroundStyle(.iCoLabel)
110106
.background {
111107
VStack {
112108
ZStack {
113109
Text(ticker.snapshot.formatedPrice)
114-
.font(.system(size: 15))
110+
.font(.ico15M)
115111
.measureWidth { w in
116112
priceWidth = w + pricePadding
117113
}
118114
Text(ticker.snapshot.formatedVolume)
119-
.font(.system(size: 11))
115+
.font(.ico11M)
120116
.measureWidth { w in
121117
volumeWidth = w + pricePadding
122118
}

AIProject/iCo/Features/Market/SubView/HeaderToggleButton.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ struct HeaderToggleButton: View {
2121
} label: {
2222
HStack {
2323
Text(title)
24-
.font(.system(size: 11))
24+
.font(.ico11)
2525
.foregroundStyle(.iCoLabelSecondary)
2626

2727
HStack(spacing: 4) {
2828
Image(systemName: sortOrder.iconName)
29-
.font(.system(size: 12, weight: .regular))
29+
.font(.ico12)
3030
.foregroundStyle(.iCoLabelSecondary)
3131
.animation(nil, value: sortOrder)
3232
}

AIProject/iCo/Features/Market/SubView/RecentCoinSectionView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct RecentCoinSectionView: View {
1818
ForEach(coins) { coin in
1919
HStack(spacing: 8) {
2020
Text(coin.koreanName)
21-
.font(.system(size: 14))
21+
.font(.ico14)
2222

2323
Button {
2424
deleteAction(coin)

AIProject/iCo/Features/Search/SearchBarView.swift

Lines changed: 67 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,56 +11,83 @@ struct SearchBarView: View {
1111
@Binding var searchText: String
1212
@FocusState private var isFocused: Bool
1313
@State private var showCancel: Bool = false
14+
@State private var containerHeight: CGFloat = 50
15+
@Environment(\.dynamicTypeSize) private var dynamicTypeSize
1416

17+
private func recomputeHeight() {
18+
// Use a Dynamic Type–aware font close to .ico14 (subheadline ~ 15pt)
19+
let lineHeight = UIFont.preferredFont(forTextStyle: .subheadline).lineHeight
20+
// Vertical paddings used below are 14(top)+14(bottom) = 28
21+
let calculated = lineHeight + 28
22+
// Ensure minimum tap target
23+
containerHeight = max(44, calculated)
24+
}
25+
1526
var body: some View {
16-
HStack(spacing: 0) {
17-
HStack {
18-
Image(systemName: "magnifyingglass")
19-
.foregroundStyle(.iCoLabel)
20-
21-
TextField("코인 이름으로 검색하세요", text: $searchText)
22-
.keyboardType(.webSearch)
23-
.textInputAutocapitalization(.never)
24-
.autocorrectionDisabled(true)
25-
.padding(.horizontal, 8)
26-
.submitLabel(.search)
27-
.font(.system(size: 14))
28-
.focused($isFocused)
29-
.onChange(of: isFocused) {
30-
showCancel = isFocused
31-
}
32-
33-
if !searchText.isEmpty {
34-
CircleDeleteButton(fontSize: 9) {
35-
searchText = ""
27+
GeometryReader { proxy in
28+
HStack(spacing: 0) {
29+
HStack {
30+
Image(systemName: "magnifyingglass")
31+
.foregroundStyle(.iCoLabel)
32+
33+
TextField("코인 이름으로 검색하세요", text: $searchText)
34+
.keyboardType(.webSearch)
35+
.textInputAutocapitalization(.never)
36+
.autocorrectionDisabled(true)
37+
.padding(.horizontal, 8)
38+
.submitLabel(.search)
39+
.font(.ico14)
40+
.focused($isFocused)
41+
.onChange(of: isFocused) {
42+
showCancel = isFocused
43+
}
44+
45+
if !searchText.isEmpty {
46+
CircleDeleteButton(fontSize: 9) {
47+
print("Tapped")
48+
searchText = ""
49+
}
3650
}
3751
}
38-
}
39-
.padding(.horizontal, 12)
40-
.padding(.vertical, 14)
41-
.background {
42-
RoundedRectangle(cornerRadius: 15)
43-
.fill(showCancel ? .iCoBackgroundBlue : .iCoBackground)
44-
}
45-
.overlay {
46-
RoundedRectangle(cornerRadius: 15)
47-
.strokeBorder(showCancel ? .accentGradient : .defaultGradient, lineWidth: 0.5)
48-
}
49-
50-
Button {
52+
.padding(.horizontal, 12)
53+
.padding(.vertical, 14)
54+
.background {
55+
RoundedRectangle(cornerRadius: 15)
56+
.fill(showCancel ? .iCoBackgroundBlue : .iCoBackground)
57+
}
58+
.overlay {
59+
RoundedRectangle(cornerRadius: 15)
60+
.strokeBorder(showCancel ? .accentGradient : .defaultGradient, lineWidth: 0.5)
61+
}
62+
.animation(.bouncy, value: showCancel)
63+
64+
Button {
5165
isFocused = false
5266
searchText = ""
53-
} label: {
54-
Text("취소")
55-
.foregroundStyle(.iCoNegative)
56-
.font(.system(size: 13))
67+
} label: {
68+
Text("취소")
69+
.foregroundStyle(.iCoNegative)
70+
.font(.ico13)
71+
}
72+
.opacity(showCancel ? 1 : 0)
73+
.frame(width: showCancel ? 40 : 0, alignment: .trailing)
74+
.animation(.default, value: showCancel)
5775
}
58-
.opacity(showCancel ? 1 : 0)
59-
.frame(width: showCancel ? 40 : 0, alignment: .trailing)
60-
.animation(nil, value: showCancel)
6176
}
77+
.frame(height: containerHeight)
78+
.onAppear { recomputeHeight() }
79+
.onChange(of: dynamicTypeSize, { oldValue, newValue in
80+
recomputeHeight()
81+
})
6282
.onTapGesture {
6383
isFocused = true
6484
}
6585
}
6686
}
87+
88+
#Preview(traits: .sizeThatFitsLayout) {
89+
@Previewable @State var searchText: String = "key"
90+
SearchBarView(searchText: $searchText)
91+
.padding()
92+
.frame(width:.infinity, height: 100)
93+
}

0 commit comments

Comments
 (0)