diff --git a/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsPlayingResponse.kt b/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsPlayingResponse.kt index f05496c6..1931e0be 100644 --- a/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsPlayingResponse.kt +++ b/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsPlayingResponse.kt @@ -20,7 +20,7 @@ data class RoomsPlayingResponse( val bookTitle: String, val authorName: String, val currentPage: Int, - val userPercentage: Double, + val userPercentage: Int, val currentVotes: List ) diff --git a/app/src/main/java/com/texthip/thip/data/model/users/response/OthersFollowersResponse.kt b/app/src/main/java/com/texthip/thip/data/model/users/response/OthersFollowersResponse.kt index 71728031..25c21ffa 100644 --- a/app/src/main/java/com/texthip/thip/data/model/users/response/OthersFollowersResponse.kt +++ b/app/src/main/java/com/texthip/thip/data/model/users/response/OthersFollowersResponse.kt @@ -18,5 +18,6 @@ data class FollowerList( @SerializedName("profileImageUrl") val profileImageUrl: String?, @SerializedName("aliasName") val aliasName: String, @SerializedName("aliasColor") val aliasColor: String, - @SerializedName("followerCount") val followerCount: Int + @SerializedName("followerCount") val followerCount: Int, + @SerializedName("isMyself") val isMyself: Boolean ) \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/common/CommentActionMode.kt b/app/src/main/java/com/texthip/thip/ui/common/CommentActionMode.kt deleted file mode 100644 index 0e39238c..00000000 --- a/app/src/main/java/com/texthip/thip/ui/common/CommentActionMode.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.texthip.thip.ui.common - -enum class CommentActionMode { - POPUP, - BOTTOM_SHEET -} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/OptionChipButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/OptionChipButton.kt index 21f0ba2a..66de672e 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/OptionChipButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/OptionChipButton.kt @@ -42,7 +42,7 @@ fun OptionChipButton( val checked = isSelected ?: isClicked val textColor = when { - !enabled && isFilled -> colors.Grey02 + !enabled -> colors.DarkGrey isFilled -> colors.White checked -> colors.Purple else -> colors.Grey01 @@ -54,6 +54,7 @@ fun OptionChipButton( else -> Color.Transparent } val borderColor = when { + !enabled -> colors.DarkGrey02 !isFilled && checked -> colors.Purple !isFilled -> colors.Grey02 else -> Color.Transparent diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/SubGenreChipRow.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/SubGenreChipRow.kt index c29255df..16eeeb7c 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/SubGenreChipRow.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/SubGenreChipRow.kt @@ -24,11 +24,17 @@ fun SubGenreChipGrid( horizontalArrangement = Arrangement.spacedBy(8.dp, horizontalAlignment), verticalArrangement = Arrangement.spacedBy(8.dp) ) { + val isLimitReached = selectedGenres.size >= 5 + subGenres.forEach { genre -> + val isSelected = selectedGenres.contains(genre) + val isEnabled = isSelected || !isLimitReached + OptionChipButton( text = genre, - isSelected = selectedGenres.contains(genre), + isSelected = isSelected, isFilled = false, + enabled = isEnabled, onClick = { onGenreToggle(genre) } ) } diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardBookList.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardBookList.kt index 8bb88cc5..14c97c32 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardBookList.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardBookList.kt @@ -1,6 +1,7 @@ package com.texthip.thip.ui.common.cards import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -40,12 +41,14 @@ fun CardBookList( imageUrl: String? = null, // API에서 받은 이미지 URL showBookmark: Boolean = false, isBookmarked: Boolean = false, - onBookmarkClick: () -> Unit = {} + onBookmarkClick: () -> Unit = {}, + onClick: () -> Unit = {}, ) { Row( modifier = modifier .fillMaxWidth() - .background(Color.Transparent), + .background(Color.Transparent) + .clickable { onClick() }, ) { // 책 이미지 AsyncImage( diff --git a/app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt b/app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt index 7ea84058..a7e72064 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt @@ -43,6 +43,7 @@ fun ImageViewerModal( Box( modifier = Modifier .fillMaxSize() + .background(colors.Black80) .clickable { onDismiss() } ) { // 이전 버튼 @@ -66,7 +67,8 @@ fun ImageViewerModal( .clickable { /* HorizontalPager 내부 클릭 시 모달 닫기 방지 */ } ) { page -> Box( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize(), contentAlignment = Alignment.Center ) { AsyncImage( @@ -103,7 +105,11 @@ fun ImageViewerModal( // 이미지 카운터 (예: 1/3) if (imageUrls.size > 1) { Text( - text = stringResource(id = R.string.tag_count, pagerState.currentPage + 1, imageUrls.size), + text = stringResource( + id = R.string.tag_count, + pagerState.currentPage + 1, + imageUrls.size + ), style = typography.copy_r400_s14, color = colors.White, modifier = Modifier 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 ee46c8c2..d32c21a1 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 @@ -4,7 +4,6 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Arrangement @@ -42,18 +41,16 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController -import androidx.navigation.compose.rememberNavController import coil.compose.AsyncImage import com.texthip.thip.R -import com.texthip.thip.ui.common.CommentActionMode import com.texthip.thip.ui.common.bottomsheet.MenuBottomSheet import com.texthip.thip.ui.common.buttons.ActionBarButton import com.texthip.thip.ui.common.buttons.ActionBookButton @@ -64,18 +61,18 @@ import com.texthip.thip.ui.common.modal.DialogPopup import com.texthip.thip.ui.common.modal.ToastWithDate import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar import com.texthip.thip.ui.feed.component.ImageViewerModal -import com.texthip.thip.ui.feed.mock.FeedStateUpdateResult import com.texthip.thip.ui.feed.viewmodel.FeedDetailViewModel import com.texthip.thip.ui.group.note.component.CommentSection import com.texthip.thip.ui.group.note.viewmodel.CommentsEvent import com.texthip.thip.ui.group.note.viewmodel.CommentsViewModel import com.texthip.thip.ui.group.room.mock.MenuBottomSheetItem -import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography import com.texthip.thip.utils.rooms.advancedImePadding import kotlinx.coroutines.delay +private data class CommentActionTarget(val commentId: Int, val isWriter: Boolean) + @Composable fun FeedCommentScreen( navController: NavHostController, @@ -156,9 +153,20 @@ fun FeedCommentScreen( // 피드 데이터가 없으면 리턴 val feedDetail = feedDetailUiState.feedDetail ?: return - var isBottomSheetVisible by remember { mutableStateOf(false) } - var showDialog by remember { mutableStateOf(false) } // 피드 삭제 + var isPostMenuVisible by remember { mutableStateOf(false) } + var isCommentMenuVisible by remember { mutableStateOf(false) } + var selectedCommentForMenu by remember { mutableStateOf(null) } + var showDeleteDialog by remember { mutableStateOf(false) } var showToast by remember { mutableStateOf(false) } + var toastMessage by remember { mutableStateOf("") } + val context = LocalContext.current + + LaunchedEffect(showToast) { + if (showToast) { + delay(3000) + showToast = false + } + } val images = feedDetail.contentUrls var showImageViewer by remember { mutableStateOf(false) } @@ -168,8 +176,6 @@ fun FeedCommentScreen( var replyingToCommentId by remember { mutableStateOf(null) } var replyingToNickname by remember { mutableStateOf(null) } - var selectedCommentId by remember { mutableStateOf(null) } - val focusManager = LocalFocusManager.current val focusRequester = remember { FocusRequester() } val listState = rememberLazyListState() @@ -184,17 +190,18 @@ fun FeedCommentScreen( } } + val isOverlayVisible = isPostMenuVisible || isCommentMenuVisible || showDeleteDialog || showImageViewer + Box( modifier = Modifier .fillMaxSize() .advancedImePadding() ) { Box( - modifier = if (isBottomSheetVisible || showDialog || showImageViewer) { + modifier = if (isOverlayVisible) { Modifier .fillMaxSize() .blur(5.dp) - .background(colors.Black800) } else { Modifier.fillMaxSize() } @@ -202,7 +209,6 @@ fun FeedCommentScreen( .pointerInput(Unit) { detectTapGestures(onTap = { focusManager.clearFocus() - selectedCommentId = null }) } ) { @@ -211,7 +217,7 @@ fun FeedCommentScreen( isRightIconVisible = true, isTitleVisible = false, onLeftClick = onNavigateBack, - onRightClick = { isBottomSheetVisible = true }, + onRightClick = { isPostMenuVisible = true }, ) LazyColumn( @@ -310,9 +316,7 @@ fun FeedCommentScreen( isPinVisible = false, isLockIcon = feedDetail.isPublic == false, onLikeClick = { feedDetailViewModel.changeFeedLike() }, - onCommentClick = { /* 스크롤 이동 or 포커스 처리 */ }, onBookmarkClick = { feedDetailViewModel.changeFeedSave() }, - onPinClick = { /* TODO: pin 기능 */ } ) HorizontalDivider( @@ -367,23 +371,19 @@ fun FeedCommentScreen( ) { commentItem -> CommentSection( commentItem = commentItem, - actionMode = CommentActionMode.POPUP, - selectedCommentId = selectedCommentId, onEvent = commentsViewModel::onEvent, onReplyClick = { commentId, nickname -> replyingToCommentId = commentId replyingToNickname = nickname - selectedCommentId = null focusRequester.requestFocus() }, onCommentLongPress = { comment -> - selectedCommentId = comment.commentId + selectedCommentForMenu = CommentActionTarget(comment.commentId!!, comment.isWriter) + isCommentMenuVisible = true }, onReplyLongPress = { reply -> - selectedCommentId = reply.commentId - }, - onDismissPopup = { - selectedCommentId = null + selectedCommentForMenu = CommentActionTarget(reply.commentId, reply.isWriter) + isCommentMenuVisible = true }, onProfileClick = onNavigateToUserProfile ) @@ -425,32 +425,31 @@ fun FeedCommentScreen( visible = showToast, enter = slideInVertically( initialOffsetY = { -it }, - animationSpec = tween(durationMillis = 2000) + animationSpec = tween(durationMillis = 1000) ), exit = slideOutVertically( targetOffsetY = { -it }, - animationSpec = tween(durationMillis = 2000) + animationSpec = tween(durationMillis = 1000) ), modifier = Modifier .align(Alignment.TopCenter) .padding(horizontal = 20.dp, vertical = 16.dp) - .zIndex(2f) + .zIndex(3f) ) { ToastWithDate( - message = "게시글 신고를 완료했어요." + message = toastMessage ) } } - if (isBottomSheetVisible) { + if (isPostMenuVisible) { val menuItems = if (feedDetail.isWriter) { - // 내 피드인 경우: 수정, 삭제 listOf( MenuBottomSheetItem( text = stringResource(R.string.edit_feed), color = colors.White, onClick = { - isBottomSheetVisible = false + isPostMenuVisible = false onNavigateToFeedEdit(feedDetail.feedId) } ), @@ -458,56 +457,81 @@ fun FeedCommentScreen( text = stringResource(R.string.delete_feed), color = colors.Red, onClick = { - isBottomSheetVisible = false - showDialog = true + isPostMenuVisible = false + showDeleteDialog = true + } + ) + ) + } else { + listOf( + MenuBottomSheetItem( + text = stringResource(R.string.report), + color = colors.Red, + onClick = { + toastMessage = "피드 신고를 완료했습니다." + showToast = true + isPostMenuVisible = false + } + ) + ) + } + MenuBottomSheet( + items = menuItems, + onDismiss = { isPostMenuVisible = false } + ) + } + + if (isCommentMenuVisible && selectedCommentForMenu != null) { + val comment = selectedCommentForMenu!! + val menuItems = if (comment.isWriter) { + listOf( + MenuBottomSheetItem( + text = stringResource(R.string.delete), + color = colors.Red, + onClick = { + commentsViewModel.onEvent(CommentsEvent.DeleteComment(comment.commentId)) + isCommentMenuVisible = false } ) ) } else { - // 다른 사람 피드인 경우: 신고만 listOf( MenuBottomSheetItem( text = stringResource(R.string.report), color = colors.Red, onClick = { - isBottomSheetVisible = false - // TODO: 피드 신고 API 호출 + toastMessage = "댓글 신고를 완료했습니다." showToast = true + isCommentMenuVisible = false } ) ) } + MenuBottomSheet( items = menuItems, - onDismiss = { isBottomSheetVisible = false } + onDismiss = { isCommentMenuVisible = false } ) } - if (showDialog) { + if (showDeleteDialog) { Box( Modifier .fillMaxSize() - .clickable { showDialog = false }) { + .clickable(enabled = false, onClick = {}) + ) { Box(Modifier.align(Alignment.Center)) { DialogPopup( title = stringResource(R.string.delete_feed_dialog_title), description = stringResource(R.string.delete_feed_dialog_description), onConfirm = { - showDialog = false - isBottomSheetVisible = false + showDeleteDialog = false feedDetailViewModel.deleteFeed(feedId) }, onCancel = { - showDialog = false - isBottomSheetVisible = false + showDeleteDialog = false } ) - LaunchedEffect(showToast) { - if (showToast) { - delay(3000) - showToast = false - } - } } } } @@ -521,14 +545,3 @@ fun FeedCommentScreen( } } } - -@Preview -@Composable -private fun FeedCommentScreenPrev() { - ThipTheme { - FeedCommentScreen( - feedId = 1, - navController = rememberNavController() - ) - } -} diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedMyScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedMyScreen.kt new file mode 100644 index 00000000..8b5248e7 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedMyScreen.kt @@ -0,0 +1,224 @@ +package com.texthip.thip.ui.feed.screen + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +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 +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +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 com.texthip.thip.R +import com.texthip.thip.data.model.feed.response.FeedList +import com.texthip.thip.data.model.feed.response.FeedMineInfoResponse +import com.texthip.thip.data.model.feed.response.MyFeedItem +import com.texthip.thip.ui.common.header.AuthorHeader +import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.feed.component.FeedSubscribeBarlist +import com.texthip.thip.ui.feed.component.OthersFeedCard +import com.texthip.thip.ui.feed.viewmodel.FeedUiState +import com.texthip.thip.ui.feed.viewmodel.FeedViewModel +import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography +import com.texthip.thip.utils.color.hexToColor + +@Composable +fun FeedMyScreen( + viewModel: FeedViewModel, + onNavigateBack: () -> Unit, + onNavigateToSubscriptionList: (userId: Long) -> Unit = {}, + onNavigateToFeedComment: (feedId: Long) -> Unit = {}, +) { + val uiState by viewModel.uiState.collectAsState() + + LaunchedEffect(Unit) { + viewModel.onTabSelected(1) + } + + FeedMyContent( + uiState = uiState, + onNavigateBack = onNavigateBack, + onLikeClick = { feedId -> viewModel.changeFeedLike(feedId) }, + onBookmarkClick = { feedId -> viewModel.changeFeedSave(feedId) }, + onNavigateToSubscriptionList = onNavigateToSubscriptionList, + onNavigateToFeedComment = onNavigateToFeedComment + ) +} + +@Composable +fun FeedMyContent( + uiState: FeedUiState, + onNavigateBack: () -> Unit, + onLikeClick: (Long) -> Unit, + onBookmarkClick: (Long) -> Unit, + onNavigateToSubscriptionList: (userId: Long) -> Unit, + onNavigateToFeedComment: (feedId: Long) -> Unit = {}, +) { + val userInfo = uiState.myFeedInfo + + fun MyFeedItem.toFeedList(): FeedList { + return FeedList( + feedId = this.feedId.toLong(), + postDate = this.postDate, + isbn = this.isbn, + bookTitle = this.bookTitle, + bookAuthor = this.bookAuthor, + contentBody = this.contentBody, + contentUrls = this.contentUrls, + likeCount = this.likeCount, + commentCount = this.commentCount, + isPublic = this.isPublic, + isSaved = false, + isLiked = false, + isWriter = true + ) + } + + Box(modifier = Modifier.fillMaxSize()) { + Column( + modifier = Modifier.fillMaxSize() + ) { + DefaultTopAppBar( + isRightIconVisible = false, + isTitleVisible = false, + onLeftClick = onNavigateBack, + ) + + if (uiState.isRefreshing || (uiState.isLoading && uiState.myFeeds.isEmpty())) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + CircularProgressIndicator() + } + } else if (userInfo != null) { + LazyColumn( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + item { + Spacer(modifier = Modifier.height(32.dp)) + AuthorHeader( + profileImage = userInfo.profileImageUrl, + nickname = userInfo.nickname, + badgeText = userInfo.aliasName, + badgeTextColor = hexToColor(userInfo.aliasColor), + showButton = false, + modifier = Modifier.padding(bottom = 20.dp) + ) + Spacer(modifier = Modifier.height(16.dp)) + FeedSubscribeBarlist( + modifier = Modifier.padding(horizontal = 20.dp), + followerProfileImageUrls = userInfo.latestFollowerProfileImageUrls + ?: emptyList(), + onClick = { onNavigateToSubscriptionList(userInfo.creatorId) } + ) + Spacer(modifier = Modifier.height(40.dp)) + Text( + text = stringResource(R.string.whole_num, userInfo.totalFeedCount), + style = typography.menu_m500_s14_h24, + color = colors.Grey, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 12.dp, start = 20.dp) + ) + HorizontalDivider( + color = colors.DarkGrey03, + thickness = 1.dp, + modifier = Modifier.padding(horizontal = 20.dp) + ) + } + if (userInfo.totalFeedCount == 0) { + item { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(top = 244.dp), + contentAlignment = Alignment.TopCenter + ) { + Text( + text = stringResource(R.string.empty_feed), + style = typography.smalltitle_sb600_s18_h24, + color = colors.White + ) + } + } + } else { + itemsIndexed( + items = uiState.myFeeds, + key = { _, item -> item.feedId } + ) { index, feed -> + Spacer(modifier = Modifier.height(if (index == 0) 20.dp else 40.dp)) + OthersFeedCard( + feedItem = feed.toFeedList(), + onLikeClick = { onLikeClick(feed.feedId.toLong()) }, + onBookmarkClick = { onBookmarkClick(feed.feedId.toLong()) }, + onContentClick = { onNavigateToFeedComment(feed.feedId.toLong()) } + ) + Spacer(modifier = Modifier.height(40.dp)) + if (index < uiState.myFeeds.lastIndex) { + HorizontalDivider( + color = colors.DarkGrey03, + thickness = 10.dp + ) + } + } + } + } + } + } + } +} + +@Preview +@Composable +private fun FeedMyScreenPreview() { + // Preview용 가짜 데이터 + val mockUserInfo = FeedMineInfoResponse( + creatorId = 1, + profileImageUrl = "", + nickname = "김작가", + aliasName = "소설가", + aliasColor = "#A0F8E8", + totalFeedCount = 5, + followerCount = 150, + latestFollowerProfileImageUrls = emptyList(), + isFollowing = true, + ) + val mockFeeds = List(5) { + MyFeedItem( + feedId = it, postDate = "2시간 전", isbn = "1234", + bookTitle = "나의 책 제목 ${it + 1}", bookAuthor = "나", + contentBody = "내가 작성한 피드 내용입니다. 내용은 여기에 표시됩니다.", + contentUrls = emptyList(), likeCount = 15, commentCount = 3, + isPublic = true, + isWriter = false + ) + } + + ThipTheme { + FeedMyContent( + uiState = FeedUiState( + isLoading = false, + myFeedInfo = mockUserInfo, + myFeeds = mockFeeds + ), + onLikeClick = {}, + onBookmarkClick = {}, + onNavigateToSubscriptionList = {}, + onNavigateBack = {}, + ) + } +} diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedOthersScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedOthersScreen.kt index 365c301c..b55d967d 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedOthersScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedOthersScreen.kt @@ -1,5 +1,9 @@ package com.texthip.thip.ui.feed.screen +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -50,15 +54,17 @@ fun FeedOthersScreen( ) { val uiState by viewModel.uiState.collectAsState() val context = LocalContext.current - + FeedOthersContent( uiState = uiState, onNavigateBack = onNavigateBack, onLikeClick = { feedId -> viewModel.changeFeedLike(feedId) }, onBookmarkClick = { feedId -> viewModel.changeFeedSave(feedId) }, onToggleFollow = { - val followedMessage = context.getString(R.string.toast_thip, uiState.userInfo?.nickname ?: "") - val unfollowedMessage = context.getString(R.string.toast_thip_cancel, uiState.userInfo?.nickname ?: "") + val followedMessage = + context.getString(R.string.toast_thip, uiState.userInfo?.nickname ?: "") + val unfollowedMessage = + context.getString(R.string.toast_thip_cancel, uiState.userInfo?.nickname ?: "") viewModel.toggleFollow(followedMessage, unfollowedMessage) }, onHideToast = viewModel::hideToast, @@ -180,19 +186,25 @@ fun FeedOthersContent( } } } - if (uiState.showToast) { - Box( - modifier = Modifier - .fillMaxWidth() - .zIndex(1f) - .align(Alignment.TopCenter) - .padding(horizontal = 15.dp, vertical = 15.dp), - ) { - ToastWithDate( - message = uiState.toastMessage, - modifier = Modifier.fillMaxWidth() - ) - } + AnimatedVisibility( + visible = uiState.showToast, + enter = slideInVertically( + initialOffsetY = { -it }, + animationSpec = tween(durationMillis = 2000) + ), + exit = slideOutVertically( + targetOffsetY = { -it }, + animationSpec = tween(durationMillis = 2000) + ), + modifier = Modifier + .align(Alignment.TopCenter) + .padding(horizontal = 20.dp, vertical = 16.dp) + .zIndex(2f) + ) { + ToastWithDate( + message = uiState.toastMessage, + modifier = Modifier.fillMaxWidth() + ) } } } diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt index 60d0e3c2..2c8f5f49 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt @@ -1,6 +1,5 @@ package com.texthip.thip.ui.feed.screen -import android.util.Log import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.LinearEasing @@ -317,7 +316,7 @@ fun FeedScreen( Box( modifier = Modifier .fillMaxWidth() - .padding(top = 244.dp), + .padding(top = 110.dp), contentAlignment = Alignment.TopCenter ) { Text( diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/OthersSubscriptionListScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/OthersSubscriptionListScreen.kt index eed1ee27..99fe1c20 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/OthersSubscriptionListScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/OthersSubscriptionListScreen.kt @@ -43,7 +43,7 @@ import com.texthip.thip.utils.color.hexToColor @Composable fun OthersSubscriptionListScreen( onNavigateBack: () -> Unit, - onNavigateToUserProfile: (userId: Long) -> Unit = {}, + onProfileClick: (userId: Long, isMyself: Boolean) -> Unit = { _, _ -> }, viewModel: OthersSubscriptionViewModel = hiltViewModel() ) { val uiState by viewModel.uiState.collectAsState() @@ -68,7 +68,7 @@ fun OthersSubscriptionListScreen( uiState = uiState, lazyListState = lazyListState, onNavigateBack = onNavigateBack, - onProfileClick = onNavigateToUserProfile + onProfileClick = onProfileClick ) } @Composable @@ -76,7 +76,7 @@ fun OthersSubscriptionContent( uiState: OthersSubscriptionUiState, lazyListState: LazyListState, onNavigateBack: () -> Unit, - onProfileClick: (userId: Long) -> Unit + onProfileClick: (userId: Long, isMyself: Boolean) -> Unit ) { Column( Modifier @@ -122,7 +122,7 @@ fun OthersSubscriptionContent( showThipNum = true, profileImageSize = 36.dp, thipNum = user.followerCount, - onClick = { onProfileClick(user.userId) } + onClick = { onProfileClick(user.userId, user.isMyself) } ) if (index < uiState.followers.lastIndex) { @@ -164,7 +164,8 @@ private fun OthersSubscriptionListScreenPrev() { nickname = "문학소년 $it", aliasName = if (it % 3 == 0) "공식 인플루언서" else "글쓰는 탐험가", aliasColor = if (it % 3 == 0) "#00C7B2" else "#FFD600", - followerCount = it * 10 + followerCount = it * 10, + isMyself = true ) } @@ -178,7 +179,7 @@ private fun OthersSubscriptionListScreenPrev() { ), lazyListState = rememberLazyListState(), onNavigateBack = {}, - onProfileClick = {} + onProfileClick = { _, _ -> } ) } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupBookListWithScrollbar.kt b/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupBookListWithScrollbar.kt index e49ce2c8..896ce011 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupBookListWithScrollbar.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupBookListWithScrollbar.kt @@ -13,7 +13,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.texthip.thip.R import com.texthip.thip.ui.common.cards.CardBookSearch import com.texthip.thip.ui.common.modal.drawVerticalScrollbar import com.texthip.thip.ui.group.makeroom.mock.BookData @@ -31,7 +30,6 @@ fun GroupBookListWithScrollbar( Box( Modifier .fillMaxWidth() - .height(320.dp) ) { Column( Modifier @@ -45,14 +43,14 @@ fun GroupBookListWithScrollbar( imageUrl = book.imageUrl, onClick = { onBookClick(book) } ) - + Spacer(modifier = Modifier.height(12.dp)) if (index < books.size - 1) { - Spacer(modifier = Modifier.height(12.dp)) - Spacer(modifier = Modifier - .fillMaxWidth() - .padding(end = 6.dp) - .height(1.dp) - .background(color = colors.Grey02) + Spacer( + modifier = Modifier + .fillMaxWidth() + .padding(end = 6.dp) + .height(1.dp) + .background(color = colors.Grey02) ) Spacer(modifier = Modifier.height(12.dp)) } diff --git a/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupBookSearchBottomSheet.kt b/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupBookSearchBottomSheet.kt index 522086b3..dd1bd0fd 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupBookSearchBottomSheet.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupBookSearchBottomSheet.kt @@ -3,7 +3,7 @@ package com.texthip.thip.ui.group.makeroom.component import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -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.utils.rooms.advancedImePadding @Composable fun GroupBookSearchBottomSheet( @@ -65,7 +66,8 @@ fun GroupBookSearchBottomSheet( Column( Modifier .fillMaxWidth() - .padding(bottom = 90.dp) + .fillMaxHeight(0.8f) + .advancedImePadding() ) { Column(Modifier.padding(start = 20.dp, end = 20.dp, top = 20.dp)) { SearchBookTextField( diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentBottomSheet.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentBottomSheet.kt index 91ca3229..0fd831e2 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentBottomSheet.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentBottomSheet.kt @@ -36,7 +36,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import com.texthip.thip.R import com.texthip.thip.data.model.comments.response.CommentList import com.texthip.thip.data.model.comments.response.ReplyList -import com.texthip.thip.ui.common.CommentActionMode import com.texthip.thip.ui.common.bottomsheet.CustomBottomSheet import com.texthip.thip.ui.common.bottomsheet.MenuBottomSheet import com.texthip.thip.ui.common.forms.CommentTextField @@ -262,7 +261,6 @@ private fun CommentLazyList( ) { comment -> CommentSection( commentItem = comment, - actionMode = CommentActionMode.BOTTOM_SHEET, onReplyClick = onReplyClick, onEvent = onEvent, onCommentLongPress = onCommentLongPress, diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt index 66ee8e9f..75619137 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt @@ -20,10 +20,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.data.model.comments.response.CommentList -import com.texthip.thip.ui.common.CommentActionMode import com.texthip.thip.ui.common.header.ProfileBarFeed -import com.texthip.thip.ui.feed.component.CommentActionPopup -import com.texthip.thip.ui.group.note.viewmodel.CommentsEvent import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @@ -36,11 +33,7 @@ fun CommentItem( onReplyClick: (String?) -> Unit = { }, onLikeClick: () -> Unit = {}, onLongPress: () -> Unit = {}, - onProfileClick: () -> Unit = {}, - actionMode: CommentActionMode, - isSelected: Boolean = false, - onDismissPopup: () -> Unit = {}, - onEvent: (CommentsEvent) -> Unit = { _ -> } + onProfileClick: () -> Unit = {} ) { Box { if (data.isDeleted) { @@ -108,21 +101,6 @@ fun CommentItem( } } } - if (actionMode == CommentActionMode.POPUP && isSelected) { - CommentActionPopup( - text = if (data.isWriter) stringResource(R.string.delete) else stringResource(R.string.report), - textColor = if (data.isWriter) colors.Red else colors.White, - onClick = { - if (data.isWriter) { - data.commentId?.let { onEvent(CommentsEvent.DeleteComment(it)) } - } else { - // TODO: 신고 로직 - } - onDismissPopup() - }, - onDismissRequest = onDismissPopup - ) - } } } @@ -153,7 +131,6 @@ private fun CommentItemPreview() { isWriter = false, replyList = emptyList() ), - actionMode = CommentActionMode.POPUP, ) CommentItem( @@ -172,7 +149,6 @@ private fun CommentItemPreview() { isWriter = false, replyList = emptyList() ), - actionMode = CommentActionMode.BOTTOM_SHEET, ) CommentItem( @@ -191,7 +167,6 @@ private fun CommentItemPreview() { isWriter = false, replyList = emptyList() ), - actionMode = CommentActionMode.POPUP, ) } } diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt index 8d8c339c..12a38e08 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt @@ -12,7 +12,6 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.data.model.comments.response.CommentList import com.texthip.thip.data.model.comments.response.ReplyList -import com.texthip.thip.ui.common.CommentActionMode import com.texthip.thip.ui.group.note.viewmodel.CommentsEvent import com.texthip.thip.ui.theme.ThipTheme @@ -24,9 +23,6 @@ fun CommentSection( onCommentLongPress: (CommentList) -> Unit = { _ -> }, onReplyLongPress: (ReplyList) -> Unit = { _ -> }, onProfileClick: (userId: Long) -> Unit = {}, - actionMode: CommentActionMode, - selectedCommentId: Int? = null, - onDismissPopup: () -> Unit = {}, ) { Box { Column( @@ -56,11 +52,7 @@ fun CommentSection( onProfileClick = { commentItem.creatorId?.let { id -> onProfileClick(id) } - }, - actionMode = actionMode, - isSelected = selectedCommentId != null && commentItem.commentId == selectedCommentId, - onDismissPopup = onDismissPopup, - onEvent = onEvent + } ) commentItem.replyList.forEach { reply -> @@ -75,11 +67,7 @@ fun CommentSection( onEvent(CommentsEvent.LikeReply(reply.commentId)) }, onLongPress = { onReplyLongPress(reply) }, - onProfileClick = { onProfileClick(reply.creatorId) }, - actionMode = actionMode, - isSelected = selectedCommentId != null && reply.commentId == selectedCommentId, - onDismissPopup = onDismissPopup, - onEvent = onEvent + onProfileClick = { onProfileClick(reply.creatorId) } ) } } @@ -111,7 +99,6 @@ fun CommentSectionPreview() { onReplyClick = { commentId, nickname -> // Handle reply click }, - actionMode = CommentActionMode.POPUP, ) } } diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt index aff12d5a..5a6b0c56 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt @@ -52,7 +52,9 @@ fun FilterHeaderSection( text = stringResource(R.string.view_by_page), isSelected = isPageFiltered, onClick = { - isPageInputVisible = !isPageInputVisible + if (!isPageInputVisible) { + isPageInputVisible = true + } }, onCloseClick = { isPageInputVisible = true @@ -66,8 +68,16 @@ fun FilterHeaderSection( isSelected = isTotalSelected, enabled = totalEnabled, textStyle = typography.menu_r400_s14_h24, - onClick = onTotalToggle, - onDisabledClick = onDisabledClick + onClick = { + if (!isPageInputVisible) { + onTotalToggle() + } + }, + onDisabledClick = { + if (!isPageInputVisible) { + onDisabledClick() + } + }, ) } diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt index 539e47e9..16cc0e1c 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt @@ -22,10 +22,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.data.model.comments.response.ReplyList -import com.texthip.thip.ui.common.CommentActionMode import com.texthip.thip.ui.common.header.ProfileBarFeed -import com.texthip.thip.ui.feed.component.CommentActionPopup -import com.texthip.thip.ui.group.note.viewmodel.CommentsEvent import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @@ -38,11 +35,7 @@ fun ReplyItem( onReplyClick: () -> Unit = { }, onLikeClick: () -> Unit = {}, onLongPress: () -> Unit = {}, - onProfileClick: () -> Unit = {}, - actionMode: CommentActionMode, - isSelected: Boolean = false, - onDismissPopup: () -> Unit = {}, - onEvent: (CommentsEvent) -> Unit = { _ -> } + onProfileClick: () -> Unit = {} ) { Box { Row( @@ -121,21 +114,6 @@ fun ReplyItem( } } } - if (actionMode == CommentActionMode.POPUP && isSelected) { - CommentActionPopup( - text = if (data.isWriter) stringResource(R.string.delete) else stringResource(R.string.report), - textColor = if (data.isWriter) colors.Red else colors.White, - onClick = { - if (data.isWriter) { - onEvent(CommentsEvent.DeleteComment(data.commentId)) - } else { - // TODO: 신고 로직 - } - onDismissPopup() - }, - onDismissRequest = onDismissPopup // 바깥 클릭 시 팝업 닫기 - ) - } } } @@ -164,7 +142,6 @@ private fun ReplyItemPreview() { isWriter = false, likeCount = 5 ), - actionMode = CommentActionMode.POPUP, ) } } diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt index 806d20ff..36155433 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt @@ -6,6 +6,8 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.absoluteOffset import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -35,6 +37,7 @@ import com.texthip.thip.ui.group.note.viewmodel.GroupNoteCreateEvent import com.texthip.thip.ui.group.note.viewmodel.GroupNoteCreateUiState import com.texthip.thip.ui.group.note.viewmodel.GroupNoteCreateViewModel import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.utils.rooms.advancedImePadding @Composable fun GroupNoteCreateScreen( @@ -78,7 +81,9 @@ fun GroupNoteCreateContent( val iconCoordinates = remember { mutableStateOf(null) } Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() + .advancedImePadding() ) { Column { InputTopAppBar( @@ -90,6 +95,8 @@ fun GroupNoteCreateContent( Column( modifier = Modifier + .weight(1f) + .verticalScroll(rememberScrollState()) .padding(vertical = 32.dp, horizontal = 20.dp), verticalArrangement = Arrangement.spacedBy(32.dp), ) { diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt index b4a613b3..9fa925d7 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt @@ -6,6 +6,8 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.absoluteOffset import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -35,6 +37,7 @@ import com.texthip.thip.ui.group.note.viewmodel.GroupVoteCreateEvent import com.texthip.thip.ui.group.note.viewmodel.GroupVoteCreateUiState import com.texthip.thip.ui.group.note.viewmodel.GroupVoteCreateViewModel import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.utils.rooms.advancedImePadding @Composable fun GroupVoteCreateScreen( @@ -75,7 +78,11 @@ fun GroupVoteCreateContent( var showTooltip by rememberSaveable { mutableStateOf(false) } val iconCoordinates = remember { mutableStateOf(null) } - Box(modifier = Modifier.fillMaxSize()) { + Box( + modifier = Modifier + .fillMaxSize() + .advancedImePadding() + ) { Column { InputTopAppBar( title = stringResource(R.string.create_vote), @@ -86,6 +93,8 @@ fun GroupVoteCreateContent( Column( modifier = Modifier + .weight(1f) + .verticalScroll(rememberScrollState()) .padding(vertical = 32.dp, horizontal = 20.dp), verticalArrangement = Arrangement.spacedBy(32.dp), ) { diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt index 1a33072a..d0f6651e 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt @@ -24,7 +24,7 @@ fun GroupRoomBody( authorName: String, isbn: String, currentPage: Int, - userPercentage: Double, + userPercentage: Int, currentVotes: List, onNavigateToBookDetail: (isbn: String) -> Unit = {}, onNavigateToNote: () -> Unit = {}, @@ -44,7 +44,7 @@ fun GroupRoomBody( CardNote( currentPage = currentPage, - percentage = userPercentage.roundToInt(), + percentage = userPercentage, ) { onNavigateToNote() } @@ -71,7 +71,7 @@ private fun GroupRoomBodyPreview() { authorName = "저자 이름", isbn = "1234567890", currentPage = 100, - userPercentage = 50.0, + userPercentage = 50, currentVotes = listOf( CurrentVote( content = "3연에 나오는 심장은 무엇을 의미하는 걸까요?", diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt index 8690f034..d11949e8 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt @@ -301,7 +301,7 @@ private fun GroupRoomScreenPreview() { bookTitle = "호르몬 체인지", authorName = "최정화", currentPage = 100, - userPercentage = 5.0, + userPercentage = 5, currentVotes = emptyList() ), onBackClick = {} diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/component/BookContent.kt b/app/src/main/java/com/texthip/thip/ui/mypage/component/BookContent.kt index 56c34a91..40aca106 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/component/BookContent.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/component/BookContent.kt @@ -25,7 +25,9 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun BookContent( - bookList: List, viewModel: SavedBookViewModel + bookList: List, + viewModel: SavedBookViewModel, + onBookClick: (isbn: String) -> Unit ) { if (bookList.isEmpty()) { EmptyBookContent() @@ -48,7 +50,8 @@ fun BookContent( publisher = book.publisher, showBookmark = true, isBookmarked = book.isSaved, - onBookmarkClick = { viewModel.toggleBookmark(book.isbn) } + onBookmarkClick = { viewModel.toggleBookmark(book.isbn) }, + onClick = { onBookClick(book.isbn) } ) if (index != bookList.lastIndex) { diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/component/FeedContent.kt b/app/src/main/java/com/texthip/thip/ui/mypage/component/FeedContent.kt index a0f29b9a..24839bff 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/component/FeedContent.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/component/FeedContent.kt @@ -24,18 +24,20 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun FeedContent( - feedList: List, viewModel: SavedFeedViewModel + feedList: List, + viewModel: SavedFeedViewModel, + onFeedClick: (feedId: Long) -> Unit ) { if (feedList.isEmpty()) { EmptyFeedContent() } else { - LazyColumn ( + LazyColumn( modifier = Modifier .fillMaxSize(), contentPadding = PaddingValues(bottom = 20.dp) - ){ - itemsIndexed(feedList, key = { _,feed -> feed.id }) { index,feed -> + ) { + itemsIndexed(feedList, key = { _, feed -> feed.id }) { index, feed -> if (index == 0) { Spacer(Modifier.height(32.dp)) } @@ -43,7 +45,8 @@ fun FeedContent( SavedFeedCard( feedItem = feed, onBookmarkClick = { viewModel.toggleBookmark(feed.id) }, - onLikeClick = { viewModel.toggleLike(feed.id) } + onLikeClick = { viewModel.toggleLike(feed.id) }, + onContentClick = { onFeedClick(feed.id) } ) if (index != feedList.lastIndex) { diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageSaveScreen.kt b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageSaveScreen.kt index 65223b3e..76ea537b 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageSaveScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageSaveScreen.kt @@ -44,6 +44,8 @@ import com.texthip.thip.ui.theme.White @Composable fun MypageSaveScreen( onNavigateBack: () -> Unit, + onBookClick: (isbn: String) -> Unit = {}, + onFeedClick: (feedId: Long) -> Unit = {}, feedViewModel: SavedFeedViewModel = hiltViewModel(), bookViewModel: SavedBookViewModel = hiltViewModel() ) { @@ -115,12 +117,23 @@ fun MypageSaveScreen( } } } - Box(modifier = Modifier - .weight(1f) - .fillMaxWidth()) { + Box( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + ) { when (selectedTabIndex) { - 0 -> FeedContent(feedList = feedList, viewModel = feedViewModel) - 1 -> BookContent(bookList = bookList, viewModel = bookViewModel) + 0 -> FeedContent( + feedList = feedList, + onFeedClick = onFeedClick, + viewModel = feedViewModel, + ) + + 1 -> BookContent( + bookList = bookList, + onBookClick = onBookClick, + viewModel = bookViewModel, + ) } } } diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/BottomNavigationBar.kt b/app/src/main/java/com/texthip/thip/ui/navigator/BottomNavigationBar.kt index d2fe0c45..46131d72 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/BottomNavigationBar.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/BottomNavigationBar.kt @@ -24,9 +24,11 @@ import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.drawscope.Stroke 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 androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.rememberNavController import com.texthip.thip.ui.navigator.data.NavBarItems import com.texthip.thip.ui.navigator.extensions.isRoute import com.texthip.thip.ui.navigator.extensions.navigateToTab @@ -96,7 +98,7 @@ fun BottomNavigationBar(navController: NavHostController) { Row( modifier = Modifier .fillMaxSize() - .padding(horizontal = 32.dp), + .padding(horizontal = 20.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { @@ -132,4 +134,13 @@ fun BottomNavigationBar(navController: NavHostController) { } } } +} + +@Preview +@Composable +private fun BottomNavigationBarPreview() { + val navController = rememberNavController() + BottomNavigationBar( + navController = navController + ) } \ No newline at end of file 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 ada77abc..96dcbe95 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 @@ -1,26 +1,30 @@ package com.texthip.thip.ui.navigator.navigations import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.composable import androidx.navigation.toRoute import com.texthip.thip.ui.feed.screen.FeedCommentScreen +import com.texthip.thip.ui.feed.screen.FeedMyScreen import com.texthip.thip.ui.feed.screen.FeedOthersScreen import com.texthip.thip.ui.feed.screen.FeedScreen import com.texthip.thip.ui.feed.screen.FeedWriteScreen import com.texthip.thip.ui.feed.screen.MySubscriptionScreen -import com.texthip.thip.ui.feed.screen.SearchPeopleScreen import com.texthip.thip.ui.feed.screen.OthersSubscriptionListScreen +import com.texthip.thip.ui.feed.screen.SearchPeopleScreen +import com.texthip.thip.ui.feed.viewmodel.FeedViewModel import com.texthip.thip.ui.feed.viewmodel.FeedWriteViewModel import com.texthip.thip.ui.navigator.extensions.navigateToAlarm import com.texthip.thip.ui.navigator.extensions.navigateToBookDetail import com.texthip.thip.ui.navigator.extensions.navigateToFeedComment import com.texthip.thip.ui.navigator.extensions.navigateToFeedWrite import com.texthip.thip.ui.navigator.extensions.navigateToMySubscription -import com.texthip.thip.ui.navigator.extensions.navigateToSearchPeople import com.texthip.thip.ui.navigator.extensions.navigateToOthersSubscription +import com.texthip.thip.ui.navigator.extensions.navigateToSearchPeople import com.texthip.thip.ui.navigator.extensions.navigateToUserProfile import com.texthip.thip.ui.navigator.routes.FeedRoutes import com.texthip.thip.ui.navigator.routes.MainTabRoutes @@ -28,10 +32,25 @@ import com.texthip.thip.ui.navigator.routes.MainTabRoutes // Feed fun NavGraphBuilder.feedNavigation(navController: NavHostController, navigateBack: () -> Unit) { composable { backStackEntry -> + val feedViewModel: FeedViewModel = hiltViewModel(backStackEntry) + val uiState by feedViewModel.uiState.collectAsState() + val myUserId = uiState.myFeedInfo?.creatorId + + val onNavigateToUserProfile: (Long) -> Unit = { clickedUserId -> + if (myUserId != null && myUserId == clickedUserId) { + // 내 프로필일 경우 FeedMyScreen으로 이동 + navController.navigate(FeedRoutes.My) + } else { + // 다른 사람 프로필일 경우 FeedOthersScreen으로 이동 + navController.navigate(FeedRoutes.Others(clickedUserId)) + } + } + val resultFeedId = backStackEntry.savedStateHandle.get("feedId") val refreshFeed = backStackEntry.savedStateHandle.get("refreshFeed") FeedScreen( + feedViewModel = feedViewModel, navController = navController, resultFeedId = resultFeedId, refreshFeed = refreshFeed, @@ -53,9 +72,7 @@ fun NavGraphBuilder.feedNavigation(navController: NavHostController, navigateBac onNavigateToBookDetail = { isbn -> navController.navigateToBookDetail(isbn) }, - onNavigateToUserProfile = { userId -> - navController.navigateToUserProfile(userId) - }, + onNavigateToUserProfile = onNavigateToUserProfile, onNavigateToSearchPeople = { navController.navigateToSearchPeople() }, @@ -68,12 +85,20 @@ fun NavGraphBuilder.feedNavigation(navController: NavHostController, navigateBac ) } composable { + val feedViewModel: FeedViewModel = hiltViewModel(navController.getBackStackEntry(MainTabRoutes.Feed)) + val uiState by feedViewModel.uiState.collectAsState() + val myUserId = uiState.myFeedInfo?.creatorId + MySubscriptionScreen( onNavigateBack = { navigateBack() }, onNavigateToUserProfile = { userId -> - navController.navigate(FeedRoutes.Others(userId)) + if (myUserId != null && myUserId == userId) { + navController.navigate(FeedRoutes.My) + } else { + navController.navigate(FeedRoutes.Others(userId)) + } } ) } @@ -145,6 +170,19 @@ fun NavGraphBuilder.feedNavigation(navController: NavHostController, navigateBac } ) } + composable { + val feedViewModel: FeedViewModel = hiltViewModel(navController.getBackStackEntry(MainTabRoutes.Feed)) + FeedMyScreen( + viewModel = feedViewModel, + onNavigateBack = navigateBack, + onNavigateToSubscriptionList = { userId -> + navController.navigateToOthersSubscription(userId) + }, + onNavigateToFeedComment = { feedId -> + navController.navigateToFeedComment(feedId) + } + ) + } composable { backStackEntry -> // 다른 유저의 피드 화면 FeedOthersScreen( @@ -160,10 +198,10 @@ fun NavGraphBuilder.feedNavigation(navController: NavHostController, navigateBac ) } composable { backStackEntry -> - /*val route = backStackEntry.arguments?.let { - FeedRoutes.Comment(it.getLong("feedId")) - } ?: return@composable*/ val route = backStackEntry.toRoute() + val feedViewModel: FeedViewModel = hiltViewModel(navController.getBackStackEntry(MainTabRoutes.Feed)) + val uiState by feedViewModel.uiState.collectAsState() + val myUserId = uiState.myFeedInfo?.creatorId FeedCommentScreen( feedId = route.feedId, @@ -175,7 +213,11 @@ fun NavGraphBuilder.feedNavigation(navController: NavHostController, navigateBac navController.navigate(FeedRoutes.Write(feedId = feedId)) }, onNavigateToUserProfile = { userId -> - navController.navigateToUserProfile(userId) + if (myUserId != null && myUserId == userId) { + navController.navigate(FeedRoutes.My) + } else { + navController.navigate(FeedRoutes.Others(userId)) + } }, onNavigateToBookDetail = { isbn -> navController.navigateToBookDetail(isbn) @@ -186,8 +228,12 @@ fun NavGraphBuilder.feedNavigation(navController: NavHostController, navigateBac composable { OthersSubscriptionListScreen( onNavigateBack = navigateBack, - onNavigateToUserProfile = { userId -> - navController.navigateToUserProfile(userId) + onProfileClick = { userId, isMyself -> + if (isMyself) { + navController.navigate(FeedRoutes.My) + } else { + navController.navigate(FeedRoutes.Others(userId)) + } } ) } diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt index 3e1b7bef..9cb07e9e 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt @@ -9,6 +9,7 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.composable import androidx.navigation.toRoute +import com.texthip.thip.ui.feed.viewmodel.FeedViewModel import com.texthip.thip.ui.group.done.screen.GroupDoneScreen import com.texthip.thip.ui.group.makeroom.screen.GroupMakeRoomScreen import com.texthip.thip.ui.group.makeroom.viewmodel.GroupMakeRoomViewModel @@ -44,7 +45,7 @@ import com.texthip.thip.ui.navigator.extensions.navigateToGroupRoomUnlock import com.texthip.thip.ui.navigator.extensions.navigateToGroupSearch import com.texthip.thip.ui.navigator.extensions.navigateToGroupVoteCreate import com.texthip.thip.ui.navigator.extensions.navigateToRecommendedGroupRecruit -import com.texthip.thip.ui.navigator.extensions.navigateToUserProfile +import com.texthip.thip.ui.navigator.routes.FeedRoutes import com.texthip.thip.ui.navigator.routes.GroupRoutes import com.texthip.thip.ui.navigator.routes.MainTabRoutes @@ -281,13 +282,27 @@ fun NavGraphBuilder.groupNavigation( val route = backStackEntry.toRoute() val roomId = route.roomId + val feedViewModel: FeedViewModel = hiltViewModel(navController.getBackStackEntry(MainTabRoutes.Group)) + val feedUiState by feedViewModel.uiState.collectAsState() + val myUserId = feedUiState.myFeedInfo?.creatorId + + LaunchedEffect(Unit) { + if (feedUiState.myFeedInfo == null) { + feedViewModel.onTabSelected(1) + } + } + GroupRoomMatesScreen( roomId = roomId, onBackClick = { navigateBack() }, onUserClick = { userId -> - navController.navigateToUserProfile(userId) + if (myUserId != null && myUserId == userId) { + navController.navigate(FeedRoutes.My) + } else { + navController.navigate(FeedRoutes.Others(userId)) + } } ) } @@ -309,6 +324,16 @@ fun NavGraphBuilder.groupNavigation( val viewModel: GroupNoteViewModel = hiltViewModel(backStackEntry) + val feedViewModel: FeedViewModel = hiltViewModel(navController.getBackStackEntry(MainTabRoutes.Group)) + val feedUiState by feedViewModel.uiState.collectAsState() + val myUserId = feedUiState.myFeedInfo?.creatorId + + LaunchedEffect(Unit) { + if (feedUiState.myFeedInfo == null) { + feedViewModel.onTabSelected(1) + } + } + GroupNoteScreen( roomId = roomId, resultTabIndex = result, @@ -344,7 +369,11 @@ fun NavGraphBuilder.groupNavigation( ) }, onNavigateToUserProfile = { userId -> - navController.navigateToUserProfile(userId) + if (myUserId != null && myUserId == userId) { + navController.navigate(FeedRoutes.My) + } else { + navController.navigate(FeedRoutes.Others(userId)) + } }, viewModel = viewModel ) diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/MyPageNavigation.kt b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/MyPageNavigation.kt index 8d8c6aad..9490615d 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/MyPageNavigation.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/MyPageNavigation.kt @@ -9,8 +9,10 @@ import com.texthip.thip.ui.mypage.screen.MyPageScreen import com.texthip.thip.ui.mypage.screen.MypageCustomerServiceScreen import com.texthip.thip.ui.mypage.screen.MypageSaveScreen import com.texthip.thip.ui.mypage.screen.NotificationScreen +import com.texthip.thip.ui.navigator.extensions.navigateToBookDetail import com.texthip.thip.ui.navigator.extensions.navigateToCustomerService import com.texthip.thip.ui.navigator.extensions.navigateToEditProfile +import com.texthip.thip.ui.navigator.extensions.navigateToFeedComment import com.texthip.thip.ui.navigator.extensions.navigateToLeaveThipScreen import com.texthip.thip.ui.navigator.extensions.navigateToNotificationSettings import com.texthip.thip.ui.navigator.extensions.navigateToSavedFeeds @@ -41,7 +43,13 @@ fun NavGraphBuilder.myPageNavigation( } composable { MypageSaveScreen( - onNavigateBack = { navController.popBackStack() } + onNavigateBack = { navController.popBackStack() }, + onBookClick = { isbn -> + navController.navigateToBookDetail(isbn) + }, + onFeedClick = { feedId -> + navController.navigateToFeedComment(feedId) + } ) } composable { diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/routes/FeedRoutes.kt b/app/src/main/java/com/texthip/thip/ui/navigator/routes/FeedRoutes.kt index e10fd236..0bb5e5fe 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/routes/FeedRoutes.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/routes/FeedRoutes.kt @@ -30,4 +30,7 @@ sealed class FeedRoutes : Routes() { @Serializable data class OthersSubscription(val userId: Long) : FeedRoutes() + + @Serializable + data object My : FeedRoutes() } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/theme/Color.kt b/app/src/main/java/com/texthip/thip/ui/theme/Color.kt index 41c82ba2..8101479c 100644 --- a/app/src/main/java/com/texthip/thip/ui/theme/Color.kt +++ b/app/src/main/java/com/texthip/thip/ui/theme/Color.kt @@ -40,6 +40,7 @@ val DarkGrey03 = Color(0xFF1D1D1D) val DarkGrey02 = Color(0xFF282828) val DarkGrey01 = Color(0x4B4B4B4B) val Black = Color(0xFF121212) +val Black80 = Color(0xCC121212) val Black50 = Color(0x80121212) val Black30 = Color(0x4D121212) val Black10 = Color(0x1A121212) @@ -82,6 +83,7 @@ data class ThipColors( val DarkGrey03: Color, val DarkGrey02: Color, val Black: Color, + val Black80: Color, val Black50: Color, val Black30: Color, val Black10: Color, @@ -123,6 +125,7 @@ val defaultThipColors = ThipColors( DarkGrey02 = DarkGrey02, Black = Black, Black50 = Black50, + Black80 = Black80, Black30 = Black30, Black10 = Black10, Black00 = Black00, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 922a7b94..2f6c4532 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -371,6 +371,7 @@ 내가 찾는 사용자를 검색해보세요. 글을 작성중이에요... 새 글 작성을 완료했어요! + 게시글 신고를 완료했어요.