Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ fun FeedScreen(
lastVisibleIndex >= totalItems - 3
}
}

LaunchedEffect(Unit) {
navController.currentBackStackEntry?.savedStateHandle?.let { handle ->
handle.getLiveData<Long>("deleted_feed_id").observeForever { deletedId ->
Expand All @@ -144,11 +145,24 @@ fun FeedScreen(
if (feedUiState.allFeeds.isEmpty() && feedUiState.myFeeds.isEmpty()) {
feedViewModel.refreshData()
}

val hasUpdatedFeedData =
navController.currentBackStackEntry?.savedStateHandle?.get<Long>("updated_feed_id") != null
val fromProfile =
navController.currentBackStackEntry?.savedStateHandle?.get<Boolean>("from_profile") ?: false

if (!hasUpdatedFeedData) {
if (!hasUpdatedFeedData && !fromProfile) {
// 일반적인 경우: 전체 새로고침 + 스크롤 상단 이동
feedViewModel.refreshData()
allFeedListState.scrollToItem(0)
} else {
// 댓글 화면 또는 프로필에서 돌아온 경우: recentWriters만 업데이트
feedViewModel.fetchRecentWriters()
}

// 프로필 플래그 제거
if (fromProfile) {
navController.currentBackStackEntry?.savedStateHandle?.remove<Boolean>("from_profile")
}
Comment on lines 149 to 166

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

최초 진입 시 refreshData가 이중 호출됩니다 (중복 네트워크 요청 가능)

같은 LaunchedEffect(Unit) 블록 내에서:

  • (라인 144-148) 빈 목록이면 refreshData()
  • 이어서 (라인 154-158) updated_feed_id 없음 && from_profile 아님 → 다시 refreshData()

초기 진입 케이스에서 두 조건이 동시에 참이므로 두 번 호출됩니다. 한 번만 호출되도록 정리하세요.

간단히 첫 번째 블록을 제거하는 diff:

-    LaunchedEffect(Unit) {
-        // 최초 진입시에만 데이터 로딩
-        if (feedUiState.allFeeds.isEmpty() && feedUiState.myFeeds.isEmpty()) {
-            feedViewModel.refreshData()
-        }
-
+    LaunchedEffect(Unit) {
         val hasUpdatedFeedData =
             navController.currentBackStackEntry?.savedStateHandle?.get<Long>("updated_feed_id") != null
         val fromProfile =
             navController.currentBackStackEntry?.savedStateHandle?.get<Boolean>("from_profile") ?: false

         if (!hasUpdatedFeedData && !fromProfile) {
             // 일반적인 경우: 전체 새로고침 + 스크롤 상단 이동
             feedViewModel.refreshData()
             allFeedListState.scrollToItem(0)
         } else {
             // 댓글 화면 또는 프로필에서 돌아온 경우: recentWriters만 업데이트
-            feedViewModel.fetchRecentWriters()
+            // suspend로 전환된 API를 호출한다고 가정
+            feedViewModel.fetchRecentWriters()
         }
 
         // 프로필 플래그 제거
         if (fromProfile) {
             navController.currentBackStackEntry?.savedStateHandle?.remove<Boolean>("from_profile")
         }
     }

위 변경은 291라인에서 제안한 suspend 전환과 함께 적용 시 가장 자연스럽습니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
val hasUpdatedFeedData =
navController.currentBackStackEntry?.savedStateHandle?.get<Long>("updated_feed_id") != null
val fromProfile =
navController.currentBackStackEntry?.savedStateHandle?.get<Boolean>("from_profile") ?: false
if (!hasUpdatedFeedData) {
if (!hasUpdatedFeedData && !fromProfile) {
// 일반적인 경우: 전체 새로고침 + 스크롤 상단 이동
feedViewModel.refreshData()
allFeedListState.scrollToItem(0)
} else {
// 댓글 화면 또는 프로필에서 돌아온 경우: recentWriters만 업데이트
feedViewModel.fetchRecentWriters()
}
// 프로필 플래그 제거
if (fromProfile) {
navController.currentBackStackEntry?.savedStateHandle?.remove<Boolean>("from_profile")
}
LaunchedEffect(Unit) {
val hasUpdatedFeedData =
navController.currentBackStackEntry?.savedStateHandle?.get<Long>("updated_feed_id") != null
val fromProfile =
navController.currentBackStackEntry?.savedStateHandle?.get<Boolean>("from_profile") ?: false
if (!hasUpdatedFeedData && !fromProfile) {
// 일반적인 경우: 전체 새로고침 + 스크롤 상단 이동
feedViewModel.refreshData()
allFeedListState.scrollToItem(0)
} else {
// 댓글 화면 또는 프로필에서 돌아온 경우: recentWriters만 업데이트
// suspend로 전환된 API를 호출한다고 가정
feedViewModel.fetchRecentWriters()
}
// 프로필 플래그 제거
if (fromProfile) {
navController.currentBackStackEntry?.savedStateHandle?.remove<Boolean>("from_profile")
}
}

}

Expand Down Expand Up @@ -457,6 +471,8 @@ fun FeedScreen(
onNavigateToBookDetail(allFeed.isbn)
},
onProfileClick = {
// 프로필에서 돌아올 때를 위한 플래그 설정
navController.currentBackStackEntry?.savedStateHandle?.set("from_profile", true)
onNavigateToUserProfile(allFeed.creatorId)
}
)
Expand Down Expand Up @@ -530,4 +546,4 @@ private fun FeedScreenWithoutDataPreview() {
navController = rememberNavController()
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class FeedViewModel @Inject constructor(
fun pullToRefresh() {
viewModelScope.launch {
updateState { it.copy(isPullToRefreshing = true) }

fetchRecentWriters()
when (_uiState.value.selectedTabIndex) {
0 -> refreshAllFeeds()
1 -> refreshMyFeeds()
Expand Down Expand Up @@ -288,7 +288,7 @@ class FeedViewModel @Inject constructor(
}
}

private fun fetchRecentWriters() {
fun fetchRecentWriters() {
viewModelScope.launch {
updateState { it.copy(isLoading = true) }
userRepository.getMyFollowingsRecentFeeds()
Expand Down Expand Up @@ -332,10 +332,10 @@ class FeedViewModel @Inject constructor(
viewModelScope.launch {
val currentAllFeeds = _uiState.value.allFeeds
val currentMyFeeds = _uiState.value.myFeeds

val allFeedToUpdate = currentAllFeeds.find { it.feedId.toLong() == feedId }
val myFeedToUpdate = currentMyFeeds.find { it.feedId.toLong() == feedId }

if (allFeedToUpdate == null && myFeedToUpdate == null) return@launch

//ui 먼저 변경 ( 낙관적 업데이트 )
Expand All @@ -349,7 +349,7 @@ class FeedViewModel @Inject constructor(
it
}
}

val newMyFeeds = currentMyFeeds.map {
if (it.feedId.toLong() == feedId) {
it.copy(
Expand All @@ -360,7 +360,7 @@ class FeedViewModel @Inject constructor(
it
}
}

_uiState.update { it.copy(allFeeds = newAllFeeds, myFeeds = newMyFeeds) }

//api 호출
Expand All @@ -369,15 +369,20 @@ class FeedViewModel @Inject constructor(
} else {
!myFeedToUpdate!!.isLiked
}

val currentLikeCount = allFeedToUpdate?.likeCount ?: myFeedToUpdate!!.likeCount
val currentIsSaved = allFeedToUpdate?.isSaved ?: myFeedToUpdate!!.isSaved

changeFeedLikeUseCase(
feedId, newLikeStatus, currentLikeCount, currentIsSaved
)
.onFailure {
_uiState.update { it.copy(allFeeds = currentAllFeeds, myFeeds = currentMyFeeds) }
_uiState.update {
it.copy(
allFeeds = currentAllFeeds,
myFeeds = currentMyFeeds
)
}
}
}
}
Expand All @@ -386,10 +391,10 @@ class FeedViewModel @Inject constructor(
viewModelScope.launch {
val currentAllFeeds = _uiState.value.allFeeds
val currentMyFeeds = _uiState.value.myFeeds

val allFeedToUpdate = currentAllFeeds.find { it.feedId.toLong() == feedId }
val myFeedToUpdate = currentMyFeeds.find { it.feedId.toLong() == feedId }

if (allFeedToUpdate == null && myFeedToUpdate == null) return@launch

// (낙관적 업데이트) UI 즉시 변경
Expand All @@ -400,15 +405,15 @@ class FeedViewModel @Inject constructor(
it
}
}

val newMyFeeds = currentMyFeeds.map {
if (it.feedId.toLong() == feedId) {
it.copy(isSaved = !it.isSaved)
} else {
it
}
}

updateState { it.copy(allFeeds = newAllFeeds, myFeeds = newMyFeeds) }

// API 호출
Expand All @@ -417,10 +422,10 @@ class FeedViewModel @Inject constructor(
} else {
!myFeedToUpdate!!.isSaved
}

val currentIsLiked = allFeedToUpdate?.isLiked ?: myFeedToUpdate!!.isLiked
val currentLikeCount = allFeedToUpdate?.likeCount ?: myFeedToUpdate!!.likeCount

changeFeedSaveUseCase(
feedId = feedId,
newSaveStatus = newSaveStatus,
Expand All @@ -445,7 +450,7 @@ class FeedViewModel @Inject constructor(
feed
}
}

val updatedMyFeeds = _uiState.value.myFeeds.map { feed ->
if (feed.feedId.toLong() == result.feedId) {
feed.copy(
Expand All @@ -458,7 +463,7 @@ class FeedViewModel @Inject constructor(
feed
}
}

_uiState.update { it.copy(allFeeds = updatedAllFeeds, myFeeds = updatedMyFeeds) }
}

Expand Down