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
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.flint.core.designsystem.component.image

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import com.flint.core.common.extension.noRippleClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
Expand Down Expand Up @@ -43,7 +43,7 @@ fun SelectedContentItem(
Modifier
.align(Alignment.TopEnd)
.size(48.dp)
.clickable { onRemoveClick() },
.noRippleClickable { onRemoveClick() },
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.flint.core.designsystem.component.listItem.SavedContentItem
import com.flint.core.designsystem.theme.FlintTheme
import com.flint.domain.model.content.BookmarkedContentListModel
import com.flint.domain.model.content.ContentModel
import com.flint.domain.type.OttType
import kotlinx.collections.immutable.ImmutableList

@Composable
Expand Down Expand Up @@ -96,7 +97,6 @@ fun SavedContentsSection(
SavedContentItem(
contentModel = item,
onItemClick = { contentId ->

onItemClick(contentId)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ import com.flint.domain.model.collection.CollectionDetailModelNew
import com.flint.domain.model.content.ContentModelNew
import com.flint.domain.type.UserRoleType
import com.flint.presentation.collectiondetail.component.CollectionCopyrightFooter
import com.flint.R
import com.flint.core.designsystem.component.modal.OneButtonModal
import com.flint.presentation.collectiondetail.component.CollectionDetailDeleteModal
import com.flint.presentation.collectiondetail.component.CollectionDetailDescription
import com.flint.presentation.collectiondetail.component.CollectionDetailThumbnail
Expand Down Expand Up @@ -74,6 +76,7 @@ fun CollectionDetailRoute(
var showContentSaveToast: Boolean by remember { mutableStateOf(false) }
var showContentCancelToast: Boolean by remember { mutableStateOf(false) }
var showDeleteModal: Boolean by remember { mutableStateOf(false) }
var showBookmarkRestrictionModal: Boolean by remember { mutableStateOf(false) }
var showEditSuccessToastState: Boolean by remember { mutableStateOf(showEditSuccessToast) }

when (val uiState = uiState) {
Expand Down Expand Up @@ -123,6 +126,17 @@ fun CollectionDetailRoute(
else -> {}
}

if (showBookmarkRestrictionModal) {
OneButtonModal(
title = "작품 저장을 취소할 수 없어요",
message = "취향 키워드 분석을 위해\n최소 5개의 작품을 저장해주세요",
buttonText = "확인",
onConfirm = { showBookmarkRestrictionModal = false },
onDismiss = { showBookmarkRestrictionModal = false },
icon = R.drawable.ic_gradient_bookmark,
)
}

if (showDeleteModal) {
CollectionDetailDeleteModal(
onConfirm = {
Expand Down Expand Up @@ -218,6 +232,10 @@ fun CollectionDetailRoute(
}
}

CollectionDetailSideEffect.ToggleContentBookmarkMinLimitExceeded -> {
showBookmarkRestrictionModal = true
}

CollectionDetailSideEffect.DeleteCollectionSuccess -> navigateUpWithDeleteSuccess()

CollectionDetailSideEffect.DeleteCollectionFailure -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.flint.data.local.PreferencesManager
import com.flint.domain.model.bookmark.CollectionBookmarkUsersModel
import com.flint.domain.model.collection.CollectionDetailModelNew
import com.flint.domain.model.content.ContentModelNew
import com.flint.domain.model.bookmark.BookmarkException
import com.flint.domain.repository.BookmarkRepository
import com.flint.domain.repository.CollectionRepository
import com.flint.presentation.collectiondetail.sideeffect.CollectionDetailSideEffect
Expand Down Expand Up @@ -107,14 +108,47 @@ class CollectionDetailViewModel @Inject constructor(

val newBookmarkState: Boolean = !targetContent.isBookmarked
val initialBookmarkCount: Int = targetContent.bookmarkCount
val adjustedBookmarkCount: Int =
if (newBookmarkState) initialBookmarkCount + 1
else (initialBookmarkCount - 1).coerceAtLeast(0)

// 북마크 취소
if (!newBookmarkState) {
contentBookmarkDebounceJobs[contentId]?.cancel()
contentBookmarkDebounceJobs.remove(contentId)
val initialState = initialContentBookmarkStates.remove(contentId)

if (initialState == false) {
updateContentBookmarkState(
contentId = contentId,
isBookmarked = false,
bookmarkCount = (initialBookmarkCount - 1).coerceAtLeast(0),
)
return
}

viewModelScope.launch {
bookmarkRepository.toggleContentBookmark(contentId)
.onSuccess { isBookmarked: Boolean ->
updateContentBookmarkState(
contentId = contentId,
isBookmarked = isBookmarked,
bookmarkCount = (initialBookmarkCount - 1).coerceAtLeast(0),
)
_sideEffect.emit(CollectionDetailSideEffect.ToggleContentBookmarkSuccess(isBookmarked))
}
.onFailure { throwable ->
if (throwable is BookmarkException.ContentMinLimitExceeded) {
_sideEffect.emit(CollectionDetailSideEffect.ToggleContentBookmarkMinLimitExceeded)
}
}
}
return
}

// 북마크 추가
val adjustedBookmarkCount: Int = initialBookmarkCount + 1
updateContentBookmarkState(
contentId = contentId,
isBookmarked = newBookmarkState,
bookmarkCount = adjustedBookmarkCount
bookmarkCount = adjustedBookmarkCount,
)

contentBookmarkDebounceJobs[contentId]?.cancel()
Expand All @@ -132,7 +166,7 @@ class CollectionDetailViewModel @Inject constructor(
.onSuccess { isBookmarked: Boolean ->
updateContentIsBookmarkedOnly(
contentId = contentId,
isBookmarked = isBookmarked
isBookmarked = isBookmarked,
)
_sideEffect.emit(
CollectionDetailSideEffect.ToggleContentBookmarkSuccess(isBookmarked)
Expand All @@ -143,14 +177,10 @@ class CollectionDetailViewModel @Inject constructor(
(_uiState.value as? UiState.Success)?.data?.collectionDetail?.contents
?.find { it.id == contentId } ?: return@onFailure

val rollbackCount: Int =
if (initialState) fallbackContent.bookmarkCount + 1
else (fallbackContent.bookmarkCount - 1).coerceAtLeast(0)

updateContentBookmarkState(
contentId = contentId,
isBookmarked = initialState,
bookmarkCount = rollbackCount
bookmarkCount = (fallbackContent.bookmarkCount - 1).coerceAtLeast(0),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ sealed interface CollectionDetailSideEffect {

class ToggleContentBookmarkSuccess(val isBookmarked: Boolean) : CollectionDetailSideEffect

object ToggleContentBookmarkMinLimitExceeded : CollectionDetailSideEffect

object DeleteCollectionSuccess : CollectionDetailSideEffect

object DeleteCollectionFailure : CollectionDetailSideEffect
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/java/com/flint/presentation/main/MainNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import com.flint.presentation.explore.navigation.exploreNavGraph
import com.flint.presentation.home.navigation.homeNavGraph
import com.flint.presentation.login.navigation.loginNavGraph
import com.flint.presentation.onboarding.navigation.onBoardingNavGraph
import com.flint.core.navigation.MainTabRoute
import com.flint.presentation.profile.navigation.KEY_PROFILE_UPDATED
import com.flint.presentation.profile.navigation.myProfileNavGraph
import com.flint.presentation.profile.navigation.profileNavGraph
import com.flint.presentation.savedcontent.navigation.savedContentListNavGraph
Expand Down Expand Up @@ -144,6 +146,15 @@ fun MainNavHost(

editProfileNavGraph(
navigateUp = navigator::navigateUp,
onProfileSaved = {
try {
navigator.navController
.getBackStackEntry(MainTabRoute.Profile)
.savedStateHandle[KEY_PROFILE_UPDATED] = true
} catch (_: IllegalArgumentException) {
// MainTabRoute.Profile이 백스택에 없는 경우 무시
}
},
)

withdrawNavGraph(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,24 @@ fun OnboardingContentScreen(
// 타이틀 영역 - 스크롤됨
item(span = { GridItemSpan(3) }) {
Column {
var useMultiLine by remember(nickname) { mutableStateOf(false) }
Text(
text = "${nickname}님이 좋아하는 작품\n7개를 골라주세요",
text = if (useMultiLine) {
"${nickname}님이\n좋아하는 작품\n7개를 골라주세요"
} else {
"${nickname}님이 좋아하는 작품\n7개를 골라주세요"
},
color = FlintTheme.colors.white,
style = FlintTheme.typography.display2M28,
onTextLayout = { result ->
// 2줄 포맷인데 실제 렌더링이 3줄 이상이면 자연 줄바꿈 발생한 것
if (!useMultiLine && result.lineCount > 2) {
useMultiLine = true
}
},
)

Spacer(modifier = Modifier.height(8.dp))
Spacer(modifier = Modifier.height(24.dp))
}
}

Expand Down Expand Up @@ -193,6 +204,8 @@ fun OnboardingContentScreen(
}
}

Spacer(modifier = Modifier.height(8.dp))

FlintSearchTextField(
placeholder = "작품 이름",
value = contentUiState.searchKeyword,
Expand Down Expand Up @@ -277,7 +290,7 @@ fun OnboardingContentScreen(
contentAlignment = Alignment.Center,
) {
FlintSearchEmptyView(
title = "아직 준비 중인 작품이이요"
title = "아직 준비 중인 작품이에요"
)
}
}
Expand All @@ -296,7 +309,7 @@ fun OnboardingContentScreen(
contentAlignment = Alignment.Center,
) {
FlintSearchEmptyView(
title = "작품을 찾을 수 없어요"
title = "아직 준비 중인 작품이에요"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import com.flint.core.navigation.model.CollectionListRouteType
import com.flint.domain.model.collection.CollectionListModel
import com.flint.domain.model.content.BookmarkedContentListModel
import com.flint.domain.model.ott.OttListModel
import com.flint.domain.model.ott.OttModel
import com.flint.domain.model.user.KeywordListModel
import com.flint.domain.model.user.UserProfileResponseModel
import com.flint.presentation.MainActivity
Expand All @@ -66,6 +67,8 @@ fun ProfileRoute(
navigateToSavedContentList: (userId: String?) -> Unit,
navigateToCollectionDetail: (collectionId: String) -> Unit,
navigateToSetting: () -> Unit = {},
shouldRefreshProfile: Boolean = false,
onProfileRefreshed: () -> Unit = {},
viewModel: ProfileViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
Expand All @@ -76,6 +79,13 @@ fun ProfileRoute(
var ottListModel by remember { mutableStateOf(OttListModel()) }
val sheetState = rememberModalBottomSheetState()

LaunchedEffect(shouldRefreshProfile) {
if (shouldRefreshProfile) {
viewModel.reloadUserProfile()
onProfileRefreshed()
}
}

LaunchedEffect(Unit) {
viewModel.sideEffect.collect { sideEffect ->
when (sideEffect) {
Expand Down Expand Up @@ -104,7 +114,11 @@ fun ProfileRoute(
onCollectionItemClick = navigateToCollectionDetail,
onSettingsClick = navigateToSetting,
onContentItemClick = { contentId ->
viewModel.getOttListPerContent(contentId)
val ottList = (uiState.sectionData as? UiState.Success)
?.data?.savedContents?.contents
?.find { it.id == contentId }?.getOttSimpleList ?: emptyList()
ottListModel = OttListModel(otts = ottList.map { OttModel(name = it.name) })
if (ottListModel.otts.isNotEmpty()) showOttListBottomSheet = true
},
onContentMoreClick = { navigateToSavedContentList(uiState.userId) },
onCreatedCollectionMoreClick = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ class ProfileViewModel @Inject constructor(
}
}

// 프로필 헤더만 재조회 (섹션 데이터는 유지)
fun reloadUserProfile() {
viewModelScope.launch {
userRepository.getUserProfile(userId = userId)
.onSuccess { profile ->
_uiState.update { it.copy(profile = profile) }
}
.onFailure { Timber.e(it) }
}
}

fun recalculateKeywords() = viewModelScope.launch {
_uiState.update { it.copy(isRecalculating = true) }
userRepository.recalculateKeywords()
Expand Down
Loading
Loading