From 800231ed8a31d2f016d2a5835d398ed2a8bf95b6 Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 5 May 2026 15:56:18 +0900 Subject: [PATCH 1/3] =?UTF-8?q?ui:=20=EC=9A=94=EC=9D=BC=20=EB=9D=BC?= =?UTF-8?q?=EB=B2=A8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DevLog/UI/Profile/HeatmapView.swift | 82 ++++------------------------- 1 file changed, 11 insertions(+), 71 deletions(-) diff --git a/DevLog/UI/Profile/HeatmapView.swift b/DevLog/UI/Profile/HeatmapView.swift index 35ac46b3..315db7c3 100644 --- a/DevLog/UI/Profile/HeatmapView.swift +++ b/DevLog/UI/Profile/HeatmapView.swift @@ -21,77 +21,21 @@ struct HeatmapView: View { weekCounts: quarter.months.map(\.weeks.count) ) - HStack(alignment: .top, spacing: 0) { - weekdayLabel(layout: layout) - HStack(alignment: .top, spacing: layout.monthSpacing) { - ForEach(quarter.months) { month in - MonthCompactHeatmapView( - month: month, - maxCount: maxCount, - layout: layout, - selectedActivityKinds: selectedActivityKinds, - selectedDay: selectedDay, - onSelectDay: onSelectDay - ) - } + HStack(alignment: .top, spacing: layout.monthSpacing) { + ForEach(quarter.months) { month in + MonthCompactHeatmapView( + month: month, + maxCount: maxCount, + layout: layout, + selectedActivityKinds: selectedActivityKinds, + selectedDay: selectedDay, + onSelectDay: onSelectDay + ) } } .padding(.vertical, 2) } - @ViewBuilder - private func weekdayLabel(layout: HeatmapLayout) -> some View { - let labels: [Int: String] = [ - 2: String(localized: "profile_weekday_mon"), - 4: String(localized: "profile_weekday_wed"), - 6: String(localized: "profile_weekday_fri") - ] - let orderedWeekdays = Array(1...7) - let labelFontSize = smallestWeekdayLabelFontSize( - labels: Array(labels.values), - layout: layout - ) - - VStack(alignment: .leading, spacing: layout.cellSpacing) { - ForEach(orderedWeekdays, id: \.self) { weekday in - if let label = labels[weekday] { - Text(label) - .font(.system(size: labelFontSize)) - .allowsTightening(true) - .foregroundStyle(.secondary) - .frame( - width: layout.cellSize, - height: layout.cellSize, - alignment: .leading - ) - } else { - Color.clear - .frame( - width: layout.cellSize, - height: layout.cellSize - ) - } - } - } - .padding(.top, layout.weekdayTopPadding) - } - - private func smallestWeekdayLabelFontSize(labels: [String], layout: HeatmapLayout) -> CGFloat { - let captionFont = UIFont.preferredFont(forTextStyle: .caption2) - let availableWidth = max(layout.cellSize, 1) - - let fittedSizes = labels.map { label in - let textWidth = max( - (label as NSString).size(withAttributes: [.font: captionFont]).width, - 1 - ) - let widthRatio = availableWidth / textWidth - return captionFont.pointSize * min(widthRatio, 1) - } - - return max((fittedSizes.min() ?? captionFont.pointSize).rounded(.down), 1) - } - private var availableWidth: CGFloat { // ProfileView의 바깥 가로 패딩(16)과 히트맵 카드 내부 패딩(12)을 합한 값 let horizontalPadding: CGFloat = 16 + 12 @@ -142,11 +86,7 @@ private struct HeatmapLayout { } let fixedWidth = monthSpacing * CGFloat(max(sanitizedWeekCounts.count - 1, 0)) + cellSpacing * CGFloat(totalColumnSpacings) - cellSize = max(0, availableWidth - fixedWidth) / CGFloat(totalColumns + 1) - } - - var weekdayTopPadding: CGFloat { - cellSize + monthTitleSpacing + cellSize = max(0, availableWidth - fixedWidth) / CGFloat(totalColumns) } var cellCornerRadius: CGFloat { From 64288033938d028797bf8318619d3f10c66cf958 Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 5 May 2026 15:56:29 +0900 Subject: [PATCH 2/3] =?UTF-8?q?chore:=20l10n=20=ED=82=A4=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DevLog/Resource/Localizable.xcstrings | 51 --------------------------- 1 file changed, 51 deletions(-) diff --git a/DevLog/Resource/Localizable.xcstrings b/DevLog/Resource/Localizable.xcstrings index 97a40473..5de1745e 100644 --- a/DevLog/Resource/Localizable.xcstrings +++ b/DevLog/Resource/Localizable.xcstrings @@ -979,57 +979,6 @@ } } }, - "profile_weekday_fri" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fri" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "금" - } - } - } - }, - "profile_weekday_mon" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mon" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "월" - } - } - } - }, - "profile_weekday_wed" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Wed" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "수" - } - } - } - }, "profile_year" : { "extractionState" : "manual", "localizations" : { From 71e8668e1e113ce12b21bc3368c3661560610a8a Mon Sep 17 00:00:00 2001 From: opficdev Date: Tue, 5 May 2026 16:15:10 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=ED=9E=88=ED=8A=B8=EB=A7=B5=20?= =?UTF-8?q?=EC=A3=BC=EC=B0=A8=20=EC=88=98=20=EA=B3=84=EC=82=B0=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=EB=A7=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DevLog/UI/Profile/HeatmapView.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/DevLog/UI/Profile/HeatmapView.swift b/DevLog/UI/Profile/HeatmapView.swift index 315db7c3..617d11d5 100644 --- a/DevLog/UI/Profile/HeatmapView.swift +++ b/DevLog/UI/Profile/HeatmapView.swift @@ -79,12 +79,11 @@ private struct HeatmapLayout { let monthTitleSpacing: CGFloat = 6 init(availableWidth: CGFloat, weekCounts: [Int]) { - let sanitizedWeekCounts = weekCounts.filter { 0 < $0 } - let totalColumns = max(sanitizedWeekCounts.reduce(0, +), 1) - let totalColumnSpacings = sanitizedWeekCounts.reduce(0) { partialResult, count in + let totalColumns = max(weekCounts.reduce(0, +), 1) + let totalColumnSpacings = weekCounts.reduce(0) { partialResult, count in partialResult + max(count - 1, 0) } - let fixedWidth = monthSpacing * CGFloat(max(sanitizedWeekCounts.count - 1, 0)) + let fixedWidth = monthSpacing * CGFloat(max(weekCounts.count - 1, 0)) + cellSpacing * CGFloat(totalColumnSpacings) cellSize = max(0, availableWidth - fixedWidth) / CGFloat(totalColumns) }