From ba4133408359be32898859727c141d07d806ecb0 Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Thu, 4 Sep 2025 17:50:27 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[refactor]:=20=ED=94=BC=EB=93=9C=20?= =?UTF-8?q?=EB=8D=94=EB=B3=B4=EA=B8=B0=20=EC=9C=84=EC=B9=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/feed/component/MyFeedCard.kt | 32 +++++++++++++++---- .../thip/ui/mypage/component/SavedFeedCard.kt | 31 +++++++++++++++--- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt b/app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt index 9685f3f6..e4928352 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt @@ -44,8 +44,29 @@ fun MyFeedCard( onBookClick: () -> Unit = {} ) { val hasImages = feedItem.imageUrls.isNotEmpty() - val maxLines = if (hasImages) 3 else 8 + val maxTextLines = if (hasImages) 3 else 8 var isTextTruncated by remember { mutableStateOf(false) } + + // 실제 텍스트 줄 수를 기준으로 표시할 텍스트 계산 + val processedText = remember(feedItem.content) { + val lines = feedItem.content.split("\n") + val nonEmptyLines = mutableListOf() // 실제 텍스트가 있는 줄의 인덱스 + + lines.forEachIndexed { index, line -> + if (line.trim().isNotEmpty()) { + nonEmptyLines.add(index) + } + } + + if (nonEmptyLines.size <= maxTextLines) { + // 실제 텍스트 줄이 제한보다 적으면 전체 표시 + feedItem.content + } else { + // 실제 텍스트 줄이 제한을 초과하면, maxTextLines 번째 텍스트 줄까지만 표시 + val lastAllowedLineIndex = nonEmptyLines[maxTextLines - 1] + lines.take(lastAllowedLineIndex + 1).joinToString("\n") + } + } Column( modifier = modifier @@ -99,20 +120,19 @@ fun MyFeedCard( .clickable { onContentClick() } ) { Text( - text = feedItem.content, + text = processedText, style = typography.feedcopy_r400_s14_h20, color = colors.White, - maxLines = maxLines, modifier = Modifier .fillMaxWidth() .padding(top = 16.dp), - // 3. onTextLayout 콜백을 사용하여 텍스트가 잘렸는지 확인 onTextLayout = { textLayoutResult -> - isTextTruncated = textLayoutResult.hasVisualOverflow + // 원본 텍스트와 처리된 텍스트가 다르면 잘렸다고 판단 + isTextTruncated = processedText != feedItem.content } ) - // 4. 텍스트가 잘렸을 경우에만 "...더보기" 이미지를 우측 하단에 표시 + // 텍스트가 잘린 경우에만 "...더보기" 표시 if (isTextTruncated) { Image( painter = painterResource(id = R.drawable.ic_text_more), diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt b/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt index 0d69fba8..d19bfc57 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt @@ -48,8 +48,29 @@ fun SavedFeedCard( onProfileClick: () -> Unit = {} ) { val hasImages = feedItem.imageUrls.isNotEmpty() - val maxLines = if (hasImages) 3 else 8 + val maxTextLines = if (hasImages) 3 else 8 var isTextTruncated by remember { mutableStateOf(false) } + + // 실제 텍스트 줄 수를 기준으로 표시할 텍스트 계산 + val processedText = remember(feedItem.content) { + val lines = feedItem.content.split("\n") + val nonEmptyLines = mutableListOf() // 실제 텍스트가 있는 줄의 인덱스 + + lines.forEachIndexed { index, line -> + if (line.trim().isNotEmpty()) { + nonEmptyLines.add(index) + } + } + + if (nonEmptyLines.size <= maxTextLines) { + // 실제 텍스트 줄이 제한보다 적으면 전체 표시 + feedItem.content + } else { + // 실제 텍스트 줄이 제한을 초과하면, maxTextLines 번째 텍스트 줄까지만 표시 + val lastAllowedLineIndex = nonEmptyLines[maxTextLines - 1] + lines.take(lastAllowedLineIndex + 1).joinToString("\n") + } + } Column( modifier = modifier @@ -85,15 +106,17 @@ fun SavedFeedCard( ) { Box { Text( - text = feedItem.content, + text = processedText, style = typography.feedcopy_r400_s14_h20, color = colors.White, - maxLines = maxLines, modifier = Modifier.fillMaxWidth(), onTextLayout = { textLayoutResult -> - isTextTruncated = textLayoutResult.hasVisualOverflow + // 원본 텍스트와 처리된 텍스트가 다르면 잘렸다고 판단 + isTextTruncated = processedText != feedItem.content } ) + + // 텍스트가 잘린 경우에만 "...더보기" 표시 if (isTextTruncated) { Image( painter = painterResource(id = R.drawable.ic_text_more), From e2ac9d9989a2584b4de4ab8c217ee0fc13dd78ee Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Thu, 4 Sep 2025 18:04:39 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[refactor]:=20=EA=B3=A0=EA=B0=9D=EC=84=BC?= =?UTF-8?q?=ED=84=B0=20=EB=A7=81=ED=81=AC=20=EC=88=98=EC=A0=95=20(#127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt index 4b884548..b60692a3 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt @@ -42,7 +42,7 @@ import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography import com.texthip.thip.utils.color.hexToColor -private const val URL_CUSTOMER_SERVICE = "https://slashpage.com/thip/xjqy1g2vw7vejm6vd54z" +private const val URL_CUSTOMER_SERVICE = "https://slashpage.com/thip/dk58wg2e6yy3zmnqevxz" private const val URL_NOTICE = "https://slashpage.com/thip/7vgjr4m1nynpy2dwpy86" private const val URL_TERMS_OF_USE = "https://slashpage.com/thip/7916x82r8y74n24kpyg3" private const val URL_GUIDE = "https://slashpage.com/thip/ywk9j72989p6rmgpqvnd" From 14d345e1fc301c3cbedf59e2e7106c3abb8862bc Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Thu, 4 Sep 2025 18:40:24 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[refactor]:=20=EC=9E=A5=EB=A5=B4=20?= =?UTF-8?q?=EC=B9=A9=20UI=20=EA=B9=A8=EC=A7=90=20=EC=88=98=EC=A0=95=20(#12?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/buttons/GenreChipRow.kt | 120 +++++++++++++++--- .../component/GroupDeadlineRoomSection.kt | 6 +- 2 files changed, 103 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/GenreChipRow.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/GenreChipRow.kt index 9619852b..47af29a7 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/GenreChipRow.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/GenreChipRow.kt @@ -1,18 +1,24 @@ package com.texthip.thip.ui.common.buttons +import android.annotation.SuppressLint 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.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.ui.theme.ThipTheme +@SuppressLint("ConfigurationScreenWidthHeight") @Composable fun GenreChipRow( modifier: Modifier = Modifier.width(4.dp), @@ -21,35 +27,95 @@ fun GenreChipRow( onSelect: (Int) -> Unit, horizontalArrangement: Arrangement.Horizontal = Arrangement.Center ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = horizontalArrangement - ) { - genres.forEachIndexed { idx, genre -> - OptionChipButton( - modifier = Modifier - .clip(RoundedCornerShape(20.dp)), // 버튼 모양에 맞게 클리핑 - text = genre, - isFilled = true, - isSelected = selectedIndex == idx, - onClick = { - if (selectedIndex == idx) { - onSelect(-1) - } else { - onSelect(idx) + val configuration = LocalConfiguration.current + val screenWidthDp = configuration.screenWidthDp + + if (screenWidthDp < 360) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth() + ) { + Row( + horizontalArrangement = Arrangement.Center + ) { + genres.take(3).forEachIndexed { idx, genre -> + OptionChipButton( + modifier = Modifier + .clip(RoundedCornerShape(20.dp)), + text = genre, + isFilled = true, + isSelected = selectedIndex == idx, + onClick = { + if (selectedIndex == idx) { + onSelect(-1) + } else { + onSelect(idx) + } + } + ) + if (idx < 2) { + Spacer(modifier = modifier) + } + } + } + Spacer(modifier = Modifier.height(8.dp)) + + Row( + horizontalArrangement = Arrangement.Center + ) { + genres.drop(3).forEachIndexed { relativeIdx, genre -> + val idx = relativeIdx + 3 + OptionChipButton( + modifier = Modifier + .clip(RoundedCornerShape(20.dp)), + text = genre, + isFilled = true, + isSelected = selectedIndex == idx, + onClick = { + if (selectedIndex == idx) { + onSelect(-1) + } else { + onSelect(idx) + } + } + ) + if (relativeIdx < genres.drop(3).size - 1) { + Spacer(modifier = modifier) } } - ) - if (idx < genres.size - 1) { - Spacer(modifier = modifier) + } + } + } else { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = horizontalArrangement + ) { + genres.forEachIndexed { idx, genre -> + OptionChipButton( + modifier = Modifier + .clip(RoundedCornerShape(20.dp)), + text = genre, + isFilled = true, + isSelected = selectedIndex == idx, + onClick = { + if (selectedIndex == idx) { + onSelect(-1) + } else { + onSelect(idx) + } + } + ) + if (idx < genres.size - 1) { + Spacer(modifier = modifier) + } } } } } -@Preview() +@Preview(name = "Normal Screen (>=360dp)", widthDp = 400) @Composable -fun PreviewGenreChipRow() { +fun PreviewGenreChipRowNormal() { ThipTheme { GenreChipRow( genres = listOf("문학", "과학·IT", "사회과학", "인문학", "예술"), @@ -58,3 +124,15 @@ fun PreviewGenreChipRow() { ) } } + +@Preview(name = "Small Screen (<360dp)", widthDp = 320) +@Composable +fun PreviewGenreChipRowSmall() { + ThipTheme { + GenreChipRow( + genres = listOf("문학", "과학·IT", "사회과학", "인문학", "예술"), + selectedIndex = 2, + onSelect = {} + ) + } +} diff --git a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt index 2442587e..26d46fea 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt @@ -113,7 +113,7 @@ fun GroupRoomDeadlineSection( ), shape = RoundedCornerShape(14.dp) ) - .padding(vertical = 20.dp, horizontal = 20.dp) + .padding(vertical = 20.dp) ) { Column( horizontalAlignment = Alignment.CenterHorizontally @@ -121,7 +121,8 @@ fun GroupRoomDeadlineSection( Text( text = sectionTitle, style = typography.title_b700_s20_h24, - color = colors.White + color = colors.White, + modifier = Modifier.padding(horizontal = 20.dp) ) Spacer(Modifier.height(40.dp)) @@ -137,6 +138,7 @@ fun GroupRoomDeadlineSection( modifier = Modifier .fillMaxWidth() .height(584.dp) + .padding(horizontal = 20.dp) ) { when { // 에러 상태 From c6bef994ae0b10e98ae2e7f04b4328e95898d7dd Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Thu, 4 Sep 2025 20:54:12 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[refactor]:=20=ED=94=BC=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EB=B0=8F,=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=9D=98=20?= =?UTF-8?q?=EC=B1=85=20=EC=84=A0=ED=83=9D=20=EB=A1=9C=EC=A7=81=20=EB=B0=8F?= =?UTF-8?q?=20UI=20=EC=88=98=EC=A0=95=20(#127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/cards/CardInputBook.kt | 54 ++++++++++------ .../ui/feed/viewmodel/FeedWriteViewModel.kt | 15 +++++ .../makeroom/component/GroupSelectBook.kt | 61 +++---------------- .../navigator/navigations/FeedNavigation.kt | 12 ++-- .../navigator/navigations/SearchNavigation.kt | 3 - .../search/screen/SearchBookDetailScreen.kt | 1 - 6 files changed, 66 insertions(+), 80 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardInputBook.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardInputBook.kt index bfffacff..b154ee90 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardInputBook.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardInputBook.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage import com.texthip.thip.R import com.texthip.thip.ui.common.buttons.OutlinedButton import com.texthip.thip.ui.theme.ThipTheme.colors @@ -34,7 +35,9 @@ fun CardInputBook( modifier: Modifier = Modifier, title: String, author: String, - imageRes: Int? = R.drawable.img_book_cover_sample, // 기본 이미지 리소스 + imageUrl: String? = null, // 이미지 URL (AsyncImage 사용) + imageRes: Int? = R.drawable.img_book_cover_sample, // 기본 이미지 리소스 (fallback) + showChangeButton: Boolean = true, // 변경 버튼 표시 여부 onChangeClick: () -> Unit = {} ) { Row( @@ -47,14 +50,26 @@ fun CardInputBook( modifier = Modifier .size(width = 60.dp, height = 80.dp) ) { - - imageRes?.let { - Image( - painter = painterResource(id = it), + if (!imageUrl.isNullOrBlank()) { + // URL 이미지가 있는 경우 AsyncImage 사용 + AsyncImage( + model = imageUrl, contentDescription = null, modifier = Modifier.fillMaxSize(), - contentScale = ContentScale.Crop + contentScale = ContentScale.Crop, + fallback = imageRes?.let { painterResource(id = it) }, + error = imageRes?.let { painterResource(id = it) } ) + } else { + // URL이 없는 경우 기본 이미지 리소스 사용 + imageRes?.let { + Image( + painter = painterResource(id = it), + contentDescription = null, + modifier = Modifier.fillMaxSize(), + contentScale = ContentScale.Crop + ) + } } } @@ -76,20 +91,24 @@ fun CardInputBook( Text( text = stringResource(R.string.card_input_author, author), style = typography.view_m500_s12_h20, - color = colors.Grey01 + color = colors.Grey01, + maxLines = 1, + overflow = TextOverflow.Ellipsis ) } - // 텍스트 정보와 버튼 사이 19dp 고정 간격 - Spacer(modifier = Modifier.width(19.dp)) - OutlinedButton( - modifier = Modifier - .size(width = 49.dp, height = 33.dp) - .align(Alignment.Bottom), - text = stringResource(R.string.change), - textStyle = typography.view_m500_s14, - onClick = onChangeClick - ) + if (showChangeButton) { + Spacer(modifier = Modifier.width(19.dp)) + + OutlinedButton( + modifier = Modifier + .size(width = 49.dp, height = 33.dp) + .align(Alignment.Bottom), + text = stringResource(R.string.change), + textStyle = typography.view_m500_s14, + onClick = onChangeClick + ) + } } } @@ -105,6 +124,7 @@ fun CardInputBookPreview() { CardInputBook( title = "책제목입니다.책제목입니다.책제목입니다.책제목입니다.책제목입니다.", author = "리처드 도킨스", + imageUrl = null, // 기본 이미지 사용 onChangeClick = {} ) } diff --git a/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/FeedWriteViewModel.kt b/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/FeedWriteViewModel.kt index a13dc70b..5844f7a5 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/FeedWriteViewModel.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/FeedWriteViewModel.kt @@ -189,6 +189,21 @@ class FeedWriteViewModel @Inject constructor( updateState { it.copy(selectedBook = book) } } + fun setPreselectedBookForFeed(isbn: String, bookTitle: String, bookAuthor: String, bookImageUrl: String) { + val preselectedBook = BookData( + title = bookTitle, + imageUrl = bookImageUrl, + author = bookAuthor, + isbn = isbn + ) + updateState { + it.copy( + selectedBook = preselectedBook, + isBookPreselected = true + ) + } + } + fun toggleBookSearchSheet(show: Boolean) { updateState { it.copy(showBookSearchSheet = show) } if (show) { diff --git a/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupSelectBook.kt b/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupSelectBook.kt index dea635ba..8e914a88 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupSelectBook.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupSelectBook.kt @@ -7,7 +7,6 @@ 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.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -18,14 +17,12 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage import com.texthip.thip.R -import com.texthip.thip.ui.common.buttons.OptionChipButton +import com.texthip.thip.ui.common.cards.CardInputBook import com.texthip.thip.ui.group.makeroom.mock.BookData import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors @@ -78,54 +75,14 @@ fun GroupSelectBook( ) } } else { - // 선택된 상태: 커버, 제목, 저자, 변경 버튼 - Row( - modifier = Modifier - .fillMaxWidth() - .height(80.dp), - verticalAlignment = Alignment.Bottom - ) { - AsyncImage( - model = selectedBook.imageUrl ?: R.drawable.img_book_cover_sample, - contentDescription = selectedBook.title, - modifier = Modifier - .height(80.dp) - .width(60.dp), - contentScale = ContentScale.Crop - ) - Spacer(modifier = Modifier.width(12.dp)) - Column( - modifier = Modifier - .fillMaxSize() - .weight(1f), - verticalArrangement = Arrangement.Top - ) { - Text( - text = selectedBook.title, - color = colors.White, - style = typography.menu_sb600_s14_h24 - ) - Spacer(modifier = Modifier.height(8.dp)) - selectedBook.author?.let { - Text( - text = stringResource( - R.string.group_selected_book_author, - selectedBook.author - ), - color = colors.Grey01, - style = typography.info_r400_s12, - maxLines = 1 - ) - } - } - if (!isBookPreselected) { - OptionChipButton( - text = stringResource(R.string.change), - onClick = onChangeBookClick, - isSelected = false - ) - } - } + CardInputBook( + title = selectedBook.title, + author = selectedBook.author ?: "", + imageUrl = selectedBook.imageUrl, + imageRes = R.drawable.img_book_cover_sample, + showChangeButton = !isBookPreselected, // 사전 선택된 책인 경우 변경 버튼 숨김 + onChangeClick = onChangeBookClick + ) } } } diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt index 20daf602..c5a2964f 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt @@ -151,13 +151,11 @@ fun NavGraphBuilder.feedNavigation( route.bookAuthor != null ) { // 새 글 작성 모드: 책 정보만 있는 경우 (책 상세 페이지에서 온 경우) - viewModel.selectBook( - com.texthip.thip.ui.group.makeroom.mock.BookData( - title = route.bookTitle, - imageUrl = route.bookImageUrl ?: "", - author = route.bookAuthor, - isbn = route.isbn - ) + viewModel.setPreselectedBookForFeed( + isbn = route.isbn, + bookTitle = route.bookTitle, + bookAuthor = route.bookAuthor, + bookImageUrl = route.bookImageUrl ?: "" ) } } diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/SearchNavigation.kt b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/SearchNavigation.kt index 809dc468..6469c7cf 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/SearchNavigation.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/SearchNavigation.kt @@ -38,9 +38,6 @@ fun NavGraphBuilder.searchNavigation(navController: NavHostController) { onLeftClick = { navController.popBackStack() }, - onRightClick = { - // TODO: 우측 버튼 액션 구현 - }, onRecruitingGroupClick = { navController.navigateToBookGroup(isbn) }, diff --git a/app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookDetailScreen.kt b/app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookDetailScreen.kt index 1eb5e2c3..86c2d61a 100644 --- a/app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookDetailScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookDetailScreen.kt @@ -68,7 +68,6 @@ fun SearchBookDetailScreen( modifier: Modifier = Modifier, isbn: String, onLeftClick: () -> Unit = {}, - onRightClick: () -> Unit = {}, onRecruitingGroupClick: () -> Unit = {}, onWriteFeedClick: (BookDetailResponse) -> Unit = {}, onFeedClick: (Long) -> Unit = {}, From 6e9195b8d047adc3928676f90dfbbd12fca18877 Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Thu, 4 Sep 2025 21:04:22 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[refactor]:=20=ED=94=BC=EB=93=9C=20?= =?UTF-8?q?=EC=9E=90=EC=84=B8=ED=9E=88=EB=B3=B4=EA=B8=B0=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=20=EA=B9=A8=EC=A7=90=20=EC=88=98=EC=A0=95=20(#127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../texthip/thip/ui/feed/screen/FeedCommentScreen.kt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt index c14322f8..6bfeca4e 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt @@ -9,6 +9,8 @@ import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -145,6 +147,7 @@ fun FeedCommentScreen( ) } +@OptIn(ExperimentalLayoutApi::class) @Composable private fun FeedCommentContent( modifier: Modifier = Modifier, @@ -330,11 +333,13 @@ private fun FeedCommentContent( } } if (feedDetail.tagList.isNotEmpty()) { - Row( - Modifier + FlowRow( + modifier = Modifier .fillMaxWidth() .padding(bottom = 16.dp, start = 20.dp, end = 20.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + maxLines = 2 // 최대 2줄로 제한 ) { feedDetail.tagList.forEach { tag -> OptionChipButton( From cf40ad05a92b3e7b906bc1e21589d1623558e41e Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Thu, 4 Sep 2025 22:56:41 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[refactor]:=20PR=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20(#127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/texthip/thip/ui/feed/component/MyFeedCard.kt | 10 ++++------ .../group/makeroom/viewmodel/GroupMakeRoomViewModel.kt | 9 --------- .../texthip/thip/ui/mypage/component/SavedFeedCard.kt | 10 ++++------ 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt b/app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt index e4928352..c8fe5980 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt @@ -45,10 +45,9 @@ fun MyFeedCard( ) { val hasImages = feedItem.imageUrls.isNotEmpty() val maxTextLines = if (hasImages) 3 else 8 - var isTextTruncated by remember { mutableStateOf(false) } // 실제 텍스트 줄 수를 기준으로 표시할 텍스트 계산 - val processedText = remember(feedItem.content) { + val processedText = remember(feedItem.content, hasImages) { val lines = feedItem.content.split("\n") val nonEmptyLines = mutableListOf() // 실제 텍스트가 있는 줄의 인덱스 @@ -67,6 +66,9 @@ fun MyFeedCard( lines.take(lastAllowedLineIndex + 1).joinToString("\n") } } + + // 잘림 여부는 파생 값으로 계산 + val isTextTruncated = processedText != feedItem.content Column( modifier = modifier @@ -126,10 +128,6 @@ fun MyFeedCard( modifier = Modifier .fillMaxWidth() .padding(top = 16.dp), - onTextLayout = { textLayoutResult -> - // 원본 텍스트와 처리된 텍스트가 다르면 잘렸다고 판단 - isTextTruncated = processedText != feedItem.content - } ) // 텍스트가 잘린 경우에만 "...더보기" 표시 diff --git a/app/src/main/java/com/texthip/thip/ui/group/makeroom/viewmodel/GroupMakeRoomViewModel.kt b/app/src/main/java/com/texthip/thip/ui/group/makeroom/viewmodel/GroupMakeRoomViewModel.kt index cfd030ce..9c1320e4 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/makeroom/viewmodel/GroupMakeRoomViewModel.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/makeroom/viewmodel/GroupMakeRoomViewModel.kt @@ -210,15 +210,6 @@ class GroupMakeRoomViewModel @Inject constructor( ) } - private fun BookUserSaveList.toBookDataFromSaved(): BookData { - return BookData( - title = this.bookTitle, - imageUrl = this.bookImageUrl, - author = this.authorName, - isbn = this.isbn - ) - } - private fun BookSearchItem.toBookData(): BookData { return BookData( title = this.title, diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt b/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt index d19bfc57..88e1a283 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt @@ -49,10 +49,9 @@ fun SavedFeedCard( ) { val hasImages = feedItem.imageUrls.isNotEmpty() val maxTextLines = if (hasImages) 3 else 8 - var isTextTruncated by remember { mutableStateOf(false) } // 실제 텍스트 줄 수를 기준으로 표시할 텍스트 계산 - val processedText = remember(feedItem.content) { + val processedText = remember(feedItem.content, hasImages) { val lines = feedItem.content.split("\n") val nonEmptyLines = mutableListOf() // 실제 텍스트가 있는 줄의 인덱스 @@ -71,6 +70,9 @@ fun SavedFeedCard( lines.take(lastAllowedLineIndex + 1).joinToString("\n") } } + + // 잘림 여부는 파생 값으로 계산 + val isTextTruncated = processedText != feedItem.content Column( modifier = modifier @@ -110,10 +112,6 @@ fun SavedFeedCard( style = typography.feedcopy_r400_s14_h20, color = colors.White, modifier = Modifier.fillMaxWidth(), - onTextLayout = { textLayoutResult -> - // 원본 텍스트와 처리된 텍스트가 다르면 잘렸다고 판단 - isTextTruncated = processedText != feedItem.content - } ) // 텍스트가 잘린 경우에만 "...더보기" 표시