From 7ce2517a76c32ad493fdb05521fc5bd835f958d3 Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 21:24:26 +0900 Subject: [PATCH 01/13] =?UTF-8?q?[feat]:=20=EB=82=B4=20=ED=8C=94=EB=A1=9C?= =?UTF-8?q?=EC=9E=89=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20dto(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/model/users/MyFollowingsResponse.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/data/model/users/MyFollowingsResponse.kt diff --git a/app/src/main/java/com/texthip/thip/data/model/users/MyFollowingsResponse.kt b/app/src/main/java/com/texthip/thip/data/model/users/MyFollowingsResponse.kt new file mode 100644 index 00000000..d439f7e6 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/data/model/users/MyFollowingsResponse.kt @@ -0,0 +1,22 @@ +package com.texthip.thip.data.model.users + +import com.google.gson.annotations.SerializedName +import kotlinx.serialization.Serializable + +@Serializable +data class MyFollowingsResponse( + @SerializedName("followings") val followings: List, + @SerializedName("totalFollowingCount") val totalFollowingCount: Int, + @SerializedName("nextCursor") val nextCursor: String?, + @SerializedName("isLast") val isLast: Boolean +) + +@Serializable +data class FollowingDto( + @SerializedName("userId") val userId: Int, + @SerializedName("nickname") val nickname: String, + @SerializedName("profileImageUrl") val profileImageUrl: String?, + @SerializedName("aliasName") val aliasName: String, + @SerializedName("aliasColor") val aliasColor: String, + @SerializedName("isFollowing") val isFollowing: Boolean +) From 4876dc9fc6b5585edc964cf878f58508453c2603 Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 21:24:45 +0900 Subject: [PATCH 02/13] =?UTF-8?q?[feat]:=20user=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4,=20=EB=A0=88=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/data/repository/UserRepository.kt | 21 +++++++++++++++++++ .../texthip/thip/data/service/UserService.kt | 17 +++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/data/repository/UserRepository.kt create mode 100644 app/src/main/java/com/texthip/thip/data/service/UserService.kt 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 new file mode 100644 index 00000000..e048f8cb --- /dev/null +++ b/app/src/main/java/com/texthip/thip/data/repository/UserRepository.kt @@ -0,0 +1,21 @@ +package com.texthip.thip.data.repository + +import com.texthip.thip.data.model.base.handleBaseResponse +import com.texthip.thip.data.model.users.MyFollowingsResponse +import com.texthip.thip.data.service.UserService +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UserRepository@Inject constructor( + private val userService: UserService +) { + suspend fun getMyFollowings( + cursor: String?, + size: Int = 10 + ): Result = runCatching { + userService.getMyFollowings(cursor = cursor, size = size) + .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 new file mode 100644 index 00000000..b2c1f429 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/data/service/UserService.kt @@ -0,0 +1,17 @@ +package com.texthip.thip.data.service + +import com.texthip.thip.data.model.base.BaseResponse +import com.texthip.thip.data.model.rooms.response.RoomsUsersResponse +import com.texthip.thip.data.model.users.MyFollowingsResponse +import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Query + +interface UserService { + @GET("users/my-followings") + suspend fun getMyFollowings( + @Query("size") size: Int = 10, + @Query("cursor") cursor: String? = null + ): BaseResponse + +} \ No newline at end of file From dcb3844cac77428756696a119b66bce39b5ccd20 Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 21:25:12 +0900 Subject: [PATCH 03/13] =?UTF-8?q?[feat]:=20=EB=82=B4=20=ED=8C=94=EB=A1=9C?= =?UTF-8?q?=EC=9E=89=20=EB=AA=A9=EB=A1=9D=20=EB=B7=B0=EB=AA=A8=EB=8D=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/viewmodel/MySubscriptionViewModel.kt | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt diff --git a/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt b/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt new file mode 100644 index 00000000..020d47d6 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt @@ -0,0 +1,119 @@ +package com.texthip.thip.ui.feed.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +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 MySubscriptionUiState( + val isLoading: Boolean = false, + val followings: List = emptyList(), + val totalCount: Int = 0, + val isLastPage: Boolean = false, + val errorMessage: String? = null, + val showToast: Boolean = false, + val toastMessage: String = "" +) + +data class MyFollowingUiModel( + val userId: Int, + val profileImageUrl: String?, + val nickname: String, + val aliasName: String, + val aliasColor: String, + var isFollowing: Boolean +) + +@HiltViewModel +class MySubscriptionViewModel @Inject constructor( + private val userRepository: UserRepository +) : ViewModel() { + + private val _uiState = MutableStateFlow(MySubscriptionUiState()) + val uiState = _uiState.asStateFlow() + + private var nextCursor: String? = null + + init { + //ViewModel 생성될 때 첫 페이지 데이터를 로드 + fetchMyFollowings(isInitial = true) + } + + + fun fetchMyFollowings(isInitial: Boolean = false) { + if (_uiState.value.isLoading || (!isInitial && _uiState.value.isLastPage)) { + return + } + + viewModelScope.launch { + _uiState.update { it.copy(isLoading = true) } + val cursorToFetch = if (isInitial) null else nextCursor + + val result = userRepository.getMyFollowings(cursor = cursorToFetch) + + result.onSuccess { data -> + //data가 null이 아닐 경우에만 상태 업데이트 + data?.let { + val newFollowings = it.followings.map { dto -> + MyFollowingUiModel( + userId = dto.userId, + profileImageUrl = dto.profileImageUrl, + nickname = dto.nickname, + aliasName = dto.aliasName, + aliasColor = dto.aliasColor, + isFollowing = dto.isFollowing + ) + } + nextCursor = it.nextCursor + + _uiState.update { currentState -> + currentState.copy( + isLoading = false, + followings = if (isInitial) newFollowings else currentState.followings + newFollowings, + totalCount = it.totalFollowingCount, + isLastPage = it.isLast + ) + } + } ?: _uiState.update { + // 데이터가 null인 경우 (성공했지만 내용이 없는 케이스) + it.copy(isLoading = false, errorMessage = "응답 데이터가 비어있습니다.") + } + }.onFailure { exception -> + // 실패 시 예외 처리 + _uiState.update { + it.copy(isLoading = false, errorMessage = exception.message) + } + } + } + } + + + fun toggleFollow(userId: Int, followedMessage: String, unfollowedMessage: String) { + // TODO: 실제 팔로우/언팔로우 API를 호출 로직 + var toastMsg = "" + _uiState.update { currentState -> + val updatedList = currentState.followings.map { user -> + if (user.userId == userId) { + val isNowFollowing = !user.isFollowing + toastMsg = if (isNowFollowing) followedMessage else unfollowedMessage + user.copy(isFollowing = isNowFollowing) + } else { + user + } + } + currentState.copy( + followings = updatedList, + showToast = true, + toastMessage = toastMsg + ) + } + } + fun hideToast() { + _uiState.update { it.copy(showToast = false) } + } +} \ No newline at end of file From e0d94ccc8219ecf2d274ebb233ba712addf4bfab Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 21:25:41 +0900 Subject: [PATCH 04/13] =?UTF-8?q?[feat]:=20AuthorHeader=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EC=99=B8=EB=B6=80=EC=97=90=EC=84=9C=20=EB=B0=9B?= =?UTF-8?q?=EC=95=84=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#7?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/texthip/thip/ui/common/header/AuthorHeader.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt b/app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt index 36cef65b..94b4c152 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt @@ -29,6 +29,7 @@ import com.texthip.thip.ui.common.buttons.OutlinedButton import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography +import androidx.compose.ui.graphics.Color @Composable fun AuthorHeader( @@ -36,6 +37,7 @@ fun AuthorHeader( profileImage: String?, nickname: String, badgeText: String, + badgeTextColor: Color = colors.NeonGreen, buttonText: String = "", buttonWidth: Dp = 60.dp, showButton: Boolean = true, @@ -80,7 +82,7 @@ fun AuthorHeader( Text( text = badgeText, style = typography.feedcopy_r400_s14_h20, - color = colors.NeonGreen, + color = badgeTextColor, maxLines = 1 ) } @@ -131,6 +133,7 @@ fun PreviewAuthorHeader() { profileImage = null, nickname = "열자자제한열열자제한", badgeText = "칭호칭호칭호", + badgeTextColor = colors.Yellow, showButton = false, showThipNum = true, thipNum = 10, From bf05950eca291b661c5fe1d96f1583f1ecb6690e Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 21:26:14 +0900 Subject: [PATCH 05/13] =?UTF-8?q?[feat]:=20=EB=82=B4=20=ED=8C=94=EB=A1=9C?= =?UTF-8?q?=EC=9E=89=20=EB=AA=A9=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EC=88=98=EC=A0=95=20->=20screen,=20content?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC=20(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/screen/MySubscriptionListScreen.kt | 280 +++++++++--------- 1 file changed, 145 insertions(+), 135 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt index 1eed1583..8ee16dc6 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt @@ -3,216 +3,226 @@ package com.texthip.thip.ui.feed.screen import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.Text +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +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.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -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.graphics.Color import androidx.compose.ui.platform.LocalContext 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.NavController import com.texthip.thip.R +import com.texthip.thip.ui.common.header.AuthorHeader import com.texthip.thip.ui.common.modal.ToastWithDate import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar -import com.texthip.thip.ui.feed.component.MySubscriptionList -import com.texthip.thip.ui.feed.mock.MySubscriptionData +import com.texthip.thip.ui.feed.viewmodel.MyFollowingUiModel +import com.texthip.thip.ui.feed.viewmodel.MySubscriptionUiState +import com.texthip.thip.ui.feed.viewmodel.MySubscriptionViewModel import com.texthip.thip.ui.theme.ThipTheme -import com.texthip.thip.ui.theme.ThipTheme.colors -import com.texthip.thip.ui.theme.ThipTheme.typography import kotlinx.coroutines.delay +//TODO util 함수로 빼기 +fun hexToColor(hex: String): Color { + return try { + Color(android.graphics.Color.parseColor(hex)) + } catch (e: IllegalArgumentException) { + //잘못된 형식이면 기본 색 + Color.White + } +} @Composable fun MySubscriptionScreen( - navController: NavController? = null, - titleText: String = stringResource(R.string.my_thip_list) + navController: NavController, + viewModel: MySubscriptionViewModel = hiltViewModel() ) { - val initialmembers = listOf( - MySubscriptionData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "thipthip", - role = "공식 인플루언서", - roleColor = colors.NeonGreen, - subscriberCount = 50 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "thip01", - role = "작가", - roleColor = colors.NeonGreen, - subscriberCount = 100 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "thipthip", - role = "공식 인플루언서", - roleColor = colors.NeonGreen, - subscriberCount = 50 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "thip01", - role = "작가", - roleColor = colors.NeonGreen, - subscriberCount = 100 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "thipthip", - role = "공식 인플루언서", - roleColor = colors.NeonGreen, - subscriberCount = 50 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - MySubscriptionData( - profileImageUrl = null, - nickname = "thip01", - role = "작가", - roleColor = colors.NeonGreen, - subscriberCount = 100 - ), - ) + val uiState by viewModel.uiState.collectAsState() + val lazyListState = rememberLazyListState() val context = LocalContext.current - var members by remember { mutableStateOf(initialmembers) } - var toastMessage by rememberSaveable { mutableStateOf(null) } + val isScrolledToEnd by remember { + derivedStateOf { + val layoutInfo = lazyListState.layoutInfo + if (layoutInfo.totalItemsCount == 0) return@derivedStateOf false + val lastVisibleItemIndex = layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0 + lastVisibleItemIndex >= layoutInfo.totalItemsCount - 1 + } + } + + LaunchedEffect(isScrolledToEnd) { + if (isScrolledToEnd && !uiState.isLoading && !uiState.isLastPage) { + viewModel.fetchMyFollowings() + } + } - LaunchedEffect(toastMessage) { - if (toastMessage != null) { + MySubscriptionContent( + uiState = uiState, + lazyListState = lazyListState, + onNavigateBack = { navController.popBackStack() }, + onToggleFollow = { userId, nickname -> + val followedMessage = context.getString(R.string.toast_thip, nickname) + val unfollowedMessage = context.getString(R.string.toast_thip_cancel, nickname) + viewModel.toggleFollow(userId, followedMessage, unfollowedMessage) + }, + onHideToast = { viewModel.hideToast() } + ) +} +@Composable +fun MySubscriptionContent( + uiState: MySubscriptionUiState, + lazyListState: LazyListState, + onNavigateBack: () -> Unit, + onToggleFollow: (userId: Int, nickname: String) -> Unit, + onHideToast: () -> Unit +) { + LaunchedEffect(uiState.showToast) { + if (uiState.showToast) { delay(2000) - toastMessage = null + onHideToast() } } + Box(modifier = Modifier.fillMaxSize()) { - toastMessage?.let { message -> + if (uiState.showToast) { Box( modifier = Modifier .fillMaxWidth() .zIndex(1f) .align(Alignment.TopCenter) .padding(horizontal = 15.dp, vertical = 15.dp), - contentAlignment = Alignment.TopCenter ) { ToastWithDate( - message = message, + message = uiState.toastMessage, modifier = Modifier.fillMaxWidth() ) } } + Column( Modifier - .background(colors.Black) + .background(ThipTheme.colors.Black) .fillMaxSize() ) { DefaultTopAppBar( - onLeftClick = {}, - title = titleText + onLeftClick = onNavigateBack, + title = stringResource(R.string.my_thip_list) ) - Column( - modifier = Modifier - .fillMaxWidth() - - ) { + Column(modifier = Modifier.fillMaxWidth()) { Spacer(modifier = Modifier.height(40.dp)) Text( - text = stringResource(R.string.whole_num, members.size), - style = typography.menu_m500_s14_h24, - color = colors.Grey, + text = stringResource(R.string.whole_num, uiState.totalCount), + style = ThipTheme.typography.menu_m500_s14_h24, + color = ThipTheme.colors.Grey, modifier = Modifier .fillMaxWidth() .padding(start = 20.dp, bottom = 4.dp) ) HorizontalDivider( modifier = Modifier.padding(horizontal = 20.dp), - color = colors.DarkGrey02, + color = ThipTheme.colors.DarkGrey02, thickness = 1.dp ) + LazyColumn( - modifier = Modifier - .fillMaxSize() + state = lazyListState, + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(vertical = 20.dp) ) { - item { - MySubscriptionList( - members = members, - onUnsubscribe = { nickname -> - members = members.map { - if (it.nickname == nickname) it.copy(isSubscribed = !it.isSubscribed) - else it - } - toastMessage = - if (members.find { it.nickname == nickname }?.isSubscribed == true) { - context.getString(R.string.toast_thip, nickname) - } else { - context.getString(R.string.toast_thip_cancel, nickname) - } + itemsIndexed( + items = uiState.followings, + key = { _, user -> user.userId } + ) { index, user -> + Column(modifier = Modifier.padding(horizontal = 20.dp)) { + AuthorHeader( + profileImage = user.profileImageUrl, + nickname = user.nickname, + badgeText = user.aliasName, + badgeTextColor = hexToColor(user.aliasColor), + buttonText = stringResource(if (user.isFollowing) R.string.thip_cancel else R.string.thip), + buttonWidth = 64.dp, + profileImageSize = 36.dp, + onButtonClick = { onToggleFollow(user.userId, user.nickname) } + ) + + if (index < uiState.followings.lastIndex) { + Spacer(modifier = Modifier.height(16.dp)) + HorizontalDivider( + color = ThipTheme.colors.DarkGrey02, + thickness = 1.dp + ) + Spacer(modifier = Modifier.height(16.dp)) + } + } + } + + if (uiState.isLoading && !uiState.isLastPage) { + item { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.weight(1f)) + CircularProgressIndicator(modifier = Modifier.size(24.dp)) + Spacer(modifier = Modifier.weight(1f)) } - ) + } } } } } } } - @Preview @Composable private fun MySubscriptionListScreenPrev() { + val mockUsers = (1..10).map { + MyFollowingUiModel( + userId = it, + profileImageUrl = null, + nickname = "문학소년 $it", + aliasName = if (it % 3 == 0) "공식 인플루언서" else "글쓰는 탐험가", + aliasColor = if (it % 3 == 0) "#00C7B2" else "#FFD600", + isFollowing = true + ) + } + ThipTheme { - MySubscriptionScreen() + MySubscriptionContent( + uiState = MySubscriptionUiState( + isLoading = false, + followings = mockUsers, + totalCount = 25, + isLastPage = false, + showToast = false + ), + lazyListState = rememberLazyListState(), + onNavigateBack = {}, + onToggleFollow = { _, _ -> }, + onHideToast = {} + ) } } \ No newline at end of file From 38c034993503cd1d55b4b46bf7b7577257f4b871 Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 21:52:34 +0900 Subject: [PATCH 06/13] =?UTF-8?q?[feat]:=20=EC=84=9C=EB=B9=84=EC=8A=A4?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=9C=A0=EC=A0=80=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80=20(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/texthip/thip/data/di/ServiceModule.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt b/app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt index bf7eafad..eb8dd0fd 100644 --- a/app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt +++ b/app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt @@ -3,6 +3,7 @@ package com.texthip.thip.data.di import com.texthip.thip.data.service.BookService import com.texthip.thip.data.service.GroupService import com.texthip.thip.data.service.RoomsService +import com.texthip.thip.data.service.UserService import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -29,4 +30,10 @@ object ServiceModule { @Singleton fun providesRoomsService(retrofit: Retrofit): RoomsService = retrofit.create(RoomsService::class.java) + + @Provides + @Singleton + fun provideUserService(retrofit: Retrofit): UserService { + return retrofit.create(UserService::class.java) + } } \ No newline at end of file From 225ea7af3b6222c771ac223654bddd8743b4ca4d Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 21:54:18 +0900 Subject: [PATCH 07/13] =?UTF-8?q?[feat]:=20FeedScreen=EC=97=90=20=EB=82=B4?= =?UTF-8?q?=20=EB=9D=B1=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=EB=B0=94=20=EB=B7=B0?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=20=EC=9A=94=EC=B2=AD=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../texthip/thip/ui/feed/screen/FeedScreen.kt | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) 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 77070730..79822084 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 @@ -13,16 +13,19 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier 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.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.texthip.thip.R import com.texthip.thip.ui.common.buttons.FloatingButton @@ -33,12 +36,15 @@ import com.texthip.thip.ui.feed.component.FeedSubscribeBarlist import com.texthip.thip.ui.feed.component.MyFeedCard import com.texthip.thip.ui.feed.component.MySubscribeBarlist import com.texthip.thip.ui.feed.mock.MySubscriptionData +import com.texthip.thip.ui.feed.viewmodel.MySubscriptionViewModel import com.texthip.thip.ui.mypage.component.SavedFeedCard import com.texthip.thip.ui.mypage.mock.FeedItem +import com.texthip.thip.ui.navigator.routes.FeedRoutes import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography + @Composable fun FeedScreen( navController: NavController? = null, @@ -47,7 +53,8 @@ fun FeedScreen( feeds: List = emptyList(), totalFeedCount: Int = 0, selectedTabIndex: Int = 0, - followerProfileImageUrls: List = emptyList() + followerProfileImageUrls: List = emptyList(), + viewModel: MySubscriptionViewModel = hiltViewModel() ) { val selectedIndex = rememberSaveable { mutableIntStateOf(selectedTabIndex) } val feedStateList = remember { @@ -105,6 +112,7 @@ fun FeedScreen( roleColor = colors.SocialScience ) ) + val subscriptionUiState by viewModel.uiState.collectAsState() Box(modifier = Modifier.fillMaxSize()) { Column( modifier = Modifier.fillMaxSize() @@ -204,10 +212,21 @@ fun FeedScreen( //피드 item { Spacer(modifier = Modifier.height(20.dp)) + val subscriptionsForBar = subscriptionUiState.followings.map { user -> + MySubscriptionData( + profileImageUrl = user.profileImageUrl, + nickname = user.nickname, + role = user.aliasName, + roleColor = colors.White, + subscriberCount = 0, + isSubscribed = user.isFollowing + ) + } MySubscribeBarlist( modifier = Modifier.padding(horizontal = 20.dp), - subscriptions = mySubscriptions, + subscriptions = subscriptionsForBar, onClick = { + navController?.navigate(FeedRoutes.MySubscription) } ) } @@ -301,7 +320,7 @@ private fun FeedScreenWithoutDataPreview() { FeedScreen( nickname = "ThipUser01", userRole = "문학 칭호", - selectedTabIndex = 1, + selectedTabIndex = 0, feeds = mockFeeds, totalFeedCount = mockFeeds.size, followerProfileImageUrls = mockFollowerImages From 9c62a3de2a7997e83ef8a104fd8b336638d3255a Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 21:54:31 +0900 Subject: [PATCH 08/13] =?UTF-8?q?[feat]:=20Feed=20Route=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../texthip/thip/ui/navigator/navigations/FeedNavigation.kt | 5 +++++ .../java/com/texthip/thip/ui/navigator/routes/FeedRoutes.kt | 2 ++ 2 files changed, 7 insertions(+) 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 e7e3a8b9..ef3214c8 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 @@ -4,6 +4,8 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.composable import com.texthip.thip.ui.feed.screen.FeedScreen +import com.texthip.thip.ui.feed.screen.MySubscriptionScreen +import com.texthip.thip.ui.navigator.routes.FeedRoutes import com.texthip.thip.ui.navigator.routes.MainTabRoutes // Feed @@ -20,4 +22,7 @@ fun NavGraphBuilder.feedNavigation(navController: NavHostController) { followerProfileImageUrls = emptyList() ) } + composable { + MySubscriptionScreen(navController = navController) + } } \ No newline at end of file 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 6cc7bc71..4bb9935a 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 @@ -7,4 +7,6 @@ sealed class FeedRoutes : Routes() { // 향후 추가될 Feed 관련 화면들 // @Serializable data object SubscriptionList : FeedRoutes // @Serializable data object Detail : FeedRoutes + + @Serializable data object MySubscription : FeedRoutes() } \ No newline at end of file From 27be2a553451e00a8efb6117890c2c5c5073d298 Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 22:49:12 +0900 Subject: [PATCH 09/13] =?UTF-8?q?[refactor]:=20textAlign=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../texthip/thip/ui/feed/component/MySubscribelistBar.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 ca883a4e..eea3a257 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 @@ -24,6 +24,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -105,7 +106,8 @@ fun MySubscribeBarlist( overflow = TextOverflow.Ellipsis, style = typography.view_r400_s11_h20, color = colors.White, - modifier = Modifier.width(36.dp) + modifier = Modifier.width(36.dp), + textAlign = TextAlign.Center ) } Spacer(modifier = Modifier.width(12.dp)) @@ -160,7 +162,7 @@ private fun MySubscribeBarlistPrev() { val previewData = List(10) { MySubscriptionData( profileImageUrl = "https://example.com/profile$it.jpg", - nickname = "닉네임$it", + nickname = "닉네임임$it", role = "문학가", roleColor = colors.Red, subscriberCount = 100 + it From 97ce79e50228f5836e1cb84802746ff19bead8ce Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 22:59:03 +0900 Subject: [PATCH 10/13] =?UTF-8?q?[refactor]:=20hexTocolor=20=EC=9C=A0?= =?UTF-8?q?=ED=8B=B8=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/feed/screen/MySubscriptionListScreen.kt | 10 +--------- .../java/com/texthip/thip/utils/color/HexToColor.kt | 12 ++++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/texthip/thip/utils/color/HexToColor.kt diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt index 8ee16dc6..f809c038 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt @@ -42,17 +42,9 @@ import com.texthip.thip.ui.feed.viewmodel.MyFollowingUiModel import com.texthip.thip.ui.feed.viewmodel.MySubscriptionUiState import com.texthip.thip.ui.feed.viewmodel.MySubscriptionViewModel import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.utils.color.hexToColor import kotlinx.coroutines.delay -//TODO util 함수로 빼기 -fun hexToColor(hex: String): Color { - return try { - Color(android.graphics.Color.parseColor(hex)) - } catch (e: IllegalArgumentException) { - //잘못된 형식이면 기본 색 - Color.White - } -} @Composable fun MySubscriptionScreen( navController: NavController, diff --git a/app/src/main/java/com/texthip/thip/utils/color/HexToColor.kt b/app/src/main/java/com/texthip/thip/utils/color/HexToColor.kt new file mode 100644 index 00000000..381ef36f --- /dev/null +++ b/app/src/main/java/com/texthip/thip/utils/color/HexToColor.kt @@ -0,0 +1,12 @@ +package com.texthip.thip.utils.color + +import androidx.compose.ui.graphics.Color + +fun hexToColor(hex: String): Color { + return try { + Color(android.graphics.Color.parseColor(hex)) + } catch (e: IllegalArgumentException) { + //잘못된 형식이면 기본 색 + Color.White + } +} \ No newline at end of file From 9dd50b12443abcd19a7fa27a8e34b95f5f29d83b Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 23:31:04 +0900 Subject: [PATCH 11/13] =?UTF-8?q?[refactor]:=20=EB=B7=B0=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20uimodel=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F?= =?UTF-8?q?=20=EC=9D=91=EB=8B=B5=20dto=EB=A1=9C=20=EB=8C=80=EC=B2=B4(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/screen/MySubscriptionListScreen.kt | 17 ++++++----- .../feed/viewmodel/MySubscriptionViewModel.kt | 29 ++----------------- 2 files changed, 12 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt index f809c038..de69ada9 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -35,13 +34,15 @@ import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.texthip.thip.R +import com.texthip.thip.data.model.users.FollowingDto import com.texthip.thip.ui.common.header.AuthorHeader import com.texthip.thip.ui.common.modal.ToastWithDate import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar -import com.texthip.thip.ui.feed.viewmodel.MyFollowingUiModel import com.texthip.thip.ui.feed.viewmodel.MySubscriptionUiState import com.texthip.thip.ui.feed.viewmodel.MySubscriptionViewModel 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 import kotlinx.coroutines.delay @@ -114,7 +115,7 @@ fun MySubscriptionContent( Column( Modifier - .background(ThipTheme.colors.Black) + .background(colors.Black) .fillMaxSize() ) { DefaultTopAppBar( @@ -125,15 +126,15 @@ fun MySubscriptionContent( Spacer(modifier = Modifier.height(40.dp)) Text( text = stringResource(R.string.whole_num, uiState.totalCount), - style = ThipTheme.typography.menu_m500_s14_h24, - color = ThipTheme.colors.Grey, + style = typography.menu_m500_s14_h24, + color = colors.Grey, modifier = Modifier .fillMaxWidth() .padding(start = 20.dp, bottom = 4.dp) ) HorizontalDivider( modifier = Modifier.padding(horizontal = 20.dp), - color = ThipTheme.colors.DarkGrey02, + color = colors.DarkGrey02, thickness = 1.dp ) @@ -161,7 +162,7 @@ fun MySubscriptionContent( if (index < uiState.followings.lastIndex) { Spacer(modifier = Modifier.height(16.dp)) HorizontalDivider( - color = ThipTheme.colors.DarkGrey02, + color = colors.DarkGrey02, thickness = 1.dp ) Spacer(modifier = Modifier.height(16.dp)) @@ -192,7 +193,7 @@ fun MySubscriptionContent( @Composable private fun MySubscriptionListScreenPrev() { val mockUsers = (1..10).map { - MyFollowingUiModel( + FollowingDto( userId = it, profileImageUrl = null, nickname = "문학소년 $it", diff --git a/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt b/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt index 020d47d6..018dea75 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt @@ -2,6 +2,7 @@ package com.texthip.thip.ui.feed.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.texthip.thip.data.model.users.FollowingDto import com.texthip.thip.data.repository.UserRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -12,7 +13,7 @@ import javax.inject.Inject data class MySubscriptionUiState( val isLoading: Boolean = false, - val followings: List = emptyList(), + val followings: List = emptyList(), val totalCount: Int = 0, val isLastPage: Boolean = false, val errorMessage: String? = null, @@ -20,15 +21,6 @@ data class MySubscriptionUiState( val toastMessage: String = "" ) -data class MyFollowingUiModel( - val userId: Int, - val profileImageUrl: String?, - val nickname: String, - val aliasName: String, - val aliasColor: String, - var isFollowing: Boolean -) - @HiltViewModel class MySubscriptionViewModel @Inject constructor( private val userRepository: UserRepository @@ -40,11 +32,9 @@ class MySubscriptionViewModel @Inject constructor( private var nextCursor: String? = null init { - //ViewModel 생성될 때 첫 페이지 데이터를 로드 fetchMyFollowings(isInitial = true) } - fun fetchMyFollowings(isInitial: Boolean = false) { if (_uiState.value.isLoading || (!isInitial && _uiState.value.isLastPage)) { return @@ -57,18 +47,8 @@ class MySubscriptionViewModel @Inject constructor( val result = userRepository.getMyFollowings(cursor = cursorToFetch) result.onSuccess { data -> - //data가 null이 아닐 경우에만 상태 업데이트 data?.let { - val newFollowings = it.followings.map { dto -> - MyFollowingUiModel( - userId = dto.userId, - profileImageUrl = dto.profileImageUrl, - nickname = dto.nickname, - aliasName = dto.aliasName, - aliasColor = dto.aliasColor, - isFollowing = dto.isFollowing - ) - } + val newFollowings = it.followings nextCursor = it.nextCursor _uiState.update { currentState -> @@ -80,11 +60,9 @@ class MySubscriptionViewModel @Inject constructor( ) } } ?: _uiState.update { - // 데이터가 null인 경우 (성공했지만 내용이 없는 케이스) it.copy(isLoading = false, errorMessage = "응답 데이터가 비어있습니다.") } }.onFailure { exception -> - // 실패 시 예외 처리 _uiState.update { it.copy(isLoading = false, errorMessage = exception.message) } @@ -94,7 +72,6 @@ class MySubscriptionViewModel @Inject constructor( fun toggleFollow(userId: Int, followedMessage: String, unfollowedMessage: String) { - // TODO: 실제 팔로우/언팔로우 API를 호출 로직 var toastMsg = "" _uiState.update { currentState -> val updatedList = currentState.followings.map { user -> From 1816db92cc4e0e7585fc20fe82a07d7d6033a54d Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Wed, 13 Aug 2025 23:59:36 +0900 Subject: [PATCH 12/13] =?UTF-8?q?[refactor]:=20followingDto=20->=20Followi?= =?UTF-8?q?ngList=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/texthip/thip/data/model/users/MyFollowingsResponse.kt | 4 ++-- .../texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt | 4 ++-- .../texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/data/model/users/MyFollowingsResponse.kt b/app/src/main/java/com/texthip/thip/data/model/users/MyFollowingsResponse.kt index d439f7e6..91807af3 100644 --- a/app/src/main/java/com/texthip/thip/data/model/users/MyFollowingsResponse.kt +++ b/app/src/main/java/com/texthip/thip/data/model/users/MyFollowingsResponse.kt @@ -5,14 +5,14 @@ import kotlinx.serialization.Serializable @Serializable data class MyFollowingsResponse( - @SerializedName("followings") val followings: List, + @SerializedName("followings") val followings: List, @SerializedName("totalFollowingCount") val totalFollowingCount: Int, @SerializedName("nextCursor") val nextCursor: String?, @SerializedName("isLast") val isLast: Boolean ) @Serializable -data class FollowingDto( +data class FollowingList( @SerializedName("userId") val userId: Int, @SerializedName("nickname") val nickname: String, @SerializedName("profileImageUrl") val profileImageUrl: String?, diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt index de69ada9..e3404c90 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt @@ -34,7 +34,7 @@ import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.texthip.thip.R -import com.texthip.thip.data.model.users.FollowingDto +import com.texthip.thip.data.model.users.FollowingList import com.texthip.thip.ui.common.header.AuthorHeader import com.texthip.thip.ui.common.modal.ToastWithDate import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar @@ -193,7 +193,7 @@ fun MySubscriptionContent( @Composable private fun MySubscriptionListScreenPrev() { val mockUsers = (1..10).map { - FollowingDto( + FollowingList( userId = it, profileImageUrl = null, nickname = "문학소년 $it", diff --git a/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt b/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt index 018dea75..7f4f03c2 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/viewmodel/MySubscriptionViewModel.kt @@ -2,7 +2,7 @@ package com.texthip.thip.ui.feed.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.texthip.thip.data.model.users.FollowingDto +import com.texthip.thip.data.model.users.FollowingList import com.texthip.thip.data.repository.UserRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -13,7 +13,7 @@ import javax.inject.Inject data class MySubscriptionUiState( val isLoading: Boolean = false, - val followings: List = emptyList(), + val followings: List = emptyList(), val totalCount: Int = 0, val isLastPage: Boolean = false, val errorMessage: String? = null, From e931517732502cd9ab0e66187357e6df2b5dfd98 Mon Sep 17 00:00:00 2001 From: JJUYAAA Date: Thu, 14 Aug 2025 00:21:31 +0900 Subject: [PATCH 13/13] =?UTF-8?q?[refactor]:=20=EB=84=A4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt | 5 ++--- .../ui/navigator/extensions/FeedNavigationExtensions.kt | 6 ++++++ .../texthip/thip/ui/navigator/navigations/FeedNavigation.kt | 6 +++++- 3 files changed, 13 insertions(+), 4 deletions(-) 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 79822084..45220924 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 @@ -48,6 +48,7 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun FeedScreen( navController: NavController? = null, + onNavigateToMySubscription: () -> Unit = {}, nickname: String = "", userRole: String = "", feeds: List = emptyList(), @@ -225,9 +226,7 @@ fun FeedScreen( MySubscribeBarlist( modifier = Modifier.padding(horizontal = 20.dp), subscriptions = subscriptionsForBar, - onClick = { - navController?.navigate(FeedRoutes.MySubscription) - } + onClick = onNavigateToMySubscription ) } itemsIndexed(feedStateList, key = { _, item -> item.id }) { index, feed -> diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/extensions/FeedNavigationExtensions.kt b/app/src/main/java/com/texthip/thip/ui/navigator/extensions/FeedNavigationExtensions.kt index ebc035cc..ef71bb4e 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/extensions/FeedNavigationExtensions.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/extensions/FeedNavigationExtensions.kt @@ -1,9 +1,15 @@ package com.texthip.thip.ui.navigator.extensions import androidx.navigation.NavHostController +import com.texthip.thip.ui.navigator.routes.FeedRoutes import com.texthip.thip.ui.navigator.routes.MainTabRoutes // Feed 확장 함수 fun NavHostController.navigateToFeed() { navigate(MainTabRoutes.Feed) } + +// 내 띱 목록으로 +fun NavHostController.navigateToMySubscription() { + navigate(FeedRoutes.MySubscription) +} \ 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 ef3214c8..740a9711 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 @@ -5,6 +5,7 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.composable import com.texthip.thip.ui.feed.screen.FeedScreen import com.texthip.thip.ui.feed.screen.MySubscriptionScreen +import com.texthip.thip.ui.navigator.extensions.navigateToMySubscription import com.texthip.thip.ui.navigator.routes.FeedRoutes import com.texthip.thip.ui.navigator.routes.MainTabRoutes @@ -19,7 +20,10 @@ fun NavGraphBuilder.feedNavigation(navController: NavHostController) { feeds = emptyList(), totalFeedCount = 0, selectedTabIndex = 0, - followerProfileImageUrls = emptyList() + followerProfileImageUrls = emptyList(), + onNavigateToMySubscription = { + navController.navigateToMySubscription() + } ) } composable {