From ea52972e1011e73d99ef4d19915a5edc4f714249 Mon Sep 17 00:00:00 2001 From: lyh5427 Date: Sat, 15 Aug 2026 16:11:10 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix(#176):=20HilitLoadingIndicator=20?= =?UTF-8?q?=EA=B7=B8=EB=9E=98=ED=94=BD=20=EB=B9=84=EC=9C=A8=EC=9D=84=20?= =?UTF-8?q?=EC=A0=95=EC=82=AC=EA=B0=81=ED=98=95=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 원본 벡터 리소스(loading_indicator.xml)가 72x73dp(비정사각형)로 export돼 있어, 실제로는 원인 스피너가 세로로 살짝 긴 타원으로 렌더링되고 있었다. Figma 439:10407 프레임 자체는 74x74 정사각형이라 export 과정에서 생긴 오차로 보인다. 회전 애니메이션과 겹치며 미묘하게 중심이 어긋나 보이던 원인이라, 너비/높이 비율을 더 작은 쪽(72/74)으로 통일해 Image의 기본 ContentScale.Fit이 항상 정사각형(원)으로 렌더링하게 했다. - hilitLoadingIndicatorGeometry(): graphicWidth/graphicHeight를 같은 LOADING_INDICATOR_SIZE_RATIO(72/74)로 계산 - HilitLoadingIndicatorTest: 74dp 크기에서 72x72(기존 72x73), 148dp 크기에서 144x144(기존 144x146) 되도록 기대값 갱신 Co-Authored-By: Claude Sonnet 5 --- .../component/loading/HilitLoadingIndicator.kt | 13 +++++++++---- .../component/loading/HilitLoadingIndicatorTest.kt | 8 ++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/designsystem/src/commonMain/kotlin/com/dminus14/designsystem/component/loading/HilitLoadingIndicator.kt b/designsystem/src/commonMain/kotlin/com/dminus14/designsystem/component/loading/HilitLoadingIndicator.kt index c3495720..130b686e 100644 --- a/designsystem/src/commonMain/kotlin/com/dminus14/designsystem/component/loading/HilitLoadingIndicator.kt +++ b/designsystem/src/commonMain/kotlin/com/dminus14/designsystem/component/loading/HilitLoadingIndicator.kt @@ -92,10 +92,12 @@ internal data class HilitLoadingIndicatorGeometry( internal fun hilitLoadingIndicatorGeometry(size: Dp): HilitLoadingIndicatorGeometry { require(size > 0.dp) { "HilitLoadingIndicator size must be positive." } + // 원형 스피너라 너비·높이는 항상 같아야 한다 (LOADING_INDICATOR_SIZE_RATIO 주석 참고). + val graphicSize = size * LOADING_INDICATOR_SIZE_RATIO return HilitLoadingIndicatorGeometry( containerSize = size, - graphicWidth = size * LOADING_INDICATOR_WIDTH_RATIO, - graphicHeight = size * LOADING_INDICATOR_HEIGHT_RATIO, + graphicWidth = graphicSize, + graphicHeight = graphicSize, ) } @@ -111,8 +113,11 @@ internal val LOADING_INDICATOR_EASING = sin(radians) } -private const val LOADING_INDICATOR_WIDTH_RATIO = 72f / 74f -private const val LOADING_INDICATOR_HEIGHT_RATIO = 73f / 74f +// 원본 벡터 리소스(loading_indicator.xml)의 선언 크기는 72x73dp 로 Figma export 과정에서 +// 생긴 1dp 오차가 있다(Figma 439:10407 프레임 자체는 74x74 정사각형). 회전하는 원형 스피너가 +// 세로로 살짝 긴 타원으로 그려져 회전할 때마다 중심이 미묘하게 어긋나 보이던 원인(#176)이라, +// 더 작은 쪽 비율(72/74)을 너비·높이 모두에 써서 강제로 정사각형(원)이 되게 한다. +private const val LOADING_INDICATOR_SIZE_RATIO = 72f / 74f private const val LOADING_INDICATOR_SPEED_VARIATION = 0.65f private const val LOADING_INDICATOR_FULL_CYCLE_RADIANS = (2.0 * PI).toFloat() private val DEFAULT_LOADING_INDICATOR_SIZE = 74.dp diff --git a/designsystem/src/commonTest/kotlin/com/dminus14/designsystem/component/loading/HilitLoadingIndicatorTest.kt b/designsystem/src/commonTest/kotlin/com/dminus14/designsystem/component/loading/HilitLoadingIndicatorTest.kt index dd1c5c1f..5285154d 100644 --- a/designsystem/src/commonTest/kotlin/com/dminus14/designsystem/component/loading/HilitLoadingIndicatorTest.kt +++ b/designsystem/src/commonTest/kotlin/com/dminus14/designsystem/component/loading/HilitLoadingIndicatorTest.kt @@ -9,21 +9,21 @@ import kotlin.test.assertTrue class HilitLoadingIndicatorTest { @Test - fun `기본 크기는 74dp 컨테이너 안에 72dp 곱하기 73dp 그래픽을 배치한다`() { + fun `기본 크기는 74dp 컨테이너 안에 72dp 정사각형 그래픽을 배치한다`() { val geometry = hilitLoadingIndicatorGeometry(size = 74.dp) assertEquals(74.dp, geometry.containerSize) assertEquals(72.dp, geometry.graphicWidth) - assertEquals(73.dp, geometry.graphicHeight) + assertEquals(72.dp, geometry.graphicHeight) } @Test - fun `사용자 크기에서도 원본 그래픽 비율을 유지한다`() { + fun `사용자 크기에서도 그래픽은 항상 정사각형을 유지한다`() { val geometry = hilitLoadingIndicatorGeometry(size = 148.dp) assertEquals(148.dp, geometry.containerSize) assertEquals(144.dp, geometry.graphicWidth) - assertEquals(146.dp, geometry.graphicHeight) + assertEquals(144.dp, geometry.graphicHeight) } @Test From 689e39c3810d0a15dc84b33e048e2a49a477a681 Mon Sep 17 00:00:00 2001 From: lyh5427 Date: Sat, 15 Aug 2026 16:20:54 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix(#176):=20=EB=A6=AC=ED=8F=AC=ED=8A=B8=20?= =?UTF-8?q?=EB=A1=9C=EB=94=A9/=EC=8B=A4=ED=8C=A8=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EC=9D=98=20CenteredMessage=EA=B0=80=20=EC=99=BC=EC=AA=BD?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=B9=98=EC=9A=B0=EC=B9=98=EB=8D=98=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit InterviewReportContent 의 Loading/Failed phase 가 CenteredMessage 에 Modifier.weight(1f) 만 넘기고 있었다. weight(1f) 는 Column 안에서 세로 공간만 분배할 뿐 가로 폭은 그대로 콘텐츠(스피너/문구)에 맞춰 줄어들고, Column 기본 정렬(Alignment.Start) 때문에 그 좁아진 Box 자체가 화면 왼쪽에 붙어버려 안의 Alignment.Center 가 화면 전체가 아니라 그 좁은 Box 안에서만 동작했다 — 그 결과 HilitLoadingIndicator/안내 문구가 화면 왼쪽으로 치우쳐 보였다(#176 실제 재현 화면). fillMaxWidth() 를 추가해 Box 가 화면 전체 폭을 차지하게 해서, 실제로 화면 가로 중앙에 스피너/문구가 오도록 고쳤다. 앞서 커밋한 HilitLoadingIndicator 그래픽 정사각형 수정과는 별개의, 이슈 재현 스크린샷에서 확인된 진짜 원인이다. Co-Authored-By: Claude Sonnet 5 --- .../feature/interviewreport/InterviewReportContent.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/feature/interviewreport/impl/src/main/kotlin/com/dminus14/app/feature/interviewreport/InterviewReportContent.kt b/feature/interviewreport/impl/src/main/kotlin/com/dminus14/app/feature/interviewreport/InterviewReportContent.kt index 29caed28..3a4a9cdb 100644 --- a/feature/interviewreport/impl/src/main/kotlin/com/dminus14/app/feature/interviewreport/InterviewReportContent.kt +++ b/feature/interviewreport/impl/src/main/kotlin/com/dminus14/app/feature/interviewreport/InterviewReportContent.kt @@ -55,8 +55,13 @@ internal fun InterviewReportContent( // 폴링 중 화면을 벗어날 수 있도록 닫기 버튼은 계속 노출한다. Column(modifier = Modifier.fillMaxSize()) { ReportTopBar(onClose = { onIntent(InterviewReportIntent.ClickClose) }) + // weight(1f)만 주면 Column 안에서 폭은 콘텐츠(스피너)에 맞춰 줄어들고, + // Column 기본 정렬(Alignment.Start)에 따라 그 좁은 Box 자체가 왼쪽에 + // 붙어버려 스피너가 화면 중앙이 아니라 왼쪽으로 치우쳐 보였다(#176). + // fillMaxWidth() 를 더해 Box 폭을 화면 전체로 넓혀야 안의 Alignment.Center + // 가 실제로 화면 가로 중앙을 기준으로 동작한다. CenteredMessage( - modifier = Modifier.weight(1f), + modifier = Modifier.weight(1f).fillMaxWidth(), content = { HilitLoadingIndicator() }, ) } @@ -67,8 +72,9 @@ internal fun InterviewReportContent( // 이전에는 안내 문구만 있고 액션이 없어 막다른 화면이었다. Column(modifier = Modifier.fillMaxSize()) { ReportTopBar(onClose = { onIntent(InterviewReportIntent.ClickClose) }) + // Loading phase 와 같은 이유로 fillMaxWidth() 가 필요하다(#176). CenteredMessage( - modifier = Modifier.weight(1f), + modifier = Modifier.weight(1f).fillMaxWidth(), content = { Text( text = "리포트를 불러오지 못했어요. 다시 시도해 주세요.",