From 29e528130e2ec3929088f62505e01b9eaca8d6cb Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Fri, 5 Sep 2025 14:20:54 +0900 Subject: [PATCH 01/10] =?UTF-8?q?[refactor]:=20=EB=B2=84=ED=8A=BC=20radius?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/texthip/thip/ui/feed/component/MySubscribelistBar.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt b/app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt index 0315a10c..8037a1b9 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt @@ -136,7 +136,7 @@ private fun EmptyMySubscriptionBar() { modifier = Modifier .fillMaxWidth() .height(42.dp) - .clip(RoundedCornerShape(8.dp)) + .clip(RoundedCornerShape(12.dp)) .background(colors.DarkGrey02) .clickable { } ) { From ef0389c5106318100d1007ff6c1f91c9b5148f5a Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Fri, 5 Sep 2025 14:57:32 +0900 Subject: [PATCH 02/10] =?UTF-8?q?[refactor]:=20=EC=B1=85=20=EC=9E=90?= =?UTF-8?q?=EC=84=B8=ED=9E=88=20=EB=B3=B4=EA=B8=B0=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=86=92=EC=9D=B4=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../search/screen/SearchBookDetailScreen.kt | 98 ++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) 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 86c2d61a..334792e6 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 @@ -53,6 +53,7 @@ import com.texthip.thip.ui.common.buttons.ActionMediumButton import com.texthip.thip.ui.common.modal.InfoPopup import com.texthip.thip.ui.common.topappbar.GradationTopAppBar import com.texthip.thip.ui.mypage.component.SavedFeedCard +import com.texthip.thip.ui.mypage.mock.FeedItem import com.texthip.thip.ui.search.component.SearchFilterButton import com.texthip.thip.ui.search.component.SearchFilterDropdownOverlay import com.texthip.thip.ui.search.viewmodel.BookDetailUiState @@ -398,7 +399,7 @@ private fun SearchBookDetailScreenContent( Box( modifier = Modifier .fillMaxWidth() - .height(30.dp) + .height(40.dp) .background( brush = Brush.verticalGradient( colors = listOf( @@ -459,7 +460,7 @@ private fun SearchBookDetailScreenContent( ) { index, feedItem -> val relatedFeedItem = uiState?.relatedFeeds?.getOrNull(index) - Spacer(modifier = Modifier.height(if (index == 0) 20.dp else 40.dp)) + Spacer(modifier = Modifier.height(if (index == 0) 0.dp else 40.dp)) SavedFeedCard( feedItem = feedItem, @@ -574,6 +575,99 @@ fun SearchBookDetailScreenContentSavedPreview() { } } +@Preview(showBackground = true) +@Composable +fun SearchBookDetailScreenContentWithFeedsPreview() { + val mockFeedItems = listOf( + FeedItem( + id = 1L, + userProfileImage = "https://example.com/profile1.jpg", + userName = "책읽는사람", + userRole = "문학 애호가", + bookTitle = "데미안", + authName = "헤르만 헤세", + timeAgo = "2시간 전", + content = "이 책을 읽으면서 진정한 자아를 찾아가는 과정에 대해 많은 생각을 하게 되었습니다. 싱클레어의 성장 과정이 현재의 나와 많이 닮아있다고 느꼈어요.", + likeCount = 24, + commentCount = 8, + isLiked = true, + isSaved = false, + imageUrls = listOf("https://example.com/image1.jpg") + ), + FeedItem( + id = 2L, + userProfileImage = "https://example.com/profile2.jpg", + userName = "철학독서가", + userRole = "인문학 탐구자", + bookTitle = "데미안", + authName = "헤르만 헤세", + timeAgo = "5시간 전", + content = "헤세의 작품 중에서도 가장 깊이 있는 성찰을 담고 있는 작품이라고 생각합니다. 선악을 넘어선 인간 내면의 복잡성을 이해하는 데 큰 도움이 되었습니다.", + likeCount = 18, + commentCount = 12, + isLiked = false, + isSaved = true, + imageUrls = emptyList() + ), + FeedItem( + id = 3L, + userProfileImage = "https://example.com/profile3.jpg", + userName = "문학소녀", + userRole = "소설 리뷰어", + bookTitle = "데미안", + authName = "헤르만 헤세", + timeAgo = "1일 전", + content = "청소년기에 읽었을 때와 성인이 되어 다시 읽었을 때의 감상이 완전히 달랐습니다. 나이가 들수록 더 깊이 이해되는 작품이네요.\n\n특히 데미안이라는 인물이 주는 메시지가 인상 깊었어요.", + likeCount = 31, + commentCount = 15, + isLiked = true, + isSaved = true, + imageUrls = listOf( + "https://example.com/image2.jpg", + "https://example.com/image3.jpg" + ) + ) + ) + + val mockUiState = BookDetailUiState( + bookDetail = mockBookDetail, + relatedFeeds = emptyList(), // feedItems로 변환되므로 빈 리스트 + isLoadingFeeds = false, + isLoadingMore = false, + currentSort = "like" + ).copy( + // feedItems를 직접 설정하기 위해 relatedFeeds를 임시로 설정 + relatedFeeds = mockFeedItems.map { feedItem -> + com.texthip.thip.data.model.feed.response.RelatedFeedItem( + feedId = feedItem.id.toInt(), + creatorId = feedItem.id.toInt(), + creatorNickname = feedItem.userName, + creatorProfileImageUrl = feedItem.userProfileImage, + aliasName = feedItem.userRole, + aliasColor = "#FF6B9D", + postDate = feedItem.timeAgo, + isbn = mockBookDetail.isbn, + bookTitle = feedItem.bookTitle, + bookAuthor = feedItem.authName, + contentBody = feedItem.content, + contentUrls = feedItem.imageUrls, + likeCount = feedItem.likeCount, + commentCount = feedItem.commentCount, + isSaved = feedItem.isSaved, + isLiked = feedItem.isLiked, + isWriter = false + ) + } + ) + + ThipTheme { + SearchBookDetailScreenContent( + bookDetail = mockBookDetail, + uiState = mockUiState + ) + } +} + @Preview(showBackground = true) @Composable fun SearchBookDetailScreenContentErrorPreview() { From e1d5981534b2a5229004ba2f3617c88cb4b2fe0e Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Fri, 5 Sep 2025 16:19:39 +0900 Subject: [PATCH 03/10] =?UTF-8?q?[ui]:=20=EC=95=8C=EB=A6=BC=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20UI=20=EB=B0=8F=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=88=98=EC=A0=95=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component}/CardAlarm.kt | 37 +++++++++++-------- .../ui/common/alarmpage/screen/AlarmScreen.kt | 2 +- .../alarmpage/viewmodel/AlarmViewModel.kt | 1 - .../ui/mypage/screen/MypageReactionScreen.kt | 3 +- 4 files changed, 24 insertions(+), 19 deletions(-) rename app/src/main/java/com/texthip/thip/ui/common/{cards => alarmpage/component}/CardAlarm.kt (86%) diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/CardAlarm.kt similarity index 86% rename from app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt rename to app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/CardAlarm.kt index 71e90ff4..4bc909f2 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/CardAlarm.kt @@ -1,4 +1,4 @@ -package com.texthip.thip.ui.common.cards +package com.texthip.thip.ui.common.alarmpage.component import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -111,18 +111,25 @@ fun CardAlarm( Column( horizontalAlignment = Alignment.End ) { - // 안읽음 상태일 때만 빨간 점 - if (!isRead) { - Box( - modifier = Modifier - .size(6.dp) - .clip(RoundedCornerShape(3.dp)) - .background(color = colors.Red) - ) + // 빨간 점을 위한 고정 공간 (항상 6dp 높이 유지) + Box( + modifier = Modifier + .size(6.dp), + contentAlignment = Alignment.Center + ) { + // 안읽음 상태일 때만 빨간 점 표시 + if (!isRead) { + Box( + modifier = Modifier + .size(6.dp) + .clip(RoundedCornerShape(3.dp)) + .background(color = colors.Red) + ) + } } Text( - text = timeAgo + stringResource(R.string.time_ago), + text = timeAgo, style = typography.timedate_r400_s11, color = if (isRead) colors.Grey02 else colors.Grey01, modifier = Modifier @@ -161,7 +168,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "모임", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = isRead ) { isRead = true @@ -172,7 +179,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "모임", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = true ) @@ -180,7 +187,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "피드", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = false ) @@ -188,7 +195,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "좋아요", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = isRead ) @@ -196,7 +203,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "댓글", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = isRead ) } diff --git a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt index 9d80da0e..3044e2e5 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.common.alarmpage.component.AlarmFilterRow import com.texthip.thip.ui.common.alarmpage.mock.AlarmItem -import com.texthip.thip.ui.common.cards.CardAlarm +import com.texthip.thip.ui.common.alarmpage.component.CardAlarm import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors diff --git a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt index c1e31f27..efa44466 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt @@ -15,7 +15,6 @@ class AlarmViewModel : ViewModel() { _alarmItems.value = listOf( AlarmItem(1, "피드", "내 글을 좋아합니다.", "user123님이 내 글에 좋아요를 눌렀어요.", "2시간 전", false), AlarmItem(2, "모임", "같이 읽기를 시작했어요!", "모임방에서 20분 동안 같이 읽기가 시작되었어요!", "7시간 전", false), - AlarmItem(3, "피드", "내 글에 댓글이 달렸어요.", "user1: 진짜 공감합니다!", "2025.01.12", true), AlarmItem(4, "모임", "투표가 시작되었어요!", "투표지를 먼저 열람합니다.", "17시간 전", false), AlarmItem(5, "피드", "팔로워가 새 글을 올렸어요.", "user456님이 새 리뷰를 작성했습니다.", "1일 전", true), AlarmItem(6, "모임", "새로운 모임방 초대", "호르몬 체인지 완독하는 방에 초대되었습니다.", "2일 전", false) diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt index d4b33d78..d41a5d88 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -24,7 +23,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.common.buttons.OptionChipButton -import com.texthip.thip.ui.common.cards.CardAlarm +import com.texthip.thip.ui.common.alarmpage.component.CardAlarm import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar import com.texthip.thip.ui.mypage.mock.ReactionItem import com.texthip.thip.ui.theme.ThipTheme From 9d53b24a1cb354c45911e1e766e15ded4aa93d48 Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Fri, 5 Sep 2025 14:20:54 +0900 Subject: [PATCH 04/10] =?UTF-8?q?[refactor]:=20=EB=B2=84=ED=8A=BC=20radius?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/texthip/thip/ui/feed/component/MySubscribelistBar.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt b/app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt index 0315a10c..8037a1b9 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt @@ -136,7 +136,7 @@ private fun EmptyMySubscriptionBar() { modifier = Modifier .fillMaxWidth() .height(42.dp) - .clip(RoundedCornerShape(8.dp)) + .clip(RoundedCornerShape(12.dp)) .background(colors.DarkGrey02) .clickable { } ) { From eddfa6c4b274abc7a0d9069da9961933234843ff Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Fri, 5 Sep 2025 14:57:32 +0900 Subject: [PATCH 05/10] =?UTF-8?q?[refactor]:=20=EC=B1=85=20=EC=9E=90?= =?UTF-8?q?=EC=84=B8=ED=9E=88=20=EB=B3=B4=EA=B8=B0=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=86=92=EC=9D=B4=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../search/screen/SearchBookDetailScreen.kt | 98 ++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) 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 86c2d61a..334792e6 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 @@ -53,6 +53,7 @@ import com.texthip.thip.ui.common.buttons.ActionMediumButton import com.texthip.thip.ui.common.modal.InfoPopup import com.texthip.thip.ui.common.topappbar.GradationTopAppBar import com.texthip.thip.ui.mypage.component.SavedFeedCard +import com.texthip.thip.ui.mypage.mock.FeedItem import com.texthip.thip.ui.search.component.SearchFilterButton import com.texthip.thip.ui.search.component.SearchFilterDropdownOverlay import com.texthip.thip.ui.search.viewmodel.BookDetailUiState @@ -398,7 +399,7 @@ private fun SearchBookDetailScreenContent( Box( modifier = Modifier .fillMaxWidth() - .height(30.dp) + .height(40.dp) .background( brush = Brush.verticalGradient( colors = listOf( @@ -459,7 +460,7 @@ private fun SearchBookDetailScreenContent( ) { index, feedItem -> val relatedFeedItem = uiState?.relatedFeeds?.getOrNull(index) - Spacer(modifier = Modifier.height(if (index == 0) 20.dp else 40.dp)) + Spacer(modifier = Modifier.height(if (index == 0) 0.dp else 40.dp)) SavedFeedCard( feedItem = feedItem, @@ -574,6 +575,99 @@ fun SearchBookDetailScreenContentSavedPreview() { } } +@Preview(showBackground = true) +@Composable +fun SearchBookDetailScreenContentWithFeedsPreview() { + val mockFeedItems = listOf( + FeedItem( + id = 1L, + userProfileImage = "https://example.com/profile1.jpg", + userName = "책읽는사람", + userRole = "문학 애호가", + bookTitle = "데미안", + authName = "헤르만 헤세", + timeAgo = "2시간 전", + content = "이 책을 읽으면서 진정한 자아를 찾아가는 과정에 대해 많은 생각을 하게 되었습니다. 싱클레어의 성장 과정이 현재의 나와 많이 닮아있다고 느꼈어요.", + likeCount = 24, + commentCount = 8, + isLiked = true, + isSaved = false, + imageUrls = listOf("https://example.com/image1.jpg") + ), + FeedItem( + id = 2L, + userProfileImage = "https://example.com/profile2.jpg", + userName = "철학독서가", + userRole = "인문학 탐구자", + bookTitle = "데미안", + authName = "헤르만 헤세", + timeAgo = "5시간 전", + content = "헤세의 작품 중에서도 가장 깊이 있는 성찰을 담고 있는 작품이라고 생각합니다. 선악을 넘어선 인간 내면의 복잡성을 이해하는 데 큰 도움이 되었습니다.", + likeCount = 18, + commentCount = 12, + isLiked = false, + isSaved = true, + imageUrls = emptyList() + ), + FeedItem( + id = 3L, + userProfileImage = "https://example.com/profile3.jpg", + userName = "문학소녀", + userRole = "소설 리뷰어", + bookTitle = "데미안", + authName = "헤르만 헤세", + timeAgo = "1일 전", + content = "청소년기에 읽었을 때와 성인이 되어 다시 읽었을 때의 감상이 완전히 달랐습니다. 나이가 들수록 더 깊이 이해되는 작품이네요.\n\n특히 데미안이라는 인물이 주는 메시지가 인상 깊었어요.", + likeCount = 31, + commentCount = 15, + isLiked = true, + isSaved = true, + imageUrls = listOf( + "https://example.com/image2.jpg", + "https://example.com/image3.jpg" + ) + ) + ) + + val mockUiState = BookDetailUiState( + bookDetail = mockBookDetail, + relatedFeeds = emptyList(), // feedItems로 변환되므로 빈 리스트 + isLoadingFeeds = false, + isLoadingMore = false, + currentSort = "like" + ).copy( + // feedItems를 직접 설정하기 위해 relatedFeeds를 임시로 설정 + relatedFeeds = mockFeedItems.map { feedItem -> + com.texthip.thip.data.model.feed.response.RelatedFeedItem( + feedId = feedItem.id.toInt(), + creatorId = feedItem.id.toInt(), + creatorNickname = feedItem.userName, + creatorProfileImageUrl = feedItem.userProfileImage, + aliasName = feedItem.userRole, + aliasColor = "#FF6B9D", + postDate = feedItem.timeAgo, + isbn = mockBookDetail.isbn, + bookTitle = feedItem.bookTitle, + bookAuthor = feedItem.authName, + contentBody = feedItem.content, + contentUrls = feedItem.imageUrls, + likeCount = feedItem.likeCount, + commentCount = feedItem.commentCount, + isSaved = feedItem.isSaved, + isLiked = feedItem.isLiked, + isWriter = false + ) + } + ) + + ThipTheme { + SearchBookDetailScreenContent( + bookDetail = mockBookDetail, + uiState = mockUiState + ) + } +} + @Preview(showBackground = true) @Composable fun SearchBookDetailScreenContentErrorPreview() { From 6c1d6e7c6632d4711a9164fe3664f03b5335bad2 Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Fri, 5 Sep 2025 16:19:39 +0900 Subject: [PATCH 06/10] =?UTF-8?q?[ui]:=20=EC=95=8C=EB=A6=BC=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20UI=20=EB=B0=8F=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=88=98=EC=A0=95=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component}/CardAlarm.kt | 37 +++++++++++-------- .../ui/common/alarmpage/screen/AlarmScreen.kt | 2 +- .../alarmpage/viewmodel/AlarmViewModel.kt | 1 - .../ui/mypage/screen/MypageReactionScreen.kt | 3 +- 4 files changed, 24 insertions(+), 19 deletions(-) rename app/src/main/java/com/texthip/thip/ui/common/{cards => alarmpage/component}/CardAlarm.kt (86%) diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/CardAlarm.kt similarity index 86% rename from app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt rename to app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/CardAlarm.kt index 71e90ff4..4bc909f2 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/CardAlarm.kt @@ -1,4 +1,4 @@ -package com.texthip.thip.ui.common.cards +package com.texthip.thip.ui.common.alarmpage.component import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -111,18 +111,25 @@ fun CardAlarm( Column( horizontalAlignment = Alignment.End ) { - // 안읽음 상태일 때만 빨간 점 - if (!isRead) { - Box( - modifier = Modifier - .size(6.dp) - .clip(RoundedCornerShape(3.dp)) - .background(color = colors.Red) - ) + // 빨간 점을 위한 고정 공간 (항상 6dp 높이 유지) + Box( + modifier = Modifier + .size(6.dp), + contentAlignment = Alignment.Center + ) { + // 안읽음 상태일 때만 빨간 점 표시 + if (!isRead) { + Box( + modifier = Modifier + .size(6.dp) + .clip(RoundedCornerShape(3.dp)) + .background(color = colors.Red) + ) + } } Text( - text = timeAgo + stringResource(R.string.time_ago), + text = timeAgo, style = typography.timedate_r400_s11, color = if (isRead) colors.Grey02 else colors.Grey01, modifier = Modifier @@ -161,7 +168,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "모임", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = isRead ) { isRead = true @@ -172,7 +179,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "모임", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = true ) @@ -180,7 +187,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "피드", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = false ) @@ -188,7 +195,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "좋아요", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = isRead ) @@ -196,7 +203,7 @@ fun PreviewNotificationCards() { title = "같이 읽기를 시작했어요!", badgeText = "댓글", message = "한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다. 한줄만 입력이 가능합니다.", - timeAgo = "12", + timeAgo = "12시간 전", isRead = isRead ) } diff --git a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt index 9d80da0e..3044e2e5 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.common.alarmpage.component.AlarmFilterRow import com.texthip.thip.ui.common.alarmpage.mock.AlarmItem -import com.texthip.thip.ui.common.cards.CardAlarm +import com.texthip.thip.ui.common.alarmpage.component.CardAlarm import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors diff --git a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt index c1e31f27..efa44466 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt @@ -15,7 +15,6 @@ class AlarmViewModel : ViewModel() { _alarmItems.value = listOf( AlarmItem(1, "피드", "내 글을 좋아합니다.", "user123님이 내 글에 좋아요를 눌렀어요.", "2시간 전", false), AlarmItem(2, "모임", "같이 읽기를 시작했어요!", "모임방에서 20분 동안 같이 읽기가 시작되었어요!", "7시간 전", false), - AlarmItem(3, "피드", "내 글에 댓글이 달렸어요.", "user1: 진짜 공감합니다!", "2025.01.12", true), AlarmItem(4, "모임", "투표가 시작되었어요!", "투표지를 먼저 열람합니다.", "17시간 전", false), AlarmItem(5, "피드", "팔로워가 새 글을 올렸어요.", "user456님이 새 리뷰를 작성했습니다.", "1일 전", true), AlarmItem(6, "모임", "새로운 모임방 초대", "호르몬 체인지 완독하는 방에 초대되었습니다.", "2일 전", false) diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt index d4b33d78..d41a5d88 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -24,7 +23,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.common.buttons.OptionChipButton -import com.texthip.thip.ui.common.cards.CardAlarm +import com.texthip.thip.ui.common.alarmpage.component.CardAlarm import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar import com.texthip.thip.ui.mypage.mock.ReactionItem import com.texthip.thip.ui.theme.ThipTheme From 7816e5ef01bd307eb34298b8187aa464ddd53379 Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Mon, 8 Sep 2025 01:51:18 +0900 Subject: [PATCH 07/10] =?UTF-8?q?[refactor]:=20=EB=B0=B1=EC=97=85=EC=9D=84?= =?UTF-8?q?=20false=EB=A1=9C=20=EC=84=A4=EC=A0=95=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=EC=9D=B4=20=EC=A0=80=EC=9E=A5=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 98023dfb..2fe2f65a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,7 +6,7 @@ Date: Tue, 9 Sep 2025 22:24:47 +0900 Subject: [PATCH 08/10] =?UTF-8?q?[refactor]:=20401=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EA=B0=80=20=EB=93=A4=EC=96=B4=EC=99=94=EC=9D=84=EB=95=8C=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/texthip/thip/MainActivity.kt | 18 ++++++++++++++++-- .../thip/data/manager/AuthStateManager.kt | 16 ++++++++++++++++ .../thip/utils/auth/AuthInterceptor.kt | 19 ++++++++++++++----- 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/com/texthip/thip/data/manager/AuthStateManager.kt diff --git a/app/src/main/java/com/texthip/thip/MainActivity.kt b/app/src/main/java/com/texthip/thip/MainActivity.kt index a6e16e42..4e86f830 100644 --- a/app/src/main/java/com/texthip/thip/MainActivity.kt +++ b/app/src/main/java/com/texthip/thip/MainActivity.kt @@ -5,27 +5,32 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import com.texthip.thip.data.manager.AuthStateManager import com.texthip.thip.data.manager.TokenManager import com.texthip.thip.ui.navigator.navigations.authNavigation import com.texthip.thip.ui.navigator.routes.CommonRoutes import com.texthip.thip.ui.theme.ThipTheme import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.collectLatest import javax.inject.Inject @AndroidEntryPoint class MainActivity : ComponentActivity() { @Inject lateinit var tokenManager: TokenManager + @Inject + lateinit var authStateManager: AuthStateManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { ThipTheme { - RootNavHost() + RootNavHost(authStateManager) } } // getKakaoKeyHash(this) @@ -33,8 +38,17 @@ class MainActivity : ComponentActivity() { } @Composable -fun RootNavHost() { +fun RootNavHost(authStateManager: AuthStateManager) { val navController = rememberNavController() + + LaunchedEffect(Unit) { + authStateManager.tokenExpiredEvent.collectLatest { + navController.navigate(CommonRoutes.Login) { + popUpTo(0) { inclusive = true } + } + } + } + NavHost( navController = navController, startDestination = CommonRoutes.Splash diff --git a/app/src/main/java/com/texthip/thip/data/manager/AuthStateManager.kt b/app/src/main/java/com/texthip/thip/data/manager/AuthStateManager.kt new file mode 100644 index 00000000..c6420b0b --- /dev/null +++ b/app/src/main/java/com/texthip/thip/data/manager/AuthStateManager.kt @@ -0,0 +1,16 @@ +package com.texthip.thip.data.manager + +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class AuthStateManager @Inject constructor() { + private val _tokenExpiredEvent = MutableSharedFlow(extraBufferCapacity = 1) + val tokenExpiredEvent = _tokenExpiredEvent.asSharedFlow() + + fun triggerTokenExpired() { + _tokenExpiredEvent.tryEmit(Unit) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/utils/auth/AuthInterceptor.kt b/app/src/main/java/com/texthip/thip/utils/auth/AuthInterceptor.kt index 71e9f700..8d5865e4 100644 --- a/app/src/main/java/com/texthip/thip/utils/auth/AuthInterceptor.kt +++ b/app/src/main/java/com/texthip/thip/utils/auth/AuthInterceptor.kt @@ -1,5 +1,6 @@ package com.texthip.thip.utils.auth +import com.texthip.thip.data.manager.AuthStateManager import com.texthip.thip.data.manager.TokenManager import kotlinx.coroutines.runBlocking import okhttp3.Interceptor @@ -7,7 +8,8 @@ import okhttp3.Response import javax.inject.Inject class AuthInterceptor @Inject constructor( - private val tokenManager: TokenManager + private val tokenManager: TokenManager, + private val authStateManager: AuthStateManager ) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val original = chain.request() @@ -16,18 +18,25 @@ class AuthInterceptor @Inject constructor( return chain.proceed(original) } - // 1. 정식 토큰을 먼저 확인합니다. val token = runBlocking { tokenManager.getTokenOnce() } - // 2. 정식 토큰이 없으면, 임시 토큰을 확인합니다. val tempToken = runBlocking { tokenManager.getTempTokenOnce() } - // 보낼 토큰을 결정합니다 (정식 토큰 우선). val tokenToSend = token ?: tempToken val newRequest = original.newBuilder().apply { tokenToSend?.let { addHeader("Authorization", "Bearer $it") } }.build() - return chain.proceed(newRequest) + val response = chain.proceed(newRequest) + + // 401 응답 처리 + if (response.code == 401) { + runBlocking { + tokenManager.clearTokens() + authStateManager.triggerTokenExpired() + } + } + + return response } } From 895ffd3c700d7315b5f6cd5b1581d4e666cbb683 Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Thu, 11 Sep 2025 02:02:31 +0900 Subject: [PATCH 09/10] =?UTF-8?q?[feat]:=20=ED=9A=8C=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20service,=20Repository=20=EA=B5=AC=ED=98=84=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/texthip/thip/data/repository/UserRepository.kt | 6 ++++++ .../main/java/com/texthip/thip/data/service/UserService.kt | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/app/src/main/java/com/texthip/thip/data/repository/UserRepository.kt b/app/src/main/java/com/texthip/thip/data/repository/UserRepository.kt index 96afd970..dc7dfe02 100644 --- a/app/src/main/java/com/texthip/thip/data/repository/UserRepository.kt +++ b/app/src/main/java/com/texthip/thip/data/repository/UserRepository.kt @@ -137,4 +137,10 @@ class UserRepository @Inject constructor( .handleBaseResponse() .getOrThrow() } + + suspend fun deleteAccount(): Result = runCatching { + userService.deleteAccount() + .handleBaseResponse() + .getOrThrow() + } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/data/service/UserService.kt b/app/src/main/java/com/texthip/thip/data/service/UserService.kt index a8149f6c..064180ae 100644 --- a/app/src/main/java/com/texthip/thip/data/service/UserService.kt +++ b/app/src/main/java/com/texthip/thip/data/service/UserService.kt @@ -15,6 +15,7 @@ import com.texthip.thip.data.model.users.response.SignupResponse import com.texthip.thip.data.model.users.response.UserSearchResponse import com.texthip.thip.data.model.users.response.UsersMyFollowingsRecentFeedsResponse import retrofit2.http.Body +import retrofit2.http.DELETE import retrofit2.http.GET import retrofit2.http.Header import retrofit2.http.PATCH @@ -74,4 +75,7 @@ interface UserService { @Query("size") size: Int = 30 ): BaseResponse + @DELETE("users") + suspend fun deleteAccount(): BaseResponse + } \ No newline at end of file From 9ba1d7693e5a786fa16361e1d2b30041e78b3c37 Mon Sep 17 00:00:00 2001 From: rbqks529 Date: Thu, 11 Sep 2025 02:03:41 +0900 Subject: [PATCH 10/10] =?UTF-8?q?[feat]:=20=ED=9A=8C=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=20(#131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/mypage/screen/MypageLeavethipScreen.kt | 43 +++++++++++- .../viewmodel/DeleteAccountViewModel.kt | 70 +++++++++++++++++++ .../navigator/navigations/MyPageNavigation.kt | 3 +- 3 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/DeleteAccountViewModel.kt diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageLeavethipScreen.kt b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageLeavethipScreen.kt index 7b6d8172..e5d621c2 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageLeavethipScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageLeavethipScreen.kt @@ -1,5 +1,6 @@ package com.texthip.thip.ui.mypage.screen +import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -12,15 +13,18 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle @@ -29,10 +33,13 @@ import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.texthip.thip.R import com.texthip.thip.ui.common.buttons.CheckboxButton import com.texthip.thip.ui.common.modal.DialogPopup import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.mypage.viewmodel.DeleteAccountViewModel import com.texthip.thip.ui.theme.DarkGrey02 import com.texthip.thip.ui.theme.Red import com.texthip.thip.ui.theme.ThipTheme.colors @@ -40,11 +47,30 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun DeleteAccountScreen( - onNavigateBack: () -> Unit + onNavigateBack: () -> Unit, + onNavigateToLogin: () -> Unit, + viewModel: DeleteAccountViewModel = hiltViewModel() ) { + val context = LocalContext.current + val uiState = viewModel.uiState.collectAsStateWithLifecycle().value + var isChecked by rememberSaveable { mutableStateOf(false) } val backgroundColor = if (isChecked) colors.Purple else colors.Grey02 var isDialogVisible by rememberSaveable { mutableStateOf(false) } + + // 회원탈퇴 완료 시 로그인 화면으로 이동 + LaunchedEffect(uiState.isDeleteCompleted) { + if (uiState.isDeleteCompleted) { + onNavigateToLogin() + } + } + + // 에러 메시지 표시 + LaunchedEffect(uiState.errorMessage) { + uiState.errorMessage?.let { message -> + Toast.makeText(context, message, Toast.LENGTH_SHORT).show() + } + } Column( Modifier @@ -159,12 +185,22 @@ fun DeleteAccountScreen( onCancel = { isDialogVisible = false }, onConfirm = { isDialogVisible = false - // TODO: 회원탈퇴 로직 + viewModel.deleteAccount(context) } ) } } } + + // 로딩 중일 때 전체 화면에 로딩 인디케이터 표시 + if (uiState.isLoading) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } } } @@ -172,6 +208,7 @@ fun DeleteAccountScreen( @Composable private fun DeleteAccountScreenPrev() { DeleteAccountScreen( - onNavigateBack = {} + onNavigateBack = {}, + onNavigateToLogin = {} ) } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/DeleteAccountViewModel.kt b/app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/DeleteAccountViewModel.kt new file mode 100644 index 00000000..ca342618 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/DeleteAccountViewModel.kt @@ -0,0 +1,70 @@ +package com.texthip.thip.ui.mypage.viewmodel + +import android.content.Context +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.google.android.gms.auth.api.signin.GoogleSignIn +import com.google.android.gms.auth.api.signin.GoogleSignInOptions +import com.kakao.sdk.user.UserApiClient +import com.texthip.thip.data.manager.TokenManager +import com.texthip.thip.data.repository.UserRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +data class DeleteAccountUiState( + val isLoading: Boolean = false, + val isDeleteCompleted: Boolean = false, + val errorMessage: String? = null +) + +@HiltViewModel +class DeleteAccountViewModel @Inject constructor( + private val userRepository: UserRepository, + private val tokenManager: TokenManager +) : ViewModel() { + + private val _uiState = MutableStateFlow(DeleteAccountUiState()) + val uiState = _uiState.asStateFlow() + + fun deleteAccount(context: Context) { + viewModelScope.launch { + _uiState.update { it.copy(isLoading = true, errorMessage = null) } + + // 1. 서버에 회원탈퇴 요청 + userRepository.deleteAccount() + .onSuccess { + // 2. 서버 요청 성공 후 토큰 삭제 + tokenManager.clearTokens() + + // 3. 카카오 SDK에서 연결 끊기 + UserApiClient.instance.unlink { error -> + if (error != null) { + Log.e("DeleteAccountViewModel", "카카오 연결 끊기 실패", error) + } else { + Log.d("DeleteAccountViewModel", "카카오 연결 끊기 성공") + } + } + + // 4. 구글 SDK에서 로그아웃 + val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build() + GoogleSignIn.getClient(context, gso).signOut() + + _uiState.update { it.copy(isLoading = false, isDeleteCompleted = true) } + } + .onFailure { exception -> + Log.e("DeleteAccountViewModel", "회원탈퇴 실패", exception) + _uiState.update { + it.copy( + isLoading = false, + errorMessage = exception.message ?: "회원탈퇴에 실패했습니다." + ) + } + } + } + } +} \ No newline at end of file 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 9490615d..879b9505 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 @@ -59,7 +59,8 @@ fun NavGraphBuilder.myPageNavigation( } composable { DeleteAccountScreen( - onNavigateBack = { navController.popBackStack() } + onNavigateBack = { navController.popBackStack() }, + onNavigateToLogin = onNavigateToLogin ) } composable {