Conversation
개요여행 상세 화면의 장소 재정렬 기능과 교통 수단 선택 기능을 추가합니다. 새로운 드래그 앤 드롭 유틸리티, 교통 수단 바텀시트 컴포넌트, 데이터 모델 재구성을 통해 장소별 교통 세그먼트 관리를 개선합니다. 변경사항
코드 검토 난이도🎯 4 (복잡함) | ⏱️ ~45분 🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
dd71d7d to
ace46c6
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailViewModel.kt (2)
462-485:⚠️ Potential issue | 🔴 Critical
confirmDuration에서endTime계산에 이전 duration 값이 사용됩니다.
itinerary.totalDuration은itinerary.places(업데이트 전 원본)를 기반으로 계산되는 computed property입니다.durationUpdatedPlaces에 반영된 새로운 duration이 아닌, 변경 전 값으로endTime이 설정됩니다.🐛 수정 제안: 업데이트된 itinerary로부터 totalDuration 계산
itinerary.copy( places = calculatePlaceStartTimes(durationUpdatedPlaces, itinerary.startTime ?: DEFAULT_START_TIME.hours), - endTime = (itinerary.startTime ?: DEFAULT_START_TIME.hours) + itinerary.totalDuration, ) + val baseStartTime = itinerary.startTime ?: DEFAULT_START_TIME.hours + val updatedItinerary = itinerary.copy( + places = calculatePlaceStartTimes(durationUpdatedPlaces, baseStartTime), + ) + updatedItinerary.copy(endTime = baseStartTime + updatedItinerary.totalDuration)
311-318:⚠️ Potential issue | 🟡 Minor
longClickPlaceItem에서tempItineraries를 동기화하지 않습니다.
clickEditTravel(라인 222-229)에서는tempItineraries = itineraries로 최신 상태를 동기화하지만,longClickPlaceItem에서는 동기화하지 않습니다. 교통수단 변경이나 시간 수정 후 롱프레스로 편집 모드에 진입하면 이전 데이터가 표시될 수 있습니다.🐛 수정 제안: clickEditTravel과 동일하게 tempItineraries 동기화
private fun longClickPlaceItem() { reduce { copy( isEditMode = true, selectedPlaceIds = emptySet(), + tempItineraries = itineraries, ) } }
🤖 Fix all issues with AI agents
In `@core/ui/src/main/java/com/yapp/ndgl/core/ui/util/ReorderableList.kt`:
- Around line 173-179: onDragEnd() currently just nulls autoScrollJob but
doesn't cancel the running coroutine; modify onDragEnd() to call
autoScrollJob?.cancel() (and optionally autoScrollJob?.cancelAndJoin() if you
need to wait for termination) before setting autoScrollJob = null so any running
auto-scroll coroutine is stopped; update the method that references
autoScrollJob (the onDragEnd() function in ReorderableList.kt) to perform this
cancellation.
In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/TransportBottomSheet.kt`:
- Around line 88-96: The Row's clickable modifier is placed after padding so the
touch target is reduced; in TransportBottomSheet (the Row that sets
selectedTransport) move the .noRippleClickable modifier to be before .padding
(i.e., apply it earlier in the modifier chain, ahead of
.padding/.height/.background) so the entire Row area becomes touchable and still
updates selectedTransport when tapped.
In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailViewModel.kt`:
- Around line 393-416: confirmChangeTransportSegment updates itineraries but
never closes the transport BottomSheet or clears the selectedPlace; update the
state returned by the reduce call so that after computing updatedItineraries you
return copy(itineraries = updatedItineraries, showTransportBottomSheet = false,
selectedPlace = null) (i.e., modify the reduce result inside
confirmChangeTransportSegment to explicitly set showTransportBottomSheet to
false and selectedPlace to null).
🧹 Nitpick comments (7)
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/PlaceItem.kt (1)
93-96:Color.Transparent배경은 불필요한 코드입니다.투명 색상으로 배경을 설정하는 것은 시각적으로 아무 효과가 없으므로,
.background(...)호출 자체를 제거하는 것이 더 깔끔합니다.♻️ 제안
Row( modifier = Modifier .fillMaxWidth() - .background( - color = Color.Transparent, - shape = RoundedCornerShape(16.dp), - ) .padding(horizontal = 0.dp),core/ui/src/main/java/com/yapp/ndgl/core/ui/util/ReorderableList.kt (1)
65-72:isReorderable람다가remember블록에 캡처되어 업데이트되지 않습니다.
rememberReorderableState에 전달된isReorderable람다가 변경되어도remember블록 내부의ReorderableState는 초기 값을 계속 사용합니다.onReorder처럼rememberUpdatedState로 감싸거나,remember의 키로 추가하는 것을 고려해 주세요.♻️ 수정 제안
val scope = rememberCoroutineScope() val currentList by rememberUpdatedState(list) + val currentIsReorderable by rememberUpdatedState(isReorderable) val onReorder: (Int, Int) -> Boolean = { from, to -> currentList.reorder(from - offset, to - offset) } return remember { ReorderableState( scope = scope, lazyListState = lazyListState, onReorder = onReorder, - isReorderable = isReorderable, + isReorderable = { currentIsReorderable(it) }, ) }core/ui/src/main/java/com/yapp/ndgl/core/ui/designsystem/NDGLBottomSheet.kt (1)
53-71: 헤더 Row에verticalAlignment이 지정되지 않았습니다.
Row의 기본verticalAlignment는Alignment.Top입니다. 제목 텍스트와 닫기 아이콘의 높이가 다를 수 있으므로,Alignment.CenterVertically를 추가하면 더 나은 정렬을 보장할 수 있습니다.♻️ 수정 제안
Row( modifier = Modifier .fillMaxWidth() .padding(vertical = 18.dp, horizontal = 24.dp), + verticalAlignment = Alignment.CenterVertically, ) {feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/TransportBottomSheet.kt (1)
86-86:index파라미터가 사용되지 않습니다.
itemsIndexed대신items를 사용하면 불필요한 파라미터를 제거할 수 있습니다. 또는index를_로 변경하세요.feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailViewModel.kt (1)
559-571:createTransportSegment가 실제from/to파라미터를 사용하지 않고 하드코딩된 값을 반환합니다.TODO 주석으로 명시되어 있어 인지하고 있는 부분이지만, 현재 모든 재배치에서 동일한 교통 정보(CAR, 15분, 1000m)가 할당됩니다. API 연동 전까지 임시적으로 기존
transportToNext값을 유지하는 방식도 고려해 볼 수 있습니다.feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailScreen.kt (2)
209-219:placesOffset = 3은 LazyColumn 구조에 강하게 결합된 매직 넘버입니다.LazyColumn 내 장소 아이템 앞에 위치한 아이템 수(헤더, stickyHeader, 맵)에 의존합니다. 향후 아이템 추가/제거 시 동기화가 깨질 수 있으므로, 주석 외에 상수로 추출하거나 동적으로 계산하는 방안을 고려하세요.
497-503: 기본 시작 시간8.hours가 ViewModel의DEFAULT_START_TIME과 중복됩니다.ViewModel에서
DEFAULT_START_TIME = 8을companion object로 관리하고 있으나, 여기서는8.hours를 직접 하드코딩하고 있습니다. 공통 상수로 통일하면 향후 변경 시 누락을 방지할 수 있습니다.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailViewModel.kt`:
- Around line 474-477: The endTime is still using itinerary.totalDuration which
reflects the old places; update endTime to use the duration computed from
durationUpdatedPlaces (e.g., recompute totalDuration from durationUpdatedPlaces)
or construct a temporary Itinerary with places = durationUpdatedPlaces, compute
its totalDuration, then set endTime = (itinerary.startTime ?:
DEFAULT_START_TIME.hours) + recomputedTotalDuration; ensure
calculatePlaceStartTimes is used for places and the recomputed totalDuration is
used for endTime instead of itinerary.totalDuration.
🧹 Nitpick comments (4)
core/ui/src/main/java/com/yapp/ndgl/core/ui/designsystem/NDGLBottomSheet.kt (1)
60-70: 닫기 아이콘에 접근성 설명을 추가하는 것을 권장합니다.
contentDescription이null로 설정되어 있어 스크린 리더 사용자가 버튼의 기능을 인식하기 어렵습니다.♻️ 수정 제안
Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_24_close), - contentDescription = null, + contentDescription = "닫기", tint = NDGLTheme.colors.black600,feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/TransportBottomSheet.kt (1)
86-86:itemsIndexed대신items사용을 권장합니다.
index파라미터가 사용되지 않으므로items(availableTransports)로 변경하면 더 간결합니다.♻️ 수정 제안
- itemsIndexed(availableTransports) { index, transport -> + items(availableTransports) { transport ->
itemsimport 추가 필요:import androidx.compose.foundation.lazy.itemscore/ui/src/main/java/com/yapp/ndgl/core/ui/util/ReorderableList.kt (1)
104-104:autoScrollJob에mutableStateOf대신 일반 변수 사용을 권장합니다.
autoScrollJob은 UI 렌더링에 사용되지 않는 내부 상태이므로mutableStateOf로 인한 불필요한 리컴포지션 오버헤드가 발생합니다.♻️ 수정 제안
- private var autoScrollJob by mutableStateOf<Job?>(null) + private var autoScrollJob: Job? = nullfeature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailScreen.kt (1)
506-523: Mock 교통수단 목록 생성 로직에서 중복이 발생할 수 있습니다.
mockAvailableTransports의 각 항목은 고정된 duration/distance 값을 가집니다.state.selectedPlace.transportToNext가 다른 값(예: WALK, 10분, 800m)을 가지면remove()가 일치하는 항목을 찾지 못해add()후 같은 타입의 교통수단이 중복될 수 있습니다.TODO 주석이 있어 실제 API 연동 시 수정될 예정이므로 현재는 큰 문제가 아니지만, 임시 구현 시에도 타입 기반 필터링을 고려해볼 수 있습니다.
♻️ 선택적 개선안
val mockAvailableTransports = mutableListOf( TransportSegment(TransportType.WALK, 15.minutes, 1200), TransportSegment(TransportType.CAR, 10.minutes, 5400), TransportSegment(TransportType.BUS, 25.minutes, 4800), TransportSegment(TransportType.TRAIN, 40.minutes, 12000), ) - mockAvailableTransports.remove(state.selectedPlace.transportToNext) - mockAvailableTransports.add(state.selectedPlace.transportToNext) + mockAvailableTransports.removeAll { it.type == state.selectedPlace.transportToNext.type } + mockAvailableTransports.add(state.selectedPlace.transportToNext)
ace46c6 to
4c05dd9
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailViewModel.kt (1)
374-381:⚠️ Potential issue | 🟠 Major
confirmEditMode에서 재배치 후 장소별 시작 시간이 재계산되지 않습니다.
reorderPlaces는recalculateTransportSegments만 호출하고calculatePlaceStartTimes는 호출하지 않습니다.confirmEditMode에서tempItineraries를 그대로itineraries에 반영하므로, 재배치된 장소들의startTime이 원래 순서 기준의 값을 유지하게 됩니다.🐛 수정 제안
private fun confirmEditMode() { reduce { + val recalculatedItineraries = tempItineraries.map { itinerary -> + val baseStartTime = itinerary.startTime ?: DEFAULT_START_TIME.hours + val updatedPlaces = calculatePlaceStartTimes(itinerary.places, baseStartTime) + itinerary.copy( + places = updatedPlaces, + endTime = itinerary.startTime?.let { baseStartTime + itinerary.copy(places = updatedPlaces).totalDuration }, + ) + } copy( - itineraries = tempItineraries, + itineraries = recalculatedItineraries, isEditMode = false, selectedPlaceIds = emptySet(), ) } }
🤖 Fix all issues with AI agents
In `@core/ui/src/main/java/com/yapp/ndgl/core/ui/util/ReorderableList.kt`:
- Around line 148-162: tryMoveDown is missing the same isReorderable check used
in tryMoveUp, so non-reorderable targets can be moved when dragging down; update
tryMoveDown to verify isReorderable(target.key) before calling onReorder in both
the visible-next-item branch and the else/autoscroll branch (mirror the guard in
tryMoveUp), and only set info when the target passes isReorderable and onReorder
returns true.
- Around line 65-72: The remember block in rememberReorderableState captures
isReorderable once so subsequent changes are ignored; update the remember call
to include isReorderable as a key (e.g., remember(isReorderable) {
ReorderableState(...) }) so a new ReorderableState is created when isReorderable
changes; keep using rememberUpdatedState(for onReorder) as-is and reference the
rememberReorderableState function, ReorderableState class, and the isReorderable
parameter when making this change.
In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailScreen.kt`:
- Around line 509-526: The mockAvailableTransports construction in
TravelDetailScreen can produce duplicates because
remove(state.selectedPlace.transportToNext) relies on structural equality;
instead remove any entries by transport type before adding the selected
transport. Locate the block building mockAvailableTransports and replace the
remove/add sequence with a type-based filter or removeAll by comparing
TransportSegment.transportType/TransportType (e.g., removeAll { it.type ==
state.selectedPlace.transportToNext.type }) then add the selected transport,
ensuring initialTransport/availableTransports remain consistent for
TransportBottomSheet.
In
`@feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailViewModel.kt`:
- Around line 393-416: confirmChangeTransportSegment updates transportToNext but
doesn't update places' endTime when travel duration changes; after mapping the
selected day's places and recalculating start times via
calculatePlaceStartTimes, also recalculate and set each Place's endTime based on
its startTime plus its totalDuration (including the new transportToNext where
applicable) so totalDuration and endTime stay consistent. Locate
confirmChangeTransportSegment and the block that builds timedPlaces, and either
(A) update calculatePlaceStartTimes to compute and return endTime for each place
using place.startTime + place.totalDuration, or (B) after timedPlaces is
produced, map over timedPlaces and set place.endTime = place.startTime +
place.totalDuration before copying the dayItinerary back into itineraries;
ensure you reference transportToNext, totalDuration, startTime, and endTime when
making the change.
🧹 Nitpick comments (8)
core/util/src/main/java/com/yapp/ndgl/core/util/IntUtil.kt (1)
11-17: 정수 연산으로 정수 킬로미터 여부를 확인하는 것이 더 안전합니다.
km % 1 == 0.0은 부동소수점 비교입니다.Int를Double로 나누기 때문에 현재 범위에서는 실질적으로 문제가 없지만,this % 1000 == 0으로 정수 연산을 사용하면 의도가 더 명확하고 안전합니다.또한,
formatDecimal()은Locale.US를 사용하지만,formatDistance()는Locale.getDefault()를 사용하고 있습니다. 일부 로케일에서는 소수점 구분자가 쉼표(,)로 표시되어"5,5km"처럼 출력될 수 있습니다. 의도된 동작인지 확인해 주세요.♻️ 정수 연산 활용 제안
this >= 1000 -> { - val km = this / 1000.0 - if (km % 1 == 0.0) { - "${km.toInt()}km" + if (this % 1000 == 0) { + "${this / 1000}km" } else { + val km = this / 1000.0 String.format(getDefault(), "%.1fkm", km) } }feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/PlaceItem.kt (1)
93-96: 투명 배경에shape파라미터가 불필요합니다.
Color.Transparent에RoundedCornerShape를 지정해도 시각적 효과가 없으므로,.background(...)호출 자체를 제거하거나 shape 인자를 제거하는 것을 고려해 주세요.♻️ 수정 제안
.fillMaxWidth() - .background( - color = Color.Transparent, - shape = RoundedCornerShape(16.dp), - ) .padding(horizontal = 0.dp),core/ui/src/main/java/com/yapp/ndgl/core/ui/designsystem/NDGLBottomSheet.kt (2)
75-83: 닫기 아이콘에contentDescription이 누락되어 접근성이 제한됩니다.TalkBack 등 스크린 리더 사용자가 닫기 버튼의 용도를 알 수 없습니다. 의미 있는 content description을 추가해 주세요.
♻️ 수정 제안
Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_24_close), - contentDescription = null, + contentDescription = "닫기", tint = NDGLTheme.colors.black600,
115-115: 파일 레벨@OptIn이 이미 선언되어 있어 중복됩니다.Line 1에
@file:OptIn(ExperimentalMaterial3Api::class)이 이미 적용되어 있으므로, Line 115의@OptIn은 제거해도 됩니다.core/ui/src/main/java/com/yapp/ndgl/core/ui/util/ReorderableList.kt (1)
182-199: 오토 스크롤에서updateItemIndex()가 호출되지 않습니다.스크롤 중에 새로운 아이템이 뷰포트에 들어와도 인덱스 업데이트가 발생하지 않아, 빠른 드래그 시 아이템 순서가 올바르게 변경되지 않을 수 있습니다. 스크롤 루프 내에서
updateItemIndex()를 호출하는 것을 고려해 주세요.♻️ 수정 제안
scrollOffset?.let { lazyListState.scrollBy(it) + updateItemIndex() delay(8) } ?: breakfeature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/component/TransportBottomSheet.kt (1)
148-153:onConfirm호출 후sheetState.hide()순서에 주의가 필요합니다.
onConfirm(selectedTransport)이 먼저 호출되면 상위에서 상태 변경으로 이 Composable이 composition에서 제거될 수 있고, 이 경우sheetState.hide()애니메이션이 실행되지 않습니다. 순서를 바꿔 먼저 시트를 숨긴 후 콜백을 호출하는 것이 안전합니다.♻️ 수정 제안
onClick = { coroutineScope.launch { - onConfirm(selectedTransport) sheetState.hide() + onConfirm(selectedTransport) } },feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailViewModel.kt (1)
559-571: 스텁createTransportSegment에서 사용자 맞춤 교통수단 정보가 재배치 시 유실됩니다.
recalculateTransportSegments가createTransportSegment스텁을 통해 모든 교통수단을 동일한 하드코딩 값으로 대체합니다. 사용자가 변경한 교통수단 선택이 장소 재배치 시 덮어씌워질 수 있습니다. API 연동 전까지는 불가피하지만, 연동 시 이 동작을 반드시 수정해야 합니다.TODO 항목 추적을 위한 이슈를 생성해 드릴까요?
feature/travel/src/main/java/com/yapp/ndgl/feature/travel/traveldetail/TravelDetailScreen.kt (1)
211-222:placesOffset = 3이 LazyColumn 아이템 구조에 강하게 결합되어 있습니다.아이템 순서가 변경되거나 새로운 아이템이 장소 목록 위에 추가되면 이 오프셋이 맞지 않게 됩니다. 현재로서는 동작하지만, 상수에 대한 설명 주석이 있으면 향후 유지보수에 도움이 됩니다.
| return remember { | ||
| ReorderableState( | ||
| scope = scope, | ||
| lazyListState = lazyListState, | ||
| onReorder = onReorder, | ||
| isReorderable = isReorderable, | ||
| ) | ||
| } |
There was a problem hiding this comment.
remember 블록에 키가 없어 isReorderable 변경 시 반영되지 않습니다.
rememberReorderableState의 isReorderable 파라미터가 변경되어도 remember {} 블록에 키가 없으므로 ReorderableState가 재생성되지 않습니다. onReorder는 rememberUpdatedState로 최신 list를 참조하지만, isReorderable은 최초 캡처된 값이 계속 사용됩니다.
♻️ 수정 제안
+ val currentIsReorderable by rememberUpdatedState(isReorderable)
+ val currentOnReorder: (Int, Int) -> Boolean = { from, to ->
+ currentList.reorder(from - offset, to - offset)
+ }
+
return remember {
ReorderableState(
scope = scope,
lazyListState = lazyListState,
- onReorder = onReorder,
- isReorderable = isReorderable,
+ onReorder = currentOnReorder,
+ isReorderable = { currentIsReorderable(it) },
)
}🤖 Prompt for AI Agents
In `@core/ui/src/main/java/com/yapp/ndgl/core/ui/util/ReorderableList.kt` around
lines 65 - 72, The remember block in rememberReorderableState captures
isReorderable once so subsequent changes are ignored; update the remember call
to include isReorderable as a key (e.g., remember(isReorderable) {
ReorderableState(...) }) so a new ReorderableState is created when isReorderable
changes; keep using rememberUpdatedState(for onReorder) as-is and reference the
rememberReorderableState function, ReorderableState class, and the isReorderable
parameter when making this change.
| // 아래로 드래그할 때 | ||
| private fun tryMoveDown(itemInfo: LazyListItemInfo) { | ||
| val target = lazyListState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == itemInfo.index + 1 } | ||
| if (target != null) { | ||
| if (onReorder(itemInfo.index, itemInfo.index + 1)) { | ||
| info = target | ||
| } | ||
| } else { | ||
| // 오토 스크롤 중 아이템이 화면에 보이지 않을 때 | ||
| val lastItem = lazyListState.layoutInfo.visibleItemsInfo.last() | ||
| if (onReorder(itemInfo.index, lastItem.index)) { | ||
| info = lazyListState.layoutInfo.visibleItemsInfo.last() | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
tryMoveDown에서 isReorderable 체크가 누락되었습니다.
tryMoveUp (Line 136)에서는 대상 아이템의 isReorderable(target.key)를 확인하지만, tryMoveDown에서는 이 검증이 빠져있습니다. 아래로 드래그 시 재배치 불가능한 아이템(헤더, 구분선 등)과 위치가 바뀔 수 있습니다.
🐛 수정 제안
private fun tryMoveDown(itemInfo: LazyListItemInfo) {
val target = lazyListState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == itemInfo.index + 1 }
if (target != null) {
- if (onReorder(itemInfo.index, itemInfo.index + 1)) {
+ if (isReorderable(target.key) && onReorder(itemInfo.index, itemInfo.index + 1)) {
info = target
}
} else {
// 오토 스크롤 중 아이템이 화면에 보이지 않을 때
val lastItem = lazyListState.layoutInfo.visibleItemsInfo.last()
- if (onReorder(itemInfo.index, lastItem.index)) {
+ if (isReorderable(lastItem.key) && onReorder(itemInfo.index, lastItem.index)) {
info = lazyListState.layoutInfo.visibleItemsInfo.last()
}
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // 아래로 드래그할 때 | |
| private fun tryMoveDown(itemInfo: LazyListItemInfo) { | |
| val target = lazyListState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == itemInfo.index + 1 } | |
| if (target != null) { | |
| if (onReorder(itemInfo.index, itemInfo.index + 1)) { | |
| info = target | |
| } | |
| } else { | |
| // 오토 스크롤 중 아이템이 화면에 보이지 않을 때 | |
| val lastItem = lazyListState.layoutInfo.visibleItemsInfo.last() | |
| if (onReorder(itemInfo.index, lastItem.index)) { | |
| info = lazyListState.layoutInfo.visibleItemsInfo.last() | |
| } | |
| } | |
| } | |
| // 아래로 드래그할 때 | |
| private fun tryMoveDown(itemInfo: LazyListItemInfo) { | |
| val target = lazyListState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == itemInfo.index + 1 } | |
| if (target != null) { | |
| if (isReorderable(target.key) && onReorder(itemInfo.index, itemInfo.index + 1)) { | |
| info = target | |
| } | |
| } else { | |
| // 오토 스크롤 중 아이템이 화면에 보이지 않을 때 | |
| val lastItem = lazyListState.layoutInfo.visibleItemsInfo.last() | |
| if (isReorderable(lastItem.key) && onReorder(itemInfo.index, lastItem.index)) { | |
| info = lazyListState.layoutInfo.visibleItemsInfo.last() | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In `@core/ui/src/main/java/com/yapp/ndgl/core/ui/util/ReorderableList.kt` around
lines 148 - 162, tryMoveDown is missing the same isReorderable check used in
tryMoveUp, so non-reorderable targets can be moved when dragging down; update
tryMoveDown to verify isReorderable(target.key) before calling onReorder in both
the visible-next-item branch and the else/autoscroll branch (mirror the guard in
tryMoveUp), and only set info when the target passes isReorderable and onReorder
returns true.
개요
디자인
내 여행 편집
영상
변경사항
추후 작업
테스트 체크 리스트
Summary by CodeRabbit
릴리스 노트
새로운 기능
개선 사항