diff --git a/core/data-api/src/main/java/com/neki/android/core/dataapi/repository/PoseRepository.kt b/core/data-api/src/main/java/com/neki/android/core/dataapi/repository/PoseRepository.kt index 48077c393..ad9be206f 100644 --- a/core/data-api/src/main/java/com/neki/android/core/dataapi/repository/PoseRepository.kt +++ b/core/data-api/src/main/java/com/neki/android/core/dataapi/repository/PoseRepository.kt @@ -13,7 +13,7 @@ interface PoseRepository { sortOrder: SortOrder = SortOrder.DESC, ): Flow> - fun getScrappedPosesFlow( + fun getBookmarkedPosesFlow( sortOrder: SortOrder = SortOrder.DESC, ): Flow> @@ -30,5 +30,5 @@ interface PoseRepository { poseSize: Int, ): Result> - suspend fun updateScrap(poseId: Long, scrap: Boolean): Result + suspend fun updateBookmark(poseId: Long, bookmark: Boolean): Result } diff --git a/core/data/src/main/java/com/neki/android/core/data/paging/ScrapPosePagingSource.kt b/core/data/src/main/java/com/neki/android/core/data/paging/BookmarkPosePagingSource.kt similarity index 93% rename from core/data/src/main/java/com/neki/android/core/data/paging/ScrapPosePagingSource.kt rename to core/data/src/main/java/com/neki/android/core/data/paging/BookmarkPosePagingSource.kt index f9af57e7f..aa0bfcd0a 100644 --- a/core/data/src/main/java/com/neki/android/core/data/paging/ScrapPosePagingSource.kt +++ b/core/data/src/main/java/com/neki/android/core/data/paging/BookmarkPosePagingSource.kt @@ -6,7 +6,7 @@ import com.neki.android.core.data.remote.api.PoseService import com.neki.android.core.model.Pose import com.neki.android.core.model.SortOrder -class ScrapPosePagingSource( +class BookmarkPosePagingSource( private val poseService: PoseService, private val sortOrder: SortOrder, ) : PagingSource() { @@ -14,7 +14,7 @@ class ScrapPosePagingSource( override suspend fun load(params: LoadParams): LoadResult { return try { val page = params.key ?: 0 - val poses = poseService.getScrappedPoses( + val poses = poseService.getBookmarkedPoses( page = page, size = params.loadSize, sortOrder = sortOrder.name, diff --git a/core/data/src/main/java/com/neki/android/core/data/remote/api/PoseService.kt b/core/data/src/main/java/com/neki/android/core/data/remote/api/PoseService.kt index 98fe8f121..45f2d43b0 100644 --- a/core/data/src/main/java/com/neki/android/core/data/remote/api/PoseService.kt +++ b/core/data/src/main/java/com/neki/android/core/data/remote/api/PoseService.kt @@ -1,6 +1,6 @@ package com.neki.android.core.data.remote.api -import com.neki.android.core.data.remote.model.request.UpdateScrapRequest +import com.neki.android.core.data.remote.model.request.UpdateBookmarkRequest import com.neki.android.core.data.remote.model.response.BasicNullableResponse import com.neki.android.core.data.remote.model.response.BasicResponse import com.neki.android.core.data.remote.model.response.PoseDetailResponse @@ -44,8 +44,8 @@ class PoseService @Inject constructor( }.body() } - // 스크랩된 포즈 목록 조회 - suspend fun getScrappedPoses( + // 북마크된 포즈 목록 조회 + suspend fun getBookmarkedPoses( page: Int = 0, size: Int = 20, sortOrder: String = "DESC", @@ -57,10 +57,10 @@ class PoseService @Inject constructor( }.body() } - // 스크랩 업데이트 - suspend fun updateScrap(poseId: Long, scrap: Boolean): BasicNullableResponse { + // 북마크 업데이트 + suspend fun updateBookmark(poseId: Long, bookmark: Boolean): BasicNullableResponse { return client.patch("/api/poses/$poseId/scrap") { - setBody(UpdateScrapRequest(scrap)) + setBody(UpdateBookmarkRequest(bookmark)) }.body() } } diff --git a/core/data/src/main/java/com/neki/android/core/data/remote/model/request/UpdateScrapRequest.kt b/core/data/src/main/java/com/neki/android/core/data/remote/model/request/UpdateScrapRequest.kt index 6093883cf..f9e88a810 100644 --- a/core/data/src/main/java/com/neki/android/core/data/remote/model/request/UpdateScrapRequest.kt +++ b/core/data/src/main/java/com/neki/android/core/data/remote/model/request/UpdateScrapRequest.kt @@ -4,6 +4,6 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class UpdateScrapRequest( - @SerialName("scrap") val scrap: Boolean, +data class UpdateBookmarkRequest( + @SerialName("scrap") val bookmark: Boolean, ) diff --git a/core/data/src/main/java/com/neki/android/core/data/remote/model/response/PoseDetailResponse.kt b/core/data/src/main/java/com/neki/android/core/data/remote/model/response/PoseDetailResponse.kt index 2cde355d0..a9a2d8fe6 100644 --- a/core/data/src/main/java/com/neki/android/core/data/remote/model/response/PoseDetailResponse.kt +++ b/core/data/src/main/java/com/neki/android/core/data/remote/model/response/PoseDetailResponse.kt @@ -10,13 +10,13 @@ data class PoseDetailResponse( @SerialName("poseId") val poseId: Long, @SerialName("headCount") val headCount: String, @SerialName("imageUrl") val imageUrl: String, - @SerialName("scrap") val scrap: Boolean, + @SerialName("scrap") val bookmark: Boolean, @SerialName("contentType") val contentType: String, @SerialName("createdAt") val createdAt: String, ) { internal fun toModel() = Pose( id = poseId, - isScrapped = scrap, + isBookmarked = bookmark, poseImageUrl = imageUrl, peopleCount = PeopleCount.entries.find { it.name == headCount }?.value ?: 1, ) diff --git a/core/data/src/main/java/com/neki/android/core/data/remote/model/response/PoseResponse.kt b/core/data/src/main/java/com/neki/android/core/data/remote/model/response/PoseResponse.kt index 2ede9540b..80f1940bd 100644 --- a/core/data/src/main/java/com/neki/android/core/data/remote/model/response/PoseResponse.kt +++ b/core/data/src/main/java/com/neki/android/core/data/remote/model/response/PoseResponse.kt @@ -15,7 +15,7 @@ data class PoseResponse( @SerialName("poseId") val poseId: Long, @SerialName("headCount") val headCount: String, @SerialName("imageUrl") val imageUrl: String, - @SerialName("scrap") val scrap: Boolean, + @SerialName("scrap") val bookmark: Boolean, @SerialName("contentType") val contentType: String, @SerialName("createdAt") val createdAt: String, ) { @@ -23,7 +23,7 @@ data class PoseResponse( id = poseId, poseImageUrl = imageUrl, peopleCount = PeopleCount.entries.find { it.name == headCount }?.value ?: 1, - isScrapped = scrap, + isBookmarked = bookmark, ) } diff --git a/core/data/src/main/java/com/neki/android/core/data/repository/impl/PoseRepositoryImpl.kt b/core/data/src/main/java/com/neki/android/core/data/repository/impl/PoseRepositoryImpl.kt index 123ba3eeb..33647db61 100644 --- a/core/data/src/main/java/com/neki/android/core/data/repository/impl/PoseRepositoryImpl.kt +++ b/core/data/src/main/java/com/neki/android/core/data/repository/impl/PoseRepositoryImpl.kt @@ -6,7 +6,7 @@ import androidx.paging.PagingData import com.neki.android.core.common.exception.ApiErrorCode.NO_MORE_RANDOM_POSE import com.neki.android.core.common.exception.NoMorePoseException import com.neki.android.core.data.paging.PosePagingSource -import com.neki.android.core.data.paging.ScrapPosePagingSource +import com.neki.android.core.data.paging.BookmarkPosePagingSource import com.neki.android.core.data.remote.api.PoseService import com.neki.android.core.data.util.runSuspendCatching import com.neki.android.core.dataapi.repository.PoseRepository @@ -45,7 +45,7 @@ class PoseRepositoryImpl @Inject constructor( ).flow } - override fun getScrappedPosesFlow( + override fun getBookmarkedPosesFlow( sortOrder: SortOrder, ): Flow> { return Pager( @@ -56,7 +56,7 @@ class PoseRepositoryImpl @Inject constructor( enablePlaceholders = false, ), pagingSourceFactory = { - ScrapPosePagingSource( + BookmarkPosePagingSource( poseService = poseService, sortOrder = sortOrder, ) @@ -115,7 +115,7 @@ class PoseRepositoryImpl @Inject constructor( return@runSuspendCatching result } - override suspend fun updateScrap(poseId: Long, scrap: Boolean): Result = runSuspendCatching { - poseService.updateScrap(poseId, scrap) + override suspend fun updateBookmark(poseId: Long, bookmark: Boolean): Result = runSuspendCatching { + poseService.updateBookmark(poseId, bookmark) } } diff --git a/core/designsystem/src/main/java/com/neki/android/core/designsystem/actionbar/NekiActionBar.kt b/core/designsystem/src/main/java/com/neki/android/core/designsystem/actionbar/NekiActionBar.kt index 1960f1a62..2567e5e17 100644 --- a/core/designsystem/src/main/java/com/neki/android/core/designsystem/actionbar/NekiActionBar.kt +++ b/core/designsystem/src/main/java/com/neki/android/core/designsystem/actionbar/NekiActionBar.kt @@ -123,7 +123,7 @@ private fun NekiEndActionBarPreview() { onClick = {}, ) { Icon( - imageVector = ImageVector.vectorResource(R.drawable.icon_scrap_stroked), + imageVector = ImageVector.vectorResource(R.drawable.icon_bookmark_stroked), contentDescription = null, tint = NekiTheme.colorScheme.gray500, ) @@ -156,7 +156,7 @@ private fun NekiBothSidesActionBarPreview() { onClick = {}, ) { Icon( - imageVector = ImageVector.vectorResource(R.drawable.icon_scrap_stroked), + imageVector = ImageVector.vectorResource(R.drawable.icon_bookmark_stroked), contentDescription = null, tint = NekiTheme.colorScheme.gray500, ) diff --git a/core/designsystem/src/main/res/drawable/icon_scrap_filled.xml b/core/designsystem/src/main/res/drawable/icon_bookmark_filled.xml similarity index 100% rename from core/designsystem/src/main/res/drawable/icon_scrap_filled.xml rename to core/designsystem/src/main/res/drawable/icon_bookmark_filled.xml diff --git a/core/designsystem/src/main/res/drawable/icon_scrap_stroked.xml b/core/designsystem/src/main/res/drawable/icon_bookmark_stroked.xml similarity index 100% rename from core/designsystem/src/main/res/drawable/icon_scrap_stroked.xml rename to core/designsystem/src/main/res/drawable/icon_bookmark_stroked.xml diff --git a/core/model/src/main/java/com/neki/android/core/model/Pose.kt b/core/model/src/main/java/com/neki/android/core/model/Pose.kt index db0c1f3d4..4664e58a9 100644 --- a/core/model/src/main/java/com/neki/android/core/model/Pose.kt +++ b/core/model/src/main/java/com/neki/android/core/model/Pose.kt @@ -8,6 +8,6 @@ import kotlinx.serialization.Serializable data class Pose( val id: Long = 0L, val poseImageUrl: String = "", - val isScrapped: Boolean = false, + val isBookmarked: Boolean = false, val peopleCount: Int = 0, ) diff --git a/core/ui/src/main/java/com/neki/android/core/ui/component/FilterBar.kt b/core/ui/src/main/java/com/neki/android/core/ui/component/FilterBar.kt index 686333958..46f03804a 100644 --- a/core/ui/src/main/java/com/neki/android/core/ui/component/FilterBar.kt +++ b/core/ui/src/main/java/com/neki/android/core/ui/component/FilterBar.kt @@ -132,7 +132,7 @@ private fun FilterBarDefaultPreview() { isDownIconChipSelected = false, isDefaultChipSelected = false, downIconChipDisplayText = "인원수", - defaultChipDisplayText = "스크랩", + defaultChipDisplayText = "북마크", ) } } @@ -145,7 +145,7 @@ private fun FilterBarSelectedPreview() { isDownIconChipSelected = true, isDefaultChipSelected = true, downIconChipDisplayText = "2인", - defaultChipDisplayText = "스크랩", + defaultChipDisplayText = "북마크", ) } } diff --git a/feature/pose/api/src/main/java/com/neki/android/feature/pose/api/PoseResult.kt b/feature/pose/api/src/main/java/com/neki/android/feature/pose/api/PoseResult.kt index a2e93fea8..ac08cbf5f 100644 --- a/feature/pose/api/src/main/java/com/neki/android/feature/pose/api/PoseResult.kt +++ b/feature/pose/api/src/main/java/com/neki/android/feature/pose/api/PoseResult.kt @@ -1,5 +1,5 @@ package com.neki.android.feature.pose.api sealed interface PoseResult { - data class ScrapChanged(val poseId: Long, val isScrapped: Boolean) : PoseResult + data class BookmarkChanged(val poseId: Long, val isBookmarked: Boolean) : PoseResult } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailContract.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailContract.kt index 65444039e..23932a81c 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailContract.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailContract.kt @@ -5,19 +5,19 @@ import com.neki.android.core.model.Pose data class PoseDetailState( val isLoading: Boolean = false, val pose: Pose = Pose(), - val committedScrap: Boolean = false, + val committedBookmark: Boolean = false, ) sealed interface PoseDetailIntent { data object EnterPoseDetailScreen : PoseDetailIntent data object ClickBackIcon : PoseDetailIntent - data object ClickScrapIcon : PoseDetailIntent - data class ScrapCommitted(val newScrap: Boolean) : PoseDetailIntent - data class RevertScrap(val originalScrap: Boolean) : PoseDetailIntent + data object ClickBookmarkIcon : PoseDetailIntent + data class BookmarkCommitted(val newBookmark: Boolean) : PoseDetailIntent + data class RevertBookmark(val originalBookmark: Boolean) : PoseDetailIntent } sealed interface PoseDetailSideEffect { data object NavigateBack : PoseDetailSideEffect data class ShowToast(val message: String) : PoseDetailSideEffect - data class NotifyScrapChanged(val poseId: Long, val isScrapped: Boolean) : PoseDetailSideEffect + data class NotifyBookmarkChanged(val poseId: Long, val isBookmarked: Boolean) : PoseDetailSideEffect } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailScreen.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailScreen.kt index f7a6f8d84..5032d1d81 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailScreen.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailScreen.kt @@ -41,9 +41,9 @@ internal fun PoseDetailRoute( nekiToast.showToast(sideEffect.message) } - is PoseDetailSideEffect.NotifyScrapChanged -> { + is PoseDetailSideEffect.NotifyBookmarkChanged -> { resultEventBus.sendResult( - result = PoseResult.ScrapChanged(sideEffect.poseId, sideEffect.isScrapped), + result = PoseResult.BookmarkChanged(sideEffect.poseId, sideEffect.isBookmarked), allowDuplicate = false, ) } @@ -83,8 +83,8 @@ internal fun PoseDetailScreen( color = NekiTheme.colorScheme.gray75, ) PoseActionBar( - isScrapped = uiState.pose.isScrapped, - onClickScrap = { onIntent(PoseDetailIntent.ClickScrapIcon) }, + isBookmarked = uiState.pose.isBookmarked, + onClickBookmark = { onIntent(PoseDetailIntent.ClickBookmarkIcon) }, ) } } @@ -98,7 +98,7 @@ private fun PoseDetailScreenPreview() { pose = Pose( id = 1, poseImageUrl = "https://picsum.photos/400/600", - isScrapped = false, + isBookmarked = false, ), ), ) @@ -107,14 +107,14 @@ private fun PoseDetailScreenPreview() { @DevicePreview @Composable -private fun PoseDetailScreenScrappedPreview() { +private fun PoseDetailScreenBookmarkedPreview() { NekiTheme { PoseDetailScreen( uiState = PoseDetailState( pose = Pose( id = 1, poseImageUrl = "https://picsum.photos/400/600", - isScrapped = true, + isBookmarked = true, ), ), ) diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailViewModel.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailViewModel.kt index b7572b0a4..325d372f8 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailViewModel.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/PoseDetailViewModel.kt @@ -25,7 +25,7 @@ class PoseDetailViewModel @AssistedInject constructor( @ApplicationScope private val applicationScope: CoroutineScope, ) : ViewModel() { - private val scrapRequests = MutableSharedFlow(extraBufferCapacity = 64) + private val bookmarkRequests = MutableSharedFlow(extraBufferCapacity = 64) @AssistedFactory interface Factory { @@ -41,19 +41,19 @@ class PoseDetailViewModel @AssistedInject constructor( init { viewModelScope.launch { - scrapRequests + bookmarkRequests .debounce(500) - .collect { newScrap -> - val committedScrap = store.uiState.value.committedScrap - if (committedScrap != newScrap) { - poseRepository.updateScrap(id, newScrap) + .collect { newBookmark -> + val committedBookmark = store.uiState.value.committedBookmark + if (committedBookmark != newBookmark) { + poseRepository.updateBookmark(id, newBookmark) .onSuccess { - Timber.d("updateScrap success") - store.onIntent(PoseDetailIntent.ScrapCommitted(newScrap)) + Timber.d("updateBookmark success") + store.onIntent(PoseDetailIntent.BookmarkCommitted(newBookmark)) } .onFailure { error -> - Timber.e(error, "updateScrap failed") - store.onIntent(PoseDetailIntent.RevertScrap(committedScrap)) + Timber.e(error, "updateBookmark failed") + store.onIntent(PoseDetailIntent.RevertBookmark(committedBookmark)) } } } @@ -69,29 +69,29 @@ class PoseDetailViewModel @AssistedInject constructor( when (intent) { PoseDetailIntent.EnterPoseDetailScreen -> fetchPoseData(reduce) PoseDetailIntent.ClickBackIcon -> postSideEffect(PoseDetailSideEffect.NavigateBack) - PoseDetailIntent.ClickScrapIcon -> handleScrapToggle(state, reduce) - is PoseDetailIntent.ScrapCommitted -> { - reduce { copy(committedScrap = intent.newScrap) } - postSideEffect(PoseDetailSideEffect.NotifyScrapChanged(id, intent.newScrap)) + PoseDetailIntent.ClickBookmarkIcon -> handleBookmarkToggle(state, reduce) + is PoseDetailIntent.BookmarkCommitted -> { + reduce { copy(committedBookmark = intent.newBookmark) } + postSideEffect(PoseDetailSideEffect.NotifyBookmarkChanged(id, intent.newBookmark)) } - is PoseDetailIntent.RevertScrap -> reduce { copy(pose = pose.copy(isScrapped = intent.originalScrap)) } + is PoseDetailIntent.RevertBookmark -> reduce { copy(pose = pose.copy(isBookmarked = intent.originalBookmark)) } } } - private fun handleScrapToggle( + private fun handleBookmarkToggle( state: PoseDetailState, reduce: (PoseDetailState.() -> PoseDetailState) -> Unit, ) { - val newScrapStatus = !state.pose.isScrapped - viewModelScope.launch { scrapRequests.emit(newScrapStatus) } - reduce { copy(pose = pose.copy(isScrapped = newScrapStatus)) } + val newBookmarkStatus = !state.pose.isBookmarked + viewModelScope.launch { bookmarkRequests.emit(newBookmarkStatus) } + reduce { copy(pose = pose.copy(isBookmarked = newBookmarkStatus)) } } private fun fetchPoseData(reduce: (PoseDetailState.() -> PoseDetailState) -> Unit) { viewModelScope.launch { poseRepository.getPose(poseId = id) .onSuccess { data -> - reduce { copy(pose = data, committedScrap = data.isScrapped) } + reduce { copy(pose = data, committedBookmark = data.isBookmarked) } } .onFailure { error -> Timber.e(error) @@ -102,12 +102,12 @@ class PoseDetailViewModel @AssistedInject constructor( override fun onCleared() { super.onCleared() - val currentScrap = store.uiState.value.pose.isScrapped - val committedScrap = store.uiState.value.committedScrap + val currentBookmark = store.uiState.value.pose.isBookmarked + val committedBookmark = store.uiState.value.committedBookmark - if (currentScrap != committedScrap) { + if (currentBookmark != committedBookmark) { applicationScope.launch { - poseRepository.updateScrap(id, currentScrap) + poseRepository.updateBookmark(id, currentBookmark) } } } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/component/PoseActionBar.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/component/PoseActionBar.kt index 9c0b73011..6e0825077 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/component/PoseActionBar.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/detail/component/PoseActionBar.kt @@ -17,25 +17,25 @@ import com.neki.android.core.designsystem.ui.theme.NekiTheme @Composable internal fun PoseActionBar( - isScrapped: Boolean, + isBookmarked: Boolean, modifier: Modifier = Modifier, - onClickScrap: () -> Unit = {}, + onClickBookmark: () -> Unit = {}, ) { NekiEndActionBar( modifier = modifier.fillMaxWidth(), ) { NekiIconButton( modifier = Modifier.padding(8.dp), - onClick = onClickScrap, + onClick = onClickBookmark, ) { Icon( modifier = Modifier.size(28.dp), imageVector = ImageVector.vectorResource( - if (isScrapped) R.drawable.icon_scrap_filled - else R.drawable.icon_scrap_stroked, + if (isBookmarked) R.drawable.icon_bookmark_filled + else R.drawable.icon_bookmark_stroked, ), contentDescription = null, - tint = if (isScrapped) NekiTheme.colorScheme.gray900 + tint = if (isBookmarked) NekiTheme.colorScheme.gray900 else NekiTheme.colorScheme.gray500, ) } @@ -44,16 +44,16 @@ internal fun PoseActionBar( @ComponentPreview @Composable -private fun ScrappedPoseActionBarPreview() { +private fun BookmarkedPoseActionBarPreview() { NekiTheme { - PoseActionBar(isScrapped = true) + PoseActionBar(isBookmarked = true) } } @ComponentPreview @Composable -private fun UnScrappedPoseActionBarPreview() { +private fun UnBookmarkedPoseActionBarPreview() { NekiTheme { - PoseActionBar(isScrapped = false) + PoseActionBar(isBookmarked = false) } } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseContract.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseContract.kt index e1e9754e9..a0f160dba 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseContract.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseContract.kt @@ -9,8 +9,8 @@ data class PoseState( val isLoading: Boolean = false, val selectedPeopleCount: PeopleCount? = null, val selectedRandomPosePeopleCount: PeopleCount? = null, - val isShowScrappedPose: Boolean = false, - val scrappedPoseList: ImmutableList = persistentListOf(), + val isShowBookmarkedPose: Boolean = false, + val bookmarkedPoseList: ImmutableList = persistentListOf(), val isShowPeopleCountBottomSheet: Boolean = false, val isShowRandomPosePeopleCountBottomSheet: Boolean = false, ) @@ -21,13 +21,13 @@ sealed interface PoseIntent { data object ClickPeopleCountChip : PoseIntent data object DismissPeopleCountBottomSheet : PoseIntent data object DismissRandomPosePeopleCountBottomSheet : PoseIntent - data object ClickScrapChip : PoseIntent + data object ClickBookmarkChip : PoseIntent data class ClickPoseItem(val item: Pose) : PoseIntent data class ClickPeopleCountSheetItem(val peopleCount: PeopleCount) : PoseIntent data object ClickRandomPoseRecommendation : PoseIntent data class ClickRandomPosePeopleCountSheetItem(val peopleCount: PeopleCount) : PoseIntent data object ClickRandomPoseBottomSheetSelectButton : PoseIntent - data class ScrapChanged(val poseId: Long, val isScrapped: Boolean) : PoseIntent + data class BookmarkChanged(val poseId: Long, val isBookmarked: Boolean) : PoseIntent } sealed interface PoseEffect { diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseScreen.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseScreen.kt index 8f1192cc3..1a3b07d4e 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseScreen.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseScreen.kt @@ -80,11 +80,11 @@ fun PoseScreen( ) { PoseContent( selectedPeopleCount = uiState.selectedPeopleCount, - isScrapSelected = uiState.isShowScrappedPose, + isBookmarkSelected = uiState.isShowBookmarkedPose, posePagingItems = posePagingItems, onClickAlarmIcon = { onIntent(PoseIntent.ClickAlarmIcon) }, onClickPeopleCount = { onIntent(PoseIntent.ClickPeopleCountChip) }, - onClickScrap = { onIntent(PoseIntent.ClickScrapChip) }, + onClickBookmark = { onIntent(PoseIntent.ClickBookmarkChip) }, onClickPoseItem = { onIntent(PoseIntent.ClickPoseItem(it)) }, ) @@ -122,11 +122,11 @@ fun PoseScreen( fun PoseContent( modifier: Modifier = Modifier, selectedPeopleCount: PeopleCount?, - isScrapSelected: Boolean, + isBookmarkSelected: Boolean, posePagingItems: LazyPagingItems, onClickAlarmIcon: () -> Unit = {}, onClickPeopleCount: () -> Unit = {}, - onClickScrap: () -> Unit = {}, + onClickBookmark: () -> Unit = {}, onClickPoseItem: (Pose) -> Unit = {}, ) { val lazyState = rememberLazyStaggeredGridState() @@ -164,10 +164,10 @@ fun PoseContent( else filterBarHeightPx = size.height }, peopleCount = selectedPeopleCount, - isScrapSelected = isScrapSelected, + isBookmarkSelected = isBookmarkSelected, visible = showFilterBar, onClickPeopleCount = onClickPeopleCount, - onClickScrap = onClickScrap, + onClickBookmark = onClickBookmark, ) } } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseViewModel.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseViewModel.kt index ac0d30a90..451521f03 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseViewModel.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/PoseViewModel.kt @@ -26,18 +26,18 @@ internal class PoseViewModel @Inject constructor( ) : ViewModel() { private val _headCountFilter = MutableStateFlow(null) - private val _isScrapOnly = MutableStateFlow(false) - private val updatedScraps = MutableStateFlow>(emptyMap()) + private val _isBookmarkOnly = MutableStateFlow(false) + private val updatedBookmarks = MutableStateFlow>(emptyMap()) @OptIn(ExperimentalCoroutinesApi::class) private val originalPagingData: Flow> = combine( _headCountFilter, - _isScrapOnly, - ) { headCount, isScrapOnly -> - headCount to isScrapOnly - }.flatMapLatest { (headCount, isScrapOnly) -> - if (isScrapOnly) { - poseRepository.getScrappedPosesFlow() + _isBookmarkOnly, + ) { headCount, isBookmarkOnly -> + headCount to isBookmarkOnly + }.flatMapLatest { (headCount, isBookmarkOnly) -> + if (isBookmarkOnly) { + poseRepository.getBookmarkedPosesFlow() } else { poseRepository.getPosesFlow( headCount = headCount, @@ -48,11 +48,11 @@ internal class PoseViewModel @Inject constructor( val posePagingData: Flow> = combine( originalPagingData, - updatedScraps, - ) { pagingData, scraps -> + updatedBookmarks, + ) { pagingData, bookmarks -> pagingData.map { pose -> - scraps[pose.id]?.let { isScrapped -> - pose.copy(isScrapped = isScrapped) + bookmarks[pose.id]?.let { isBookmarked -> + pose.copy(isBookmarked = isBookmarked) } ?: pose } } @@ -77,13 +77,13 @@ internal class PoseViewModel @Inject constructor( is PoseIntent.ClickPeopleCountSheetItem -> handlePeopleCountSheetItem(intent, state, reduce) PoseIntent.DismissPeopleCountBottomSheet -> reduce { copy(isShowPeopleCountBottomSheet = false) } PoseIntent.DismissRandomPosePeopleCountBottomSheet -> reduce { copy(isShowRandomPosePeopleCountBottomSheet = false) } - PoseIntent.ClickScrapChip -> { - val newValue = !state.isShowScrappedPose - _isScrapOnly.value = newValue + PoseIntent.ClickBookmarkChip -> { + val newValue = !state.isShowBookmarkedPose + _isBookmarkOnly.value = newValue _headCountFilter.value = null reduce { copy( - isShowScrappedPose = newValue, + isShowBookmarkedPose = newValue, selectedPeopleCount = null, ) } @@ -106,8 +106,8 @@ internal class PoseViewModel @Inject constructor( postSideEffect(PoseEffect.NavigateToRandomPose(selectedCount)) } - is PoseIntent.ScrapChanged -> { - updatedScraps.update { it + (intent.poseId to intent.isScrapped) } + is PoseIntent.BookmarkChanged -> { + updatedBookmarks.update { it + (intent.poseId to intent.isBookmarked) } } } } @@ -117,12 +117,12 @@ internal class PoseViewModel @Inject constructor( state: PoseState, reduce: (PoseState.() -> PoseState) -> Unit, ) { - _isScrapOnly.value = false + _isBookmarkOnly.value = false if (intent.peopleCount == state.selectedPeopleCount) { _headCountFilter.value = null reduce { copy( - isShowScrappedPose = false, + isShowBookmarkedPose = false, isShowPeopleCountBottomSheet = false, selectedPeopleCount = null, ) @@ -131,7 +131,7 @@ internal class PoseViewModel @Inject constructor( _headCountFilter.value = intent.peopleCount reduce { copy( - isShowScrappedPose = false, + isShowBookmarkedPose = false, selectedPeopleCount = intent.peopleCount.takeIf { it != state.selectedPeopleCount }, isShowPeopleCountBottomSheet = false, ) diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/component/PoseFilterBar.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/component/PoseFilterBar.kt index cfd8fa773..40060e399 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/component/PoseFilterBar.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/component/PoseFilterBar.kt @@ -10,21 +10,21 @@ import com.neki.android.core.ui.component.FilterBar @Composable internal fun PoseFilterBar( peopleCount: PeopleCount?, - isScrapSelected: Boolean, + isBookmarkSelected: Boolean, modifier: Modifier = Modifier, visible: Boolean = true, onClickPeopleCount: () -> Unit = {}, - onClickScrap: () -> Unit = {}, + onClickBookmark: () -> Unit = {}, ) { FilterBar( isDownIconChipSelected = peopleCount != null, - isDefaultChipSelected = isScrapSelected, + isDefaultChipSelected = isBookmarkSelected, downIconChipDisplayText = peopleCount?.displayText ?: "인원수", - defaultChipDisplayText = "스크랩", + defaultChipDisplayText = "북마크", modifier = modifier, visible = visible, onClickDownIconChip = onClickPeopleCount, - onClickDefaultChip = onClickScrap, + onClickDefaultChip = onClickBookmark, ) } @@ -34,7 +34,7 @@ private fun PoseFilterBarPreview() { NekiTheme { PoseFilterBar( peopleCount = null, - isScrapSelected = false, + isBookmarkSelected = false, ) } } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/component/PoseListContent.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/component/PoseListContent.kt index a7a605fad..8d318ec20 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/component/PoseListContent.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/main/component/PoseListContent.kt @@ -104,13 +104,13 @@ private fun PoseItem( modifier = Modifier.matchParentSize(), shape = RoundedCornerShape(12.dp), ) - if (pose.isScrapped) { + if (pose.isBookmarked) { Icon( modifier = Modifier .align(Alignment.TopEnd) .padding(top = 10.dp, end = 10.dp) .size(20.dp), - imageVector = ImageVector.vectorResource(R.drawable.icon_scrap_filled), + imageVector = ImageVector.vectorResource(R.drawable.icon_bookmark_filled), contentDescription = null, tint = NekiTheme.colorScheme.white, ) diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/navigation/PoseEntryProvider.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/navigation/PoseEntryProvider.kt index 1fb159013..1e03bb044 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/navigation/PoseEntryProvider.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/navigation/PoseEntryProvider.kt @@ -43,8 +43,8 @@ private fun EntryProviderScope.poseEntry(navigator: MainNavigator) { ResultEffect(resultBus) { result -> when (result) { - is PoseResult.ScrapChanged -> { - viewModel.store.onIntent(PoseIntent.ScrapChanged(result.poseId, result.isScrapped)) + is PoseResult.BookmarkChanged -> { + viewModel.store.onIntent(PoseIntent.BookmarkChanged(result.poseId, result.isBookmarked)) } } } @@ -78,8 +78,8 @@ private fun EntryProviderScope.poseEntry(navigator: MainNavigator) { ResultEffect(resultBus) { result -> when (result) { - is PoseResult.ScrapChanged -> { - viewModel.store.onIntent(RandomPoseIntent.ScrapChanged(result.poseId, result.isScrapped)) + is PoseResult.BookmarkChanged -> { + viewModel.store.onIntent(RandomPoseIntent.BookmarkChanged(result.poseId, result.isBookmarked)) } } } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseContract.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseContract.kt index 3c61f360c..2ccbc573f 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseContract.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseContract.kt @@ -9,7 +9,7 @@ data class RandomPoseUiState( val isShowTutorial: Boolean = true, val currentIndex: Int = 0, val poseList: ImmutableList = persistentListOf(), - val committedScraps: Map = emptyMap(), + val committedBookmarks: Map = emptyMap(), val hasNewPose: Boolean = true, ) { val currentPose: Pose? @@ -31,10 +31,10 @@ sealed interface RandomPoseIntent { // 기본화면 data object ClickCloseIcon : RandomPoseIntent data object ClickGoToDetailIcon : RandomPoseIntent - data object ClickScrapIcon : RandomPoseIntent + data object ClickBookmarkIcon : RandomPoseIntent data object ClickLeftSwipe : RandomPoseIntent data object ClickRightSwipe : RandomPoseIntent - data class ScrapChanged(val poseId: Long, val isScrapped: Boolean) : RandomPoseIntent + data class BookmarkChanged(val poseId: Long, val isBookmarked: Boolean) : RandomPoseIntent } sealed interface RandomPoseEffect { diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseScreen.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseScreen.kt index 3b93625c8..92108f7f8 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseScreen.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseScreen.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.neki.android.core.designsystem.DevicePreview -import com.neki.android.core.designsystem.topbar.CloseTitleTopBar +import com.neki.android.core.designsystem.topbar.NekiTitleTopBar import com.neki.android.core.designsystem.ui.theme.NekiTheme import com.neki.android.core.ui.compose.VerticalSpacer import com.neki.android.core.ui.compose.collectWithLifecycle @@ -77,9 +77,8 @@ internal fun RandomPoseScreen( .fillMaxSize() .hazeSource(state = hazeState), ) { - CloseTitleTopBar( + NekiTitleTopBar( title = "랜덤포즈", - onClose = { onIntent(RandomPoseIntent.ClickCloseIcon) }, ) VerticalSpacer(42.dp) @@ -96,10 +95,10 @@ internal fun RandomPoseScreen( uiState.currentPose?.let { pose -> RandomPoseFloatingBarContent( modifier = Modifier.fillMaxWidth(), - isScrapped = pose.isScrapped, + isBookmarked = pose.isBookmarked, onClickClose = { onIntent(RandomPoseIntent.ClickCloseIcon) }, onClickGoToDetail = { onIntent(RandomPoseIntent.ClickGoToDetailIcon) }, - onClickScrap = { onIntent(RandomPoseIntent.ClickScrapIcon) }, + onClickBookmark = { onIntent(RandomPoseIntent.ClickBookmarkIcon) }, ) } } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseViewModel.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseViewModel.kt index 6f8f63f16..a16093dc5 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseViewModel.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/RandomPoseViewModel.kt @@ -31,7 +31,7 @@ internal class RandomPoseViewModel @AssistedInject constructor( @ApplicationScope private val applicationScope: CoroutineScope, ) : ViewModel() { - private val scrapJobs = mutableMapOf() + private val bookmarkJobs = mutableMapOf() @AssistedFactory interface Factory { @@ -67,18 +67,18 @@ internal class RandomPoseViewModel @AssistedInject constructor( } } - RandomPoseIntent.ClickScrapIcon -> { + RandomPoseIntent.ClickBookmarkIcon -> { val currentPost = state.currentPose ?: return - handleScrapToggle(currentPost.id, !currentPost.isScrapped, reduce) + handleBookmarkToggle(currentPost.id, !currentPost.isBookmarked, reduce) } - is RandomPoseIntent.ScrapChanged -> handleScrapToggle(intent.poseId, intent.isScrapped, reduce) + is RandomPoseIntent.BookmarkChanged -> handleBookmarkToggle(intent.poseId, intent.isBookmarked, reduce) } } - private fun handleScrapToggle( + private fun handleBookmarkToggle( poseId: Long, - newScrapStatus: Boolean, + newBookmarkStatus: Boolean, reduce: (RandomPoseUiState.() -> RandomPoseUiState) -> Unit, ) { // UI 즉시 업데이트 @@ -86,7 +86,7 @@ internal class RandomPoseViewModel @AssistedInject constructor( copy( poseList = poseList.map { pose -> if (pose.id == poseId) { - pose.copy(isScrapped = newScrapStatus) + pose.copy(isBookmarked = newBookmarkStatus) } else { pose } @@ -95,26 +95,26 @@ internal class RandomPoseViewModel @AssistedInject constructor( } // 해당 포즈의 이전 Job 취소 후 새로운 Job 시작 - scrapJobs[poseId]?.cancel() - scrapJobs[poseId] = viewModelScope.launch { + bookmarkJobs[poseId]?.cancel() + bookmarkJobs[poseId] = viewModelScope.launch { delay(500) - val committedScrap = store.uiState.value.committedScraps[poseId] - if (committedScrap == newScrapStatus || committedScrap == null) return@launch + val committedBookmark = store.uiState.value.committedBookmarks[poseId] + if (committedBookmark == newBookmarkStatus || committedBookmark == null) return@launch - poseRepository.updateScrap(poseId, newScrapStatus) + poseRepository.updateBookmark(poseId, newBookmarkStatus) .onSuccess { - Timber.d("updateScrap success for poseId: $poseId") + Timber.d("updateBookmark success for poseId: $poseId") reduce { - copy(committedScraps = committedScraps + (poseId to newScrapStatus)) + copy(committedBookmarks = committedBookmarks + (poseId to newBookmarkStatus)) } } .onFailure { error -> - Timber.e(error, "updateScrap failed for poseId: $poseId") + Timber.e(error, "updateBookmark failed for poseId: $poseId") reduce { copy( poseList = poseList.map { pose -> if (pose.id == poseId) { - pose.copy(isScrapped = committedScrap) + pose.copy(isBookmarked = committedBookmark) } else { pose } @@ -164,7 +164,7 @@ internal class RandomPoseViewModel @AssistedInject constructor( reduce { copy( poseList = (poseList + pose).toImmutableList(), - committedScraps = committedScraps + (pose.id to pose.isScrapped), + committedBookmarks = committedBookmarks + (pose.id to pose.isBookmarked), ) } }.onFailure { error -> @@ -218,7 +218,7 @@ internal class RandomPoseViewModel @AssistedInject constructor( copy( isLoading = false, poseList = data.toImmutableList(), - committedScraps = data.associate { it.id to it.isScrapped }, + committedBookmarks = data.associate { it.id to it.isBookmarked }, currentIndex = 0, ) } @@ -235,12 +235,12 @@ internal class RandomPoseViewModel @AssistedInject constructor( val state = store.uiState.value state.poseList.forEach { pose -> - val currentScrap = pose.isScrapped - val committedScrap = state.committedScraps[pose.id] + val currentBookmark = pose.isBookmarked + val committedBookmark = state.committedBookmarks[pose.id] - if (committedScrap != null && currentScrap != committedScrap) { + if (committedBookmark != null && currentBookmark != committedBookmark) { applicationScope.launch { - poseRepository.updateScrap(pose.id, currentScrap) + poseRepository.updateBookmark(pose.id, currentBookmark) } } } diff --git a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/component/RandomPoseFloatingBar.kt b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/component/RandomPoseFloatingBar.kt index 0b560a094..a60271fd7 100644 --- a/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/component/RandomPoseFloatingBar.kt +++ b/feature/pose/impl/src/main/java/com/neki/android/feature/pose/impl/random/component/RandomPoseFloatingBar.kt @@ -29,10 +29,10 @@ import com.neki.android.core.designsystem.ui.theme.NekiTheme @Composable internal fun RandomPoseFloatingBarContent( modifier: Modifier = Modifier, - isScrapped: Boolean = false, + isBookmarked: Boolean = false, onClickClose: () -> Unit = {}, onClickGoToDetail: () -> Unit = {}, - onClickScrap: () -> Unit = {}, + onClickBookmark: () -> Unit = {}, ) { Box( modifier = modifier, @@ -44,10 +44,10 @@ internal fun RandomPoseFloatingBarContent( modifier = Modifier .padding(horizontal = 20.dp) .padding(top = 38.dp, bottom = 34.dp), - isScrapped = isScrapped, + isBookmarked = isBookmarked, onClickClose = onClickClose, onClickGoToDetail = onClickGoToDetail, - onClickScrap = onClickScrap, + onClickBookmark = onClickBookmark, ) } } @@ -73,10 +73,10 @@ private fun RandomPoseFloatingBarBackground( @Composable private fun RandomPoseFloatingBar( modifier: Modifier = Modifier, - isScrapped: Boolean = false, + isBookmarked: Boolean = false, onClickClose: () -> Unit = {}, onClickGoToDetail: () -> Unit = {}, - onClickScrap: () -> Unit = {}, + onClickBookmark: () -> Unit = {}, ) { Row( modifier = modifier @@ -129,16 +129,16 @@ private fun RandomPoseFloatingBar( } RandomPoseButton( - onClick = onClickScrap, + onClick = onClickBookmark, backgroundColor = NekiTheme.colorScheme.primary400, ) { Icon( modifier = Modifier.size(24.dp), imageVector = ImageVector.vectorResource( - if (isScrapped) R.drawable.icon_scrap_filled - else R.drawable.icon_scrap_stroked, + if (isBookmarked) R.drawable.icon_bookmark_filled + else R.drawable.icon_bookmark_stroked, ), - contentDescription = "스크랩", + contentDescription = "북마크", tint = NekiTheme.colorScheme.white, ) } @@ -206,12 +206,12 @@ private fun RandomPoseFloatingBarContentPreview() { @ComponentPreview @Composable -private fun RandomPoseFloatingBarContentScrappedPreview() { +private fun RandomPoseFloatingBarContentBookmarkedPreview() { NekiTheme { RandomPoseFloatingBarContent( modifier = Modifier .fillMaxWidth(), - isScrapped = true, + isBookmarked = true, ) } }