Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bc500ca
[feat]: GroupMakeRoomRequest 삭제 (#150)
rbqks529 Oct 26, 2025
ae4a546
[feat]: Response 500에서도 다시 로그인 화면으로 이동하게 AuthInterceptor 수정 (#150)
rbqks529 Oct 26, 2025
3233a9e
[refactor]: drawVerticalScrollbar 코드 수정 (#150)
rbqks529 Oct 26, 2025
f10150d
[refactor]: 피드 생성과 모임 생성에서의 책 검색 화면에서 바텀시트 수정 (#150)
rbqks529 Oct 26, 2025
34f50ad
[refactor]: 기존 모임 생성 로직 수정 (#150)
rbqks529 Oct 26, 2025
fe231e0
[refactor]: 모임 인원 컴포넌트 수정 (#150)
rbqks529 Oct 26, 2025
fbfb443
[refactor]: 기존 모임 활동기간 컴포넌트 수정 (#150)
rbqks529 Oct 27, 2025
aee09b5
[refactor]: 모임 활동기간 picker 메세지 수정 (#150)
rbqks529 Oct 27, 2025
b0c1505
[refactor]: picker 부분 기타 수정 (#150)
rbqks529 Oct 27, 2025
1bedd40
[refactor]: DialogPopup 버튼 텍스트 수정 (#150)
rbqks529 Oct 28, 2025
39e96f4
[refactor]: stringResource 추가 (#150)
rbqks529 Oct 28, 2025
01f35db
[refactor]: viewModel에 dialog 보여주는 함수 추가 (#150)
rbqks529 Oct 28, 2025
18530c5
[refactor]: 완료를 누르면 dialog를 보여주고 확인 버튼에 기존 로직 이동 완료 (#150)
rbqks529 Oct 28, 2025
a52cb8d
[refactor]: padding 수정 (#150)
rbqks529 Oct 28, 2025
2ed3600
[chore]: 주석 및 줄 바꿈 수정 (#150)
rbqks529 Oct 28, 2025
9d41493
[refactor]: 날짜 범위 검증 구현 (#150)
rbqks529 Oct 28, 2025
c215909
[refactor]: Dialog 함수 사용으로 수정 (#150)
rbqks529 Oct 28, 2025
5c58a6d
[refactor]: pickerUtil 경곗값 로직 수정 (#150)
rbqks529 Oct 28, 2025
a4814ab
[refactor]: pickerUtil 경곗값 로직 수정 (#150)
rbqks529 Oct 28, 2025
75f23b0
[refactor]: viewModel 상태 수정 (#150)
rbqks529 Nov 11, 2025
8b215a5
[refactor]: Picker 컴포넌트 로직 1차 수정 (#150)
rbqks529 Nov 11, 2025
a106650
[refactor]: Picker 컴포넌트 로직 1차 수정 (#150)
rbqks529 Nov 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 13 additions & 6 deletions app/src/main/java/com/texthip/thip/ui/common/modal/DialogPopup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.texthip.thip.R
import com.texthip.thip.ui.common.buttons.ActionMediumButton
import com.texthip.thip.ui.theme.ThipTheme.colors
Expand All @@ -24,43 +27,47 @@ fun DialogPopup(
modifier: Modifier = Modifier,
title: String,
description: String,
confirmText: String = stringResource(R.string.yes),
cancelText: String = stringResource(R.string.no),
Comment on lines +30 to +31

This comment was marked as resolved.

onConfirm: () -> Unit,
onCancel: () -> Unit
) {
Column(
modifier = modifier
.size(width = 320.dp, height = 182.dp)
.width(320.dp)
.background(
color = colors.DarkGrey,
shape = RoundedCornerShape(12.dp)
)
.padding(20.dp),
verticalArrangement = Arrangement.SpaceBetween,
.padding(20.dp)
) {
Text(
text = title,
color = colors.White,
style = typography.smalltitle_m500_s18_h24,
)
Spacer(modifier = Modifier.height(20.dp))
Text(
text = description,
color = colors.White,
style = typography.copy_r400_s14,
lineHeight = 22.sp
)
Spacer(modifier = Modifier.height(20.dp))

Row(
horizontalArrangement = Arrangement.spacedBy(20.dp),
modifier = Modifier.fillMaxWidth()
) {
ActionMediumButton(
text = stringResource(R.string.no),
text = cancelText,
contentColor = colors.White,
backgroundColor = colors.Grey02,
modifier = Modifier.weight(1f),
onClick = onCancel,
)
ActionMediumButton(
text = stringResource(R.string.yes),
text = confirmText,
contentColor = colors.White,
backgroundColor = colors.Purple,
modifier = Modifier.weight(1f),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package com.texthip.thip.ui.common.modal

import androidx.compose.foundation.ScrollState
import androidx.compose.runtime.Composable
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp

Expand All @@ -26,6 +25,62 @@ fun Modifier.drawVerticalScrollbar(
val scrollProgress = scrollState.value.toFloat() / scrollState.maxValue
val scrollbarOffsetY = (size.height - scrollbarHeight) * scrollProgress

//전체 고정 바
drawRoundRect(
color = trackColor,
topLeft = Offset(x = size.width - trackThickness.toPx(), y = 0f),
size = Size(trackThickness.toPx(), size.height),
cornerRadius = CornerRadius(trackThickness.toPx() / 2)
)
//핸들 바
drawRoundRect(
color = thumbColor,
topLeft = Offset(x = size.width - thumbThickness.toPx(), y = scrollbarOffsetY),
size = Size(thumbThickness.toPx(), scrollbarHeight),
cornerRadius = CornerRadius(thumbThickness.toPx() / 2)
)
}
)

fun Modifier.drawVerticalScrollbar(
lazyListState: LazyListState,
trackThickness: Dp = 1.dp,
thumbThickness: Dp = 3.dp,
trackColor: Color = Color.White.copy(alpha = 0.2f),
thumbColor: Color = Color.White.copy(alpha = 0.8f),
): Modifier = this.then(
Modifier.drawBehind {
val layoutInfo = lazyListState.layoutInfo
val totalItemsCount = layoutInfo.totalItemsCount
val viewportHeight = layoutInfo.viewportEndOffset - layoutInfo.viewportStartOffset

// 스크롤이 필요 없으면 스크롤바 표시 안 함
if (totalItemsCount == 0) return@drawBehind
if (!lazyListState.canScrollForward && !lazyListState.canScrollBackward) return@drawBehind

val scrollbarHeight = size.height / 8f

// 전체 컨텐츠 높이 추정
val averageItemHeight = if (layoutInfo.visibleItemsInfo.isNotEmpty()) {
layoutInfo.visibleItemsInfo.map { it.size }.average().toFloat()
} else {
100f
}
Comment on lines +64 to +68
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

평균 아이템 높이 계산이 이질적인 리스트에서 부정확할 수 있습니다.

현재 구현은 표시되는 아이템들의 평균 높이를 사용하여 전체 컨텐츠 높이를 추정합니다. 아이템 크기가 크게 다를 경우 스크롤바 위치가 부정확해질 수 있습니다. 또한 fallback 값 100f는 임의로 선택된 값입니다.

이 컴포넌트가 크기가 균일한 아이템 리스트에서만 사용되는지 확인하세요:


🏁 Script executed:

#!/bin/bash
# drawVerticalScrollbar(LazyListState) 사용처 확인
rg -nP --type=kotlin -C10 'drawVerticalScrollbar\s*\(\s*\w+\s*:\s*LazyListState'

Length of output: 0


검증을 위해 더 광범위한 코드베이스 검색이 필요합니다.


---

🏁 Script executed:

```shell
#!/bin/bash
# drawVerticalScrollbar 함수 정의 찾기
rg -nP --type=kotlin 'fun\s+drawVerticalScrollbar' -A 15

Length of output: 0


🏁 Script executed:

#!/bin/bash
# drawVerticalScrollbar 함수의 모든 호출처 검색
rg -nP --type=kotlin 'drawVerticalScrollbar\s*\(' -B 5 -A 2

Length of output: 3398


🏁 Script executed:

#!/bin/bash
# ScrollbarUtil.kt 파일 전체 내용 확인
fd -t f 'ScrollbarUtil\.kt' --exec cat {}

Length of output: 3756


추가 검증을 위해 실제 사용 사례를 확인하겠습니다.


---

🏁 Script executed:

```shell
#!/bin/bash
# GroupBookListWithScrollbar.kt 파일 내용 확인
fd -t f 'GroupBookListWithScrollbar\.kt' --exec cat {}

Length of output: 3464


🏁 Script executed:

#!/bin/bash
# GroupBookListWithScrollbar의 컴포지션 호출처 검색
rg -nP --type=kotlin 'GroupBookListWithScrollbar\s*\(' -B 3 -A 3

Length of output: 4887


LazyListState 버전 스크롤바 위치 계산을 개선해야 합니다.

현재 구현(drawVerticalScrollbar(lazyListState))은 visibleItemsInfo에 표시되는 아이템들의 평균 높이만 사용하여 전체 컨텐츠 높이를 추정합니다. 실제 사용처인 GroupBookListWithScrollbar에서 각 아이템이 CardBookSearch(가변 높이) + Spacers(25.dp 고정)로 구성되어 있기 때문에, 비가시 영역의 아이템들이 다른 높이를 가질 경우 스크롤바 위치가 정확하지 않을 수 있습니다. 또한 fallback 값 100f는 임의적입니다.

더 정확한 스크롤 위치 계산을 위해 다음을 고려해야 합니다:

  • 전체 아이템의 높이 정보를 누적하여 추적하거나
  • 평균값을 더 보수적으로 계산하거나
  • 스크롤 진행률 계산 로직을 재검토
🤖 Prompt for AI Agents
app/src/main/java/com/texthip/thip/ui/common/modal/ScrollbarUtil.kt around lines
64-68: the scrollbar current code estimates total content height using only the
average of visibleItemsInfo (with a hardcoded 100f fallback), which yields
inaccurate scroll positions for variable-height items; fix it by replacing the
arbitrary fallback and naive average with a conservative estimation using
measured data — compute the sum of the heights of visibleItemsInfo, derive an
average from those measured items (only if count>0), then estimate unseen items
height as average * (totalItemsCount - visibleItemsInfo.count), and use measured
sum + estimated unseen height as total content height; alternatively implement a
per-item height cache (update via onGloballyPositioned) and use the exact summed
heights when available to compute precise scrollbar position.

val estimatedTotalHeight = averageItemHeight * totalItemsCount

// 스크롤 진행률 계산
val firstVisibleIndex = lazyListState.firstVisibleItemIndex.toFloat()
val firstVisibleOffset = lazyListState.firstVisibleItemScrollOffset.toFloat()

val scrollProgress = if (estimatedTotalHeight > 0) {
((firstVisibleIndex * averageItemHeight + firstVisibleOffset) / estimatedTotalHeight)
.coerceIn(0f, 1f)
} else {
0f
}

val scrollbarOffsetY = (size.height - scrollbarHeight) * scrollProgress

//전체 고정 바
drawRoundRect(
color = trackColor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
Expand All @@ -36,7 +36,7 @@ fun GroupBookListWithScrollbar(
onLoadMore: () -> Unit = {}
) {
val listState = rememberLazyListState()

val shouldLoadMore = remember {
derivedStateOf {
val layoutInfo = listState.layoutInfo
Expand All @@ -48,7 +48,7 @@ fun GroupBookListWithScrollbar(
}

LaunchedEffect(shouldLoadMore.value, hasMore, isLoadingMore) {
if (shouldLoadMore.value && hasMore && !isLoadingMore && books.isNotEmpty()) {
if (shouldLoadMore.value && hasMore && !isLoadingMore) {
onLoadMore()
}
}
Expand All @@ -57,7 +57,8 @@ fun GroupBookListWithScrollbar(
state = listState,
modifier = Modifier
.fillMaxWidth()
.drawVerticalScrollbar(rememberScrollState())
.fillMaxHeight()
.drawVerticalScrollbar(listState)
) {
items(books) { book ->
CardBookSearch(
Expand All @@ -75,7 +76,7 @@ fun GroupBookListWithScrollbar(
)
Spacer(modifier = Modifier.height(12.dp))
}

if (isLoadingMore) {
item {
Box(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import com.texthip.thip.ui.group.makeroom.mock.BookData
import com.texthip.thip.ui.group.makeroom.mock.dummyGroupBooks
import com.texthip.thip.ui.group.makeroom.mock.dummySavedBooks
import com.texthip.thip.ui.theme.ThipTheme
import com.texthip.thip.ui.theme.ThipTheme.colors
import com.texthip.thip.utils.rooms.advancedImePadding

@Composable
Expand All @@ -49,16 +50,22 @@ fun GroupBookSearchBottomSheet(
onSearch: (String) -> Unit = {},
onLoadMoreSaved: () -> Unit = {},
onLoadMoreGroup: () -> Unit = {},
onLoadMoreSearch: () -> Unit = {}
onLoadMoreSearch: () -> Unit = {},
showGroupBooksTab: Boolean = true
) {
var selectedTab by rememberSaveable { mutableIntStateOf(0) }
val tabs = listOf(
stringResource(R.string.group_saved_book), stringResource(R.string.group_book)
)
val tabs = if (showGroupBooksTab) {
listOf(
stringResource(R.string.group_saved_book),
stringResource(R.string.group_book)
)
} else {
listOf(stringResource(R.string.group_saved_book))
}
Comment on lines +57 to +64

This comment was marked as off-topic.


var searchText by rememberSaveable { mutableStateOf("") }

val currentBooks = if (selectedTab == 0) savedBooks else groupBooks
val currentBooks = if (showGroupBooksTab && selectedTab == 1) groupBooks else savedBooks

// 검색어가 있으면 검색 결과 사용, 없으면 탭별 도서 목록 사용
val displayBooks = if (searchText.isNotEmpty()) {
Expand Down Expand Up @@ -115,12 +122,18 @@ fun GroupBookSearchBottomSheet(
.align(Alignment.CenterHorizontally),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
CircularProgressIndicator(
color = colors.White
)
}
}

else -> {
Column(Modifier.padding(horizontal = 20.dp)) {
Column(
Modifier
.weight(1f)
.padding(horizontal = 20.dp)
) {
when {
searchText.isNotEmpty() -> {
GroupBookListWithScrollbar(
Expand All @@ -131,7 +144,8 @@ fun GroupBookSearchBottomSheet(
onLoadMore = onLoadMoreSearch
)
}
selectedTab == 0 -> {

!showGroupBooksTab || selectedTab == 0 -> {
GroupBookListWithScrollbar(
books = displayBooks,
onBookClick = onBookSelect,
Expand All @@ -140,6 +154,7 @@ fun GroupBookSearchBottomSheet(
onLoadMore = onLoadMoreSaved
)
}

else -> {
GroupBookListWithScrollbar(
books = displayBooks,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -39,13 +38,13 @@ fun GroupDatePicker(
val month = selectedDate.monthValue
val day = selectedDate.dayOfMonth

// 유효한 범위 계산 - 날짜 변경 시 안정성을 위해 remember 사용
val years = remember(minDate.year, maxDate.year) {
(minDate.year..maxDate.year).toList()
// 유효한 범위 계산 - 단순하게 전체 범위 사용
val years = remember(minDate.year, maxDate.year) {
(minDate.year..maxDate.year).toList()
}
val months = remember { (1..12).toList() }
val days = remember(year, month) {
(1..LocalDate.of(year, month, 1).lengthOfMonth()).toList()
val days = remember(year, month) {
(1..LocalDate.of(year, month, 1).lengthOfMonth()).toList()
}

Row(
Expand All @@ -62,7 +61,8 @@ fun GroupDatePicker(
val newDate = try {
LocalDate.of(newYear, month, day)
} catch (e: Exception) {
LocalDate.of(newYear, month, 1)
val lastDay = LocalDate.of(newYear, month, 1).lengthOfMonth()
LocalDate.of(newYear, month, lastDay)
}
onDateSelected(newDate)
},
Expand All @@ -88,7 +88,8 @@ fun GroupDatePicker(
val newDate = try {
LocalDate.of(year, newMonth, day)
} catch (e: Exception) {
LocalDate.of(year, newMonth, 1)
val lastDay = LocalDate.of(year, newMonth, 1).lengthOfMonth()
LocalDate.of(year, newMonth, lastDay)
}
onDateSelected(newDate)
},
Expand All @@ -109,10 +110,9 @@ fun GroupDatePicker(
GroupWheelPicker(
modifier = Modifier.width(32.dp),
items = days,
selectedItem = day.coerceAtMost(days.max()),
selectedItem = day.coerceAtMost(days.maxOrNull() ?: 1),
onItemSelected = { newDay ->
val newDate = LocalDate.of(year, month, newDay)
onDateSelected(newDate)
onDateSelected(LocalDate.of(year, month, newDay))
},
displayText = { it.toString() }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fun GroupMemberLimitPicker(
selectedCount: Int = 30,
onCountSelected: (Int) -> Unit = { }
) {
val memberCounts = remember { (1..30).toList() }
val memberCounts = remember { (2..30).toList() }

Column(
modifier = modifier.fillMaxWidth()
Expand Down
Loading