-
Notifications
You must be signed in to change notification settings - Fork 0
[Feature] 세션 목록에서 칩에 대한 표현 명확화 #211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Walkthrough앱 전반에 걸쳐 “오늘의 세션” 표시와 슬라이딩 UI를 도입하고, 세션 데이터 매핑을 확장(요일/기간 필드 추가)했습니다. 세션 로딩 흐름을 단일 소스(getDateGroupedSessions)에서 파생해 오늘/진행중 세션을 계산하도록 변경하고, 새로운 active-generation 세션 API를 추가했습니다. 하단 바 높이 측정값을 CompositionLocal로 공유하도록 수정했습니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant UI as ScheduleScreen
participant VM as ScheduleViewModel
participant Repo as ScheduleRepository
participant API as ScheduleApi
UI->>VM: loadSessions()
activate VM
VM->>Repo: getDateGroupedSessions()
activate Repo
Repo->>API: GET /v1/active-generation/sessions
API-->>Repo: SessionResponse
Repo-->>VM: ScheduleList (date-grouped)
deactivate Repo
VM->>VM: Flatten schedules → filter (TODAY, ONGOING)
VM-->>UI: Update state { sessions, upcomingSessionInfo=list }
deactivate VM
note over UI: “오늘의 세션” 슬라이더는 리스트 기반으로 렌더/스냅
sequenceDiagram
autonumber
participant App as YappApp
participant Loc as CompositionLocalProvider
participant Bar as BottomNavigationBar
participant Desc as Descendant Composables
App->>Loc: Provide LocalBottomBarHeight
Loc->>Bar: Compose BottomNavigationBar
Bar->>Bar: onGloballyPositioned → measure height
Bar->>Loc: Provide measured Dp (excl. nav bar)
Loc-->>Desc: LocalBottomBarHeight.current
note over Desc: 하단 바 높이에 맞춘 레이아웃 보정
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 20
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (18)
feature/home/src/main/java/com/yapp/feature/home/HomeViewModel.kt (2)
141-149: NotFoundException/NoScheduledSessionException를 그냥 무시하면 이전 '오늘의 세션' 정보가 화면에 남습니다404(NotFound)나 일정 없음 예외가 발생해도
upcomingSession을null로 초기화하지 않아, 과거 데이터가 그대로 노출될 수 있습니다. 특히 Refresh에서 직전 상태가 남는 문제가 재현될 가능성이 큽니다. 예외 시 상태를 명시적으로 초기화하세요.적용 제안(diff):
}.onFailure { e -> when (e) { is InvalidTokenException -> postSideEffect(HomeSideEffect.NavigateToLogin) - is NoScheduledSessionException -> { } - is NotFoundException -> { } + is NoScheduledSessionException, is NotFoundException -> { + reduce { copy(upcomingSession = null) } + } else -> { postSideEffect(HomeSideEffect.HandleException(e)) e.record() } } }
127-153: 전역 isLoading 토글이 동시에 실행되는 코루틴들과 충돌하여 로딩 플래그가 흔들릴 수 있습니다
EnterHomeScreen에서 3개의 로더를joinAll로 동시 실행하는데, 각 로더가 개별적으로isLoading=true/false를 토글합니다. 로딩 인디케이터가 깜빡이거나 잘못된 시점에 해제될 수 있습니다. 섹션별 로딩 플래그(예:isLoadingUpcoming,isLoadingAttendance) 도입 또는 참조 카운트 방식으로 전역 로딩을 관리하는 것을 권장합니다.feature/schedule/src/main/java/com/yapp/feature/schedule/component/SessionItem.kt (1)
57-63: 공백만 있는 위치 문자열을 숨기는 처리 — 좋습니다
isNullOrBlank()으로 변경해 공백 문자열까지 걸러낸 점 👍. 다만 위치가 비어 있을 때도 직전에 고정Spacer(4.dp)가 항상 렌더링되어 불필요한 여백이 생길 수 있습니다. 조건부로 Spacer를 표시하는 미세 개선을 제안합니다.적용 제안(diff):
- Spacer(modifier = Modifier.height(4.dp)) - - if (!location.isNullOrBlank()) { + if (!location.isNullOrBlank()) { + Spacer(modifier = Modifier.height(4.dp)) IconWithText( iconResId = R.drawable.icon_location, text = location, contentDescription = null, ) }core/ui/src/main/java/com/yapp/core/ui/component/Indicator.kt (2)
71-116: itemCount가 0/1일 때 드래그 계산에서 예외 발생 가능(coerceIn 경계 역전) 및 불필요한 입력 처리
newPage = (dragStartPage + pageOffset).coerceIn(0, itemCount - 1)는itemCount == 0일 때coerceIn(0, -1)로IllegalArgumentException를 유발할 수 있습니다. 또한 0/1개일 때 포인터 입력을 활성화할 필요가 없습니다.안전 가드 및 경계 보정 제안(diff):
Box( modifier = modifier, contentAlignment = Alignment.Center ) { LazyRow( state = lazyListState, userScrollEnabled = false, modifier = Modifier - .pointerInput(itemCount, currentPage) { + .then( + if (itemCount > 1) Modifier.pointerInput(itemCount, currentPage) { detectDragGesturesAfterLongPress( onDragStart = { offset -> haptics.performHapticFeedback(HapticFeedbackType.LongPress) dragStartPage = currentPage dragStartX = offset.x }, onDrag = { change, _ -> val dragDistance = change.position.x - dragStartX val pageOffset = (dragDistance / dotSpacingPx).toInt() - val newPage = (dragStartPage + pageOffset).coerceIn(0, itemCount - 1) + val lastIndex = (itemCount - 1).coerceAtLeast(0) + val newPage = (dragStartPage + pageOffset).coerceIn(0, lastIndex) if (newPage != currentPage) { haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove) onPageSelect(newPage) } } ) - ) + } else Modifier + ) .widthIn(max = (visibleDotCount * (dotSize + dotSpacing)).coerceAtLeast(60.dp)), horizontalArrangement = Arrangement.spacedBy(dotSpacing), verticalAlignment = Alignment.CenterVertically ) { items(itemCount) { i ->또한 스크롤 애니메이션도 0개일 때 실행하지 않도록 아래 수정이 필요합니다.
- LaunchedEffect(scrollTarget) { + LaunchedEffect(scrollTarget, itemCount) { coroutineScope.launch { - lazyListState.animateScrollToItem(index = scrollTarget) + if (itemCount > 0) { + lazyListState.animateScrollToItem(index = scrollTarget) + } } }
101-116: 포커스/접근성 개선: 점(Indicator) 개별 탭 선택과 선택 상태 semantics 추가 권장현재 long-press+drag만 지원합니다. TalkBack 사용자는 선택이 어렵고, 키보드/트랙패드 접근도 제한됩니다. 각 점에 클릭과
selectedsemantics를 추가해 주세요.적용 제안(diff):
items(itemCount) { i -> val scaleFactor = 1f - (0.1f * abs(i - currentPage)).coerceAtMost(0.4f) val color = if (i == currentPage) activeColor else inactiveColor Box( modifier = Modifier .size(if (i == currentPage) selectedDotSize else dotSize) + .clickable(enabled = itemCount > 1, onClick = { onPageSelect(i) }, role = Role.Tab) + .semantics { + selected = (i == currentPage) + } .graphicsLayer { scaleX = scaleFactor scaleY = scaleFactor } .drawBehind { drawCircle(color) } ) }필요한 import:
import androidx.compose.foundation.clickable import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.selected import androidx.compose.ui.semantics.semanticsfeature/home/src/main/java/com/yapp/feature/home/component/HomeHeader.kt (2)
69-75: 센터 계산식이 오프셋을 두 번 포함해 약간의 오차가 발생할 수 있습니다
center = start + end/2대신center = start + (end - start)/2가 지정학적으로 정확합니다. 콘텐츠 패딩이 있을 때 현재 구현은 몇 px만큼 어긋날 수 있습니다.적용 제안(diff):
- val center = lazyListState.layoutInfo.viewportStartOffset + - lazyListState.layoutInfo.viewportEndOffset / 2 + val info = lazyListState.layoutInfo + val center = info.viewportStartOffset + (info.viewportEndOffset - info.viewportStartOffset) / 2
142-151: 세션이 비어 있을 때 Indicators 호출을 건너뛰어 안전 경계 확보
sessions.size == 0인 경우에도Indicators(itemCount=0)가 호출되면, Indicator 쪽에서 경계 조건을 방어하지 않으면 크래시 가능성이 있습니다. 헤더에서도 가드하는 것이 안전합니다.적용 제안(diff):
- Indicators( - itemCount = sessions.size, - onPageSelect = { index -> - scope.launch { - lazyListState.scrollToItem(index) - } - }, - currentPage = selectedIndex - ) + if (sessions.isNotEmpty()) { + Indicators( + itemCount = sessions.size, + onPageSelect = { index -> + scope.launch { lazyListState.scrollToItem(index) } + }, + currentPage = selectedIndex + ) + }core/data/src/main/java/com/yapp/core/data/remote/model/response/SessionResponse.kt (4)
22-25: startDayOfWeek/endDayOfWeek 필드 도입 시 역직렬화 호환성 확인신규 엔드포인트에서는 제공되겠지만, 과거/다른 엔드포인트와 혼용 시 startDayOfWeek가 누락되면 역직렬화 실패 위험(Non-null)입니다. 서버 스키마가 항상 보장되는지 확인하거나, 안전성을 위해 Nullable + 기본값 처리도 고려해 주세요.
35-41: isToday 계산과 요일(dayOfTheWeek) 산정에 firstSession 의존 — 데이터 불일치 가정 확인같은 날짜 그룹 내 모든 세션이 동일한 relativeDays/요일을 갖는다는 서버 불변식이 전제입니다. 만약 다를 가능성이 있다면 any { relativeDays == 0 } 혹은 대표값 선정 규칙(가장 이른 시간 등)으로 보강이 필요합니다.
Apply this diff to make isToday more 견고하게 계산하는 예시:
- isToday = firstSession.relativeDays == 0, + isToday = sessions.any { it.relativeDays == 0 },
41-57: 세션 정렬 보강 제안(시간 기준)서버 정렬이 항상 보장되지 않으면 UI 일관성이 떨어질 수 있습니다. 시간(없으면 이름) 기준으로 정렬 후 매핑을 권장합니다.
다음과 같이 정렬을 추가할 수 있습니다:
- schedules = sessions.map { + val sorted = sessions.sortedWith( + compareBy<SessionResponse.Session> { it.time ?: "00:00" } + .thenBy { it.name } + ) + schedules = sorted.map { ScheduleInfo(
62-79: Home 변환은 기존 매핑(toSessionProgressPhase) 유지 — 의도 확인HomeSession 모델에 대해서는 기존 매핑을 유지하고 있습니다. 화면 간 상태명이 다를 수 있으므로, 기획/QA 관점에서 표현 불일치가 문제 없음을 확인해 주세요.
feature/schedule/src/main/java/com/yapp/feature/schedule/component/DateGroupedScheduleItem.kt (2)
120-139: 프리뷰 데이터 형식/일관성 정리상단 DateGroupedScheduleItem 인자(date="2025-05-08")와 내부 ScheduleInfo.date("2023.10.01")의 포맷/값이 달라 혼동을 유발할 수 있습니다. 포맷/요일("일")과 실제 날짜 일치 여부를 맞춰 주세요.
Apply this diff 예시(값은 임의):
- date = "2025-05-08", - dayOfWeek = "일", + date = "2025-05-18", + dayOfWeek = "일", ... - date = "2023.10.01", - endDate = "2023.10.01" + date = "2025.05.18", + endDate = "2025.05.18"
174-197: 두 번째 프리뷰도 동일하게 포맷 일치 권장위 코멘트와 동일 맥락으로 날짜 문자열 포맷과 요일을 맞추면 디자인 검증시 혼동이 줄어듭니다.
feature/schedule/src/main/java/com/yapp/feature/schedule/ScheduleViewModel.kt (4)
49-57: SESSION 탭 새로고침 경로가 이원화되어 일관성/깜빡임(flicker) 우려RefreshTab.SESSION에서 refreshUpcomingSessionInfo(= getDateGroupedSessions, 캐시 의존 가능성)와 refreshSessions(= refreshDateGroupedSessions, 네트워크 강제)를 분리 호출합니다. 서로 다른 소스/타이밍으로 isLoading을 두 번 토글해 UI 깜빡임과 상태 불일치(세션은 최신, 오늘의 세션은 구버전)가 발생할 수 있습니다. 단일 refreshDateGroupedSessions 결과로 sessions/upcomingSessionInfo를 함께 갱신하는 쪽이 안전합니다.
다음과 같이 단일 경로로 합치는 것을 제안합니다:
when (intent.tab) { ScheduleTab.ALL -> refreshScheduleInfo(state.selectedYear, state.selectedMonth, reduce, postSideEffect) ScheduleTab.SESSION -> { - refreshUpcomingSessionInfo(reduce, postSideEffect) - refreshSessions(reduce, postSideEffect) + refreshSessionsAndUpcoming(reduce, postSideEffect) } }아래에 새 함수 제안을 추가합니다(파일 외부 코드 블록 참조).
101-117: TODAY/ONGOING 필터 중복 로직 추출 및 불필요 이중 로딩 토글 제거
- 필터 로직이 여기와 refresh 쪽에 중복됩니다. 헬퍼로 추출해 재사용을 권장합니다.
- onSuccess 블록에서 isLoading=false로 만들고, 함수 말미에서 다시 false로 설정하고 있어 중복입니다. finally 한 곳에서만 false로 토글하세요.
Apply this diff:
- }.onSuccess { + }.onSuccess { val upcomingSessions = it.dates .flatMap { date -> date.schedules } - .filter { session -> session.scheduleProgressPhase == ScheduleProgressPhase.TODAY || session.scheduleProgressPhase == ScheduleProgressPhase.ONGOING } + .filter { session -> + session.scheduleProgressPhase in setOf( + ScheduleProgressPhase.TODAY, + ScheduleProgressPhase.ONGOING + ) + } reduce { copy( - isLoading = false, sessions = it, upcomingSessionInfo = upcomingSessions + isLoading = false, + sessions = it, + upcomingSessionInfo = upcomingSessions ) } }.onFailure { e -> postSideEffect(ScheduleSideEffect.HandleException(e)) e.record() } - reduce { copy(isLoading = false) } + // finally에서 한 번만 false로 만드는 패턴 유지 권장 (상단에서 이미 false 처리됨)또한 정렬 일관성을 위해 upcomingSessions도 날짜/시간 기준 정렬을 고려해 주세요.
Also applies to: 122-123
153-169: refreshUpcomingSessionInfo가 getDateGroupedSessions(캐시) 호출 — 새로고침 동작 불일치새로고침 액션에서 캐시 레이어(get…)를 쓰면 최신 데이터가 반영되지 않을 수 있습니다. refreshDateGroupedSessions 사용 또는 위 제안처럼 단일 API 결과로 sessions/upcomingSessionInfo 동시 갱신을 권장합니다. 현 구조는 isLoading 토글도 2회 발생합니다.
Apply this minimal fix if 유지할 경우:
- scheduleRepository.getDateGroupedSessions() + scheduleRepository.refreshDateGroupedSessions()단, 최종적으로는 본 함수 자체를 제거하고 refreshSessions 경로에서 함께 계산하는 구조가 더 단순합니다.
175-189: refreshSessions에서 upcomingSessionInfo 동기화 누락세션 리스트만 갱신하면 오늘의 세션 리스트와 데이터가 엇갈릴 수 있습니다. 여기서도 upcomingSessionInfo를 함께 계산/세팅하거나, 단일 함수로 병합하세요.
아래 통합 함수 예시를 참고해 주세요.
feature/schedule/src/main/java/com/yapp/feature/schedule/ScheduleScreen.kt (1)
359-399: Preview 데이터 최신 스키마와의 타입 일치 검증프리뷰에서
upcomingSessionInfo = listOf(...)로 전달됩니다. 본문과 동일하게 네이밍/타입이 실제ScheduleState와 일치하는지 다시 한 번 확인 바랍니다(특히 endDate/endDayOfWeek의 nullability가 데이터 계층과 다를 수 있음).
- 프리뷰도 실제 런타임 스키마와 동일하게 유지하면 리팩토링 시 컴파일 타임에 문제를 조기 포착할 수 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (18)
app/src/main/java/com/yapp/app/YappApp.kt(4 hunks)core/data/src/main/java/com/yapp/core/data/data/repository/ScheduleRepositoryImpl.kt(2 hunks)core/data/src/main/java/com/yapp/core/data/remote/api/ScheduleApi.kt(1 hunks)core/data/src/main/java/com/yapp/core/data/remote/model/response/DateGroupedScheduleResponse.kt(3 hunks)core/data/src/main/java/com/yapp/core/data/remote/model/response/SessionResponse.kt(1 hunks)core/model/src/main/java/com/yapp/model/ScheduleInfo.kt(2 hunks)core/ui/src/main/java/com/yapp/core/ui/component/BottomNavigationBar.kt(1 hunks)core/ui/src/main/java/com/yapp/core/ui/component/Indicator.kt(2 hunks)core/ui/src/main/java/com/yapp/core/ui/util/DateTime.kt(1 hunks)feature/home/src/main/java/com/yapp/feature/home/HomeViewModel.kt(2 hunks)feature/home/src/main/java/com/yapp/feature/home/component/HomeHeader.kt(1 hunks)feature/schedule/src/main/java/com/yapp/feature/schedule/ScheduleContract.kt(2 hunks)feature/schedule/src/main/java/com/yapp/feature/schedule/ScheduleScreen.kt(7 hunks)feature/schedule/src/main/java/com/yapp/feature/schedule/ScheduleViewModel.kt(3 hunks)feature/schedule/src/main/java/com/yapp/feature/schedule/component/DateGroupedScheduleItem.kt(6 hunks)feature/schedule/src/main/java/com/yapp/feature/schedule/component/SessionItem.kt(1 hunks)feature/schedule/src/main/java/com/yapp/feature/schedule/component/UpcomingSessionSection.kt(3 hunks)feature/schedule/src/main/res/values/strings.xml(1 hunks)
🔇 Additional comments (10)
feature/home/src/main/java/com/yapp/feature/home/HomeViewModel.kt (1)
19-19: 404 에러 → NotFoundException 매핑 적용 여부 수동 검증 요청core/data 모듈의 Retrofit 설정에서
ApiResultCallAdapterFactory(및OptionalApiResultCallAdapterFactory)가 실제로Retrofit.Builder에 등록되어 있는지 확인이 필요합니다.
이 어댑터들이 등록되어야만,handleCommonError(404)가 호출되어NotFoundException으로 변환되며 홈 화면의when (e) is NotFoundException분기로 내려옵니다.검증할 사항:
- Retrofit 인스턴스 생성 시
ResultCallAdapterFactory.create()혹은OptionalApiResultCallAdapter가 Builder에 추가되었는지 (addCallAdapterFactory호출 여부).- suspend 함수 호출(코루틴)에서도 동일한 에러 매핑 로직이 적용되는지.
위 설정이 누락되면 404가
HttpException으로 그대로 올라와 일반 예외 처리(HomeSideEffect.HandleException)가 될 수 있습니다.
확인 후 피드백 부탁드립니다.core/ui/src/main/java/com/yapp/core/ui/component/Indicator.kt (1)
34-46: 공개 API 패키지 경로 변경 검증 완료구 패키지(
com.yapp.feature.home.component.Indicators)를 참조하는 import 구문은 전역 검색 결과 발견되지 않았으며,Indicators호출부 역시 최신 패키지(com.yapp.core.ui.component)를 사용하고 있습니다.
별도 수정이 필요하지 않으므로 이 부분은 해결되었습니다.feature/home/src/main/java/com/yapp/feature/home/component/HomeHeader.kt (2)
41-41: Indicator import 경로 변경 — 정상 적용 확인
Indicator가 core/ui로 이동하며 공개 API가 되었고, 본 파일에서도 새 경로로 교체되어 일관됩니다. 추가 조치 필요 없습니다.
125-136: onClickSessionItem이 빈 람다로 전달됩니다 — 의도 확인 필요카드 클릭 시 동작이 비활성화되어 있습니다. 상세 화면 이동 등 의도된 네비게이션 콜백 연동을 확인해 주세요.
core/model/src/main/java/com/yapp/model/ScheduleInfo.kt (1)
41-41: ScheduleProgressPhase 변경에 따른 검토 결과아래 검색 결과로 ScheduleProgressPhase 및 ScheduleInfo 모델이 참조되는 위치가 확인되었습니다. 현재
ScheduleInfo.kt에서만DONE("종료")로 변경된 상태이며, 이 모델을 직접 참조하는 UI/테스트 코드는 발견되지 않았습니다.• core/model/src/main/java/com/yapp/model/ScheduleInfo.kt (enum 정의)
└ DONE("종료"), TODAY("당일"), ONGOING("진행중"), PENDING("예정")• ScheduleProgressPhase 사용처: 없음
• ScheduleInfo 사용처: 없음추가로 UI에서 모델의
title값을 노출하는 컴포넌트나, 스냅샷/문구 비교 테스트가 있는지 확인이 필요합니다.
- 만약
ScheduleProgressPhase.DONE.title을 직접 사용해 "완료"를 기대하는 테스트가 있다면,종료로 변경되며 실패할 수 있습니다.- 릴리스 노트 및 카피 가이드에도 “종료” 반영 여부를 검토해주세요.
필요 시:
- 관련 UI 컴포넌트 검토 및 테스트 수정
- 별도 PR로 테스트·문서 업데이트 분리
core/data/src/main/java/com/yapp/core/data/remote/api/ScheduleApi.kt (1)
20-21: 신규 엔드포인트 추가 LGTMactive-generation 세션 전용 API 분리는 의도와 구현이 명확합니다. 메서드 시그니처도 간결합니다.
app/src/main/java/com/yapp/app/YappApp.kt (2)
57-91: CompositionLocal로 BottomBar 높이 주입 접근은 합리적 — Insets 처리 상호작용만 재점검contentWindowInsets = WindowInsets(0.dp)로 덮어쓰고, 화면 하단은 조건부로 navigationBars를 consume하고 있습니다. 상단(status bars) 등 여타 inset 처리는 상위 레이아웃에서 보장되는지 확인 부탁드립니다. 또한 IME(키보드) 등장 시 bottomBar 높이를 사용할 컴포넌트가 원하는 동작(레이아웃 이동/고정)을 하는지도 점검이 필요합니다.
142-146: 네비게이션 바 차감 로직 검증 필요아래 두 가지 사항을 확인해 주세요:
- onGloballyPositioned로 얻은
coordinates.size.height에 이미WindowInsets가 반영된 상태인지 확인
• 이미 반영되어 있다면, 별도 네비게이션 바 높이 차감 로직을 제거하는 방안을 고려해야 합니다.heightDp - navigationBarHeight계산 결과가 음수가 될 수 있으므로, 최소 0dp로 하한을 두는coerceAtLeast(0.dp)적용을 권장합니다.예시 제안(diff):
BottomNavigationBar( modifier = modifier.onGloballyPositioned { coordinates -> val heightDp = with(density) { coordinates.size.height.toDp() } - val bottomBarHeightWithoutNav = heightDp - navigationBarHeight + val bottomBarHeightWithoutNav = (heightDp - navigationBarHeight).coerceAtLeast(0.dp) onHeightMeasured(bottomBarHeightWithoutNav) }또한,
BottomNavigationBar내부에서 이미WindowInsets처리를 수행 중이라면 이중 차감 여부를 반드시 검토해 주세요.feature/schedule/src/main/java/com/yapp/feature/schedule/component/DateGroupedScheduleItem.kt (1)
86-94: formatScheduleTimeRange로 교체 LGTM — null/형식 케이스만 점검date, endDate 형식(yyyy-MM-dd vs yyyy.MM.dd 혼재)과 time/endTime null 케이스에서 의도한 문자열이 생성되는지 확인해 주세요. 유틸이 null 반환 시, SessionItem의 duration 파라미터 처리(빈 문자열 대체 등)도 점검이 필요합니다.
core/data/src/main/java/com/yapp/core/data/remote/model/response/DateGroupedScheduleResponse.kt (1)
44-47: endDate/요일 필드 null 안정성 확인 필요
- core/data/src/main/java/com/yapp/core/data/remote/model/response/DateGroupedScheduleResponse.kt (Lines 44–47)
•endDate: String→ 서버에서 값이 빠지면kotlinx.serialization디시리얼라이즈 예외 발생 가능
•startDayOfTheWeek/endDayOfTheWeek가 non-null로 추가되어, UI(UpcomingSessionItem)에서는String?로 가정하는 현재 타입과 불일치제안하는 안전한 기본값 처리 방식:
data class ScheduleResponse( … - val startDayOfTheWeek: String, - val endDate: String, - val endDayOfTheWeek: String, + val startDayOfTheWeek: String, + val endDate: String? = null, + val endDayOfTheWeek: String? = null, … ) { fun toScheduleModel() = ScheduleInfo( … - endDate = endDate, - startDayOfWeek = startDayOfTheWeek, - endDayOfWeek = endDayOfTheWeek, + endDate = endDate ?: date, // 단일 일정 기본값 + startDayOfWeek = startDayOfTheWeek, + endDayOfWeek = endDayOfTheWeek ?: startDayOfTheWeek, // 미제공 시 시작 요일로 대체 … ) }
- 위 처리 후에도 서버 스펙(특히 단일일정에서
endDate/endDayOfTheWeek보장 여부)을 반드시 재확인해주세요.- 서버 계약이 100% non-null을 보장한다면, UI 측
UpcomingSessionItem또한 non-null 타입으로 통일하는 방향을 고려하십시오.
core/data/src/main/java/com/yapp/core/data/data/repository/ScheduleRepositoryImpl.kt
Show resolved
Hide resolved
core/data/src/main/java/com/yapp/core/data/data/repository/ScheduleRepositoryImpl.kt
Show resolved
Hide resolved
core/data/src/main/java/com/yapp/core/data/remote/model/response/DateGroupedScheduleResponse.kt
Show resolved
Hide resolved
feature/schedule/src/main/java/com/yapp/feature/schedule/component/UpcomingSessionSection.kt
Show resolved
Hide resolved
feature/schedule/src/main/java/com/yapp/feature/schedule/ScheduleContract.kt
Outdated
Show resolved
Hide resolved
feature/schedule/src/main/java/com/yapp/feature/schedule/ScheduleScreen.kt
Show resolved
Hide resolved
feature/schedule/src/main/java/com/yapp/feature/schedule/ScheduleScreen.kt
Show resolved
Hide resolved
✅ Actions performedReview triggered.
|
| import com.yapp.core.designsystem.theme.YappTheme | ||
|
|
||
| val LocalBottomBarHeight = compositionLocalOf { 56.dp } | ||
| val LocalBottomBarHeight = compositionLocalOf { 0.dp } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C: 음 .. 혹시 이거 scaffold의 innerpadding.calculateBottom() 써서 받아오는건 안되려나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bd0ad36 수정했습니다!
| return "${formatToKoreanTime(context, startTime)} - ${formatToKoreanTime(context, endTime)}" | ||
| } | ||
|
|
||
| fun formatScheduleTimeRange( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C: 요 함수는 컴포저블 내부에서도 호출되겠죠? 리컴포지션 때마다 호출되면 성능 이슈가 좀 있을 것 같은데 호출되는 곳에서 remember로 잘 처리되고 있는지 한번 확인 부탁드려용
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aacce45 수정했습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨어요!!
💡 Issue
🌱 Key changes
스프린트 내용
관련 디스코드 스레드
v1/active-generation/sessions사용TODAY,ONGOING인 세션을 스크롤 가능한 형태로 노출✅ To Reviewers
이전에 사용하던
v1/active-generation/sessions를 다시 재사용하면서progressPhase, attendanceStatus가 다른 API의 응답 값과 일치하지 않아 새롭게 확장 함수를 만들었습니다.
📸 스크린샷
Summary by CodeRabbit