diff --git a/data/src/main/java/pokitmons/pokit/data/repository/link/LinkRepositoryImpl.kt b/data/src/main/java/pokitmons/pokit/data/repository/link/LinkRepositoryImpl.kt index 6c4b621e..2bb81de1 100644 --- a/data/src/main/java/pokitmons/pokit/data/repository/link/LinkRepositoryImpl.kt +++ b/data/src/main/java/pokitmons/pokit/data/repository/link/LinkRepositoryImpl.kt @@ -109,7 +109,7 @@ class LinkRepositoryImpl @Inject constructor( categoryId = categoryId, memo = memo, alertYn = alertYn, - thumbNail = if (thumbNail.isEmpty()) thumbNail else null + thumbNail = thumbNail.ifEmpty { null } ) val response = dataSource.modifyLink(contentId = linkId, modifyLinkRequest = modifyLinkRequest) val mappedResponse = LinkMapper.mapperToLink(response) @@ -127,7 +127,7 @@ class LinkRepositoryImpl @Inject constructor( categoryId = categoryId, memo = memo, alertYn = alertYn, - thumbNail = if (thumbNail.isEmpty()) thumbNail else null + thumbNail = thumbNail.ifEmpty { null } ) val response = dataSource.createLink(createLinkRequest = createLinkRequest) val mappedResponse = LinkMapper.mapperToLink(response) diff --git a/domain/src/main/java/pokitmons/pokit/domain/model/pokit/PokitErrorCode.kt b/domain/src/main/java/pokitmons/pokit/domain/model/pokit/PokitErrorCode.kt index ab6521f2..948ef749 100644 --- a/domain/src/main/java/pokitmons/pokit/domain/model/pokit/PokitErrorCode.kt +++ b/domain/src/main/java/pokitmons/pokit/domain/model/pokit/PokitErrorCode.kt @@ -1,10 +1,10 @@ package pokitmons.pokit.domain.model.pokit object PokitErrorCode { - const val ALREADY_USED_POKIT_NAME = "C_001" - const val CANNOT_FOUND_POKIT_INFO = "C_002" - const val UNAVAILABLE_POKIT = "C_003" - const val CANNOT_FOUND_POKIT_IMAGE = "C_004" - const val TOO_MUCH_POKIT = "C_005" - const val CANNOT_FOUND_UNCATEGORY_IMAGE = "C_006" + const val ALREADY_USED_POKIT_NAME = "CA_001" + const val CANNOT_FOUND_POKIT_INFO = "CA_002" + const val UNAVAILABLE_POKIT = "CA_003" + const val CANNOT_FOUND_POKIT_IMAGE = "CA_004" + const val TOO_MUCH_POKIT = "CA_005" + const val CANNOT_FOUND_UNCATEGORY_IMAGE = "CA_006" } diff --git a/feature/addlink/src/main/java/com/strayalpaca/addlink/AddLinkScreen.kt b/feature/addlink/src/main/java/com/strayalpaca/addlink/AddLinkScreen.kt index b23cb3a0..0c4bd205 100644 --- a/feature/addlink/src/main/java/com/strayalpaca/addlink/AddLinkScreen.kt +++ b/feature/addlink/src/main/java/com/strayalpaca/addlink/AddLinkScreen.kt @@ -205,7 +205,7 @@ fun AddLinkScreen( Spacer(modifier = Modifier.height(16.dp)) if (state.link != null) { - Link(state.link) + Link(link = state.link, title = title.ifEmpty { null }) Spacer(modifier = Modifier.height(16.dp)) } @@ -224,7 +224,6 @@ fun AddLinkScreen( LabeledInput( label = stringResource(id = R.string.title), sub = "", - maxLength = 20, inputText = title, hintText = stringResource(id = R.string.placeholder_title), onChangeText = inputTitle, @@ -310,13 +309,13 @@ fun AddLinkScreen( toggleRemindRadio(it.second) }, getTitleFromItem = { it.first }, - enabled = enable + enabled = false ) Spacer(modifier = Modifier.height(8.dp)) Text( - text = stringResource(id = R.string.sub_remind), + text = stringResource(id = R.string.see_you_soon), style = PokitTheme.typography.detail1.copy(color = PokitTheme.colors.textTertiary) ) diff --git a/feature/addlink/src/main/java/com/strayalpaca/addlink/AddLinkViewModel.kt b/feature/addlink/src/main/java/com/strayalpaca/addlink/AddLinkViewModel.kt index 5ac42780..3ef65cd4 100644 --- a/feature/addlink/src/main/java/com/strayalpaca/addlink/AddLinkViewModel.kt +++ b/feature/addlink/src/main/java/com/strayalpaca/addlink/AddLinkViewModel.kt @@ -18,6 +18,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.orbitmvi.orbit.Container @@ -28,6 +29,7 @@ import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container import pokitmons.pokit.core.feature.navigation.args.LinkArg import pokitmons.pokit.core.feature.navigation.args.LinkUpdateEvent +import pokitmons.pokit.core.feature.navigation.args.PokitUpdateEvent import pokitmons.pokit.domain.commom.PokitResult import pokitmons.pokit.domain.model.pokit.MAX_POKIT_COUNT import pokitmons.pokit.domain.usecase.link.CreateLinkUseCase @@ -74,6 +76,8 @@ class AddLinkViewModel @Inject constructor( val currentLinkId: Int? = savedStateHandle.get("link_id")?.toIntOrNull() init { + initPokitAddEventDetector() + if (currentLinkId != null) { loadPokitLink(currentLinkId) } else { @@ -81,6 +85,18 @@ class AddLinkViewModel @Inject constructor( } } + private fun initPokitAddEventDetector() { + viewModelScope.launch { + PokitUpdateEvent.addedPokit.collectLatest { addedPokit -> + intent { + reduce { + state.copy(currentPokit = Pokit(addedPokit.title, addedPokit.id.toString(), 0)) + } + } + } + } + } + private fun loadUncategorizedPokit() { viewModelScope.launch { val response = getUncategorizedPokitUseCase.getUncategoriezdPokit() @@ -148,6 +164,9 @@ class AddLinkViewModel @Inject constructor( val response = getLinkCardUseCase.getLinkCard(linkUrl) if (response is PokitResult.Success) { reduce { state.copy(step = ScreenStep.IDLE, link = Link.fromDomainLinkCard(response.result)) } + if (response.result.title.isNotEmpty() && title.value.isEmpty()) { + _title.update { response.result.title } + } } else { reduce { state.copy(step = ScreenStep.IDLE) } } diff --git a/feature/addlink/src/main/java/com/strayalpaca/addlink/components/block/Link.kt b/feature/addlink/src/main/java/com/strayalpaca/addlink/components/block/Link.kt index 08299993..23a336da 100644 --- a/feature/addlink/src/main/java/com/strayalpaca/addlink/components/block/Link.kt +++ b/feature/addlink/src/main/java/com/strayalpaca/addlink/components/block/Link.kt @@ -12,12 +12,15 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import coil.compose.AsyncImage +import com.strayalpaca.addlink.R import com.strayalpaca.addlink.model.Link import pokitmons.pokit.core.ui.theme.PokitTheme import pokitmons.pokit.core.ui.utils.noRippleClickable @@ -25,10 +28,13 @@ import pokitmons.pokit.core.ui.utils.noRippleClickable @Composable internal fun Link( link: Link, + title: String?, modifier: Modifier = Modifier, openWebBrowserByClick: Boolean = true, ) { val uriHandler = LocalUriHandler.current + val placeHolder = stringResource(id = R.string.placeholder_title) + val linkTitle = remember(link, title) { title ?: link.title.ifEmpty { placeHolder } } Row( modifier = modifier @@ -60,7 +66,7 @@ internal fun Link( ) { Text( modifier = Modifier.fillMaxWidth(), - text = link.title, + text = linkTitle, maxLines = 2, style = PokitTheme.typography.body3Medium.copy(color = PokitTheme.colors.textSecondary) ) diff --git a/feature/addlink/src/main/java/com/strayalpaca/addlink/paging/PokitPaging.kt b/feature/addlink/src/main/java/com/strayalpaca/addlink/paging/PokitPaging.kt index aeeed146..581f5f91 100644 --- a/feature/addlink/src/main/java/com/strayalpaca/addlink/paging/PokitPaging.kt +++ b/feature/addlink/src/main/java/com/strayalpaca/addlink/paging/PokitPaging.kt @@ -19,6 +19,7 @@ class PokitPaging( private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO), private val initPage: Int = 0, private val firstRequestPage: Int = 3, + private val showUncategorizedPokit: Boolean = true, ) : SimplePaging { private val _pagingState = MutableStateFlow(SimplePagingState.IDLE) override val pagingState: StateFlow = _pagingState.asStateFlow() @@ -36,7 +37,7 @@ class PokitPaging( requestJob = coroutineScope.launch { try { currentPageIndex = initPage - val response = getPokits.getPokits(size = perPage * firstRequestPage, page = currentPageIndex) + val response = getPokits.getPokits(size = perPage * firstRequestPage, page = currentPageIndex, filterUncategorized = !showUncategorizedPokit) when (response) { is PokitResult.Success -> { val pokitList = response.result.map { domainPokit -> @@ -65,7 +66,7 @@ class PokitPaging( requestJob = coroutineScope.launch { try { - val response = getPokits.getPokits(size = perPage, page = currentPageIndex) + val response = getPokits.getPokits(size = perPage, page = currentPageIndex, filterUncategorized = !showUncategorizedPokit) when (response) { is PokitResult.Success -> { val pokitList = response.result.map { domainPokit -> diff --git a/feature/addlink/src/main/res/values/string.xml b/feature/addlink/src/main/res/values/string.xml index a87848ca..6db0e72a 100644 --- a/feature/addlink/src/main/res/values/string.xml +++ b/feature/addlink/src/main/res/values/string.xml @@ -5,7 +5,7 @@ 링크 내용을 입력해주세요. 제목 - 내용을 입력해주세요. + 제목을 입력해주세요. 포킷 메모 내용을 입력해주세요. @@ -22,4 +22,6 @@ 네트워크 에러가 발생했습니다. 네트워크 환경을 확인해주세요. 최대 30개의 포킷을 생성할 수 있습니다.\n포킷을 삭제한 뒤에 추가해주세요. + + 준비중인 기능이니 조금만 기다려주세요. \ No newline at end of file diff --git a/feature/addpokit/src/main/java/com/strayalpaca/addpokit/AddPokitScreen.kt b/feature/addpokit/src/main/java/com/strayalpaca/addpokit/AddPokitScreen.kt index 475eb701..aa5029f7 100644 --- a/feature/addpokit/src/main/java/com/strayalpaca/addpokit/AddPokitScreen.kt +++ b/feature/addpokit/src/main/java/com/strayalpaca/addpokit/AddPokitScreen.kt @@ -54,6 +54,7 @@ import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitButtonSize import pokitmons.pokit.core.ui.components.block.labeledinput.LabeledInput import pokitmons.pokit.core.ui.components.block.pokitlist.PokitList import pokitmons.pokit.core.ui.components.block.pokitlist.attributes.PokitListState +import pokitmons.pokit.core.ui.components.block.pokittoast.PokitToast import pokitmons.pokit.core.ui.components.template.bottomsheet.PokitBottomSheet import pokitmons.pokit.core.ui.theme.PokitTheme import pokitmons.pokit.core.ui.utils.noRippleClickable @@ -75,6 +76,7 @@ fun AddPokitScreenContainer( derivedStateOf { state.step != AddPokitScreenStep.POKIT_SAVE_LOADING && state.pokitInputErrorMessage == null && + state.errorToastMessage == null && state.pokitImage != null } } @@ -99,6 +101,7 @@ fun AddPokitScreenContainer( hideProfileSelectBottomSheet = viewModel::hidePokitProfileSelectBottomSheet, showSelectProfileBottomSheet = viewModel::showPokitProfileSelectBottomSheet, selectPokitProfileImage = viewModel::selectPokitProfile, + hideToastMessage = viewModel::hideToastMessage, pokits = pokits, pokitsState = pokitsState, loadPokits = viewModel::loadPokitList, @@ -117,6 +120,7 @@ fun AddPokitScreen( hideProfileSelectBottomSheet: () -> Unit = {}, showSelectProfileBottomSheet: () -> Unit = {}, selectPokitProfileImage: (PokitImage) -> Unit = {}, + hideToastMessage: () -> Unit = {}, pokits: List = emptyList(), pokitsState: SimplePagingState = SimplePagingState.IDLE, loadPokits: () -> Unit = {}, @@ -251,6 +255,17 @@ fun AddPokitScreen( trackColor = PokitTheme.colors.backgroundSecondary ) } + + state.errorToastMessage?.let { message -> + PokitToast( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomCenter) + .padding(start = 12.dp, end = 12.dp, bottom = 16.dp), + text = message, + onClickClose = hideToastMessage + ) + } } Box( diff --git a/feature/addpokit/src/main/java/com/strayalpaca/addpokit/AddPokitViewModel.kt b/feature/addpokit/src/main/java/com/strayalpaca/addpokit/AddPokitViewModel.kt index 0410116a..756d5e38 100644 --- a/feature/addpokit/src/main/java/com/strayalpaca/addpokit/AddPokitViewModel.kt +++ b/feature/addpokit/src/main/java/com/strayalpaca/addpokit/AddPokitViewModel.kt @@ -27,6 +27,7 @@ import org.orbitmvi.orbit.viewmodel.container import pokitmons.pokit.core.feature.navigation.args.PokitArg import pokitmons.pokit.core.feature.navigation.args.PokitUpdateEvent import pokitmons.pokit.domain.commom.PokitResult +import pokitmons.pokit.domain.model.pokit.PokitErrorCode import pokitmons.pokit.domain.usecase.pokit.CreatePokitUseCase import pokitmons.pokit.domain.usecase.pokit.GetPokitImagesUseCase import pokitmons.pokit.domain.usecase.pokit.GetPokitUseCase @@ -65,12 +66,18 @@ class AddPokitViewModel @Inject constructor( val pokitImages: StateFlow> = _pokitIamges.asStateFlow() init { - loadPokitList() + initPokitList() loadPokitImages() setAddModifyMode(pokitId) } + private fun initPokitList() { + viewModelScope.launch { + pokitPaging.refresh() + } + } + fun loadPokitList() { viewModelScope.launch { pokitPaging.load() @@ -117,9 +124,9 @@ class AddPokitViewModel @Inject constructor( _pokitName.update { pokitName } intent { - val isInAvailableLength = pokitName.length > POKIT_NAME_MAX_LENGTH + val isOutOfMaxLength = pokitName.length > POKIT_NAME_MAX_LENGTH - if (isInAvailableLength) { + if (isOutOfMaxLength) { val errorMessage = errorMessageProvider.getTextLengthErrorMessage() reduce { state.copy(pokitInputErrorMessage = errorMessage) } } else { @@ -129,6 +136,13 @@ class AddPokitViewModel @Inject constructor( } fun savePokit() = intent { + // todo 에러 코드 파싱 수정시 제거 필요 + if (pokitPaging.pagingData.value.find { it.title == pokitName.value } != null) { + val errorMessage = errorMessageProvider.errorCodeToMessage(PokitErrorCode.ALREADY_USED_POKIT_NAME) + reduce { state.copy(errorToastMessage = errorMessage) } + return@intent + } + reduce { state.copy(step = AddPokitScreenStep.POKIT_SAVE_LOADING) } @@ -159,7 +173,7 @@ class AddPokitViewModel @Inject constructor( } else { response as PokitResult.Error val errorMessage = errorMessageProvider.errorCodeToMessage(response.error.code) - reduce { state.copy(pokitInputErrorMessage = errorMessage) } + reduce { state.copy(errorToastMessage = errorMessage, step = AddPokitScreenStep.IDLE) } } } @@ -193,4 +207,10 @@ class AddPokitViewModel @Inject constructor( state.copy(pokitImage = pokitImage) } } + + fun hideToastMessage() = intent { + reduce { + state.copy(errorToastMessage = null) + } + } } diff --git a/feature/addpokit/src/main/java/com/strayalpaca/addpokit/model/AddPokitScreenState.kt b/feature/addpokit/src/main/java/com/strayalpaca/addpokit/model/AddPokitScreenState.kt index 78ae278f..d44ad256 100644 --- a/feature/addpokit/src/main/java/com/strayalpaca/addpokit/model/AddPokitScreenState.kt +++ b/feature/addpokit/src/main/java/com/strayalpaca/addpokit/model/AddPokitScreenState.kt @@ -8,6 +8,7 @@ data class AddPokitScreenState( val step: AddPokitScreenStep = AddPokitScreenStep.IDLE, val pokitImage: PokitImage? = null, val isModify: Boolean = false, + val errorToastMessage: String? = null, ) sealed class AddPokitScreenStep { diff --git a/feature/home/src/main/java/pokitmons/pokit/home/pokit/PokitViewModel.kt b/feature/home/src/main/java/pokitmons/pokit/home/pokit/PokitViewModel.kt index 3cb65303..06db6857 100644 --- a/feature/home/src/main/java/pokitmons/pokit/home/pokit/PokitViewModel.kt +++ b/feature/home/src/main/java/pokitmons/pokit/home/pokit/PokitViewModel.kt @@ -68,10 +68,10 @@ class PokitViewModel @Inject constructor( private fun initLinkAddEventDetector() { viewModelScope.launch { LinkUpdateEvent.addedLink.collectLatest { addedLink -> + linkPaging.refresh() val linkAddedPokit = pokitPaging.pagingData.value.find { it.id == addedLink.pokitId.toString() } ?: return@collectLatest val modifiedPokit = linkAddedPokit.copy(count = (linkAddedPokit.count + 1)) pokitPaging.modifyItem(modifiedPokit) - linkPaging.refresh() } } } @@ -162,6 +162,9 @@ class PokitViewModel @Inject constructor( private val _currentDetailShowLink = MutableStateFlow(null) val currentDetailShowLink = _currentDetailShowLink.asStateFlow() + private val _linkOptionBottomSheetType = MutableStateFlow(null) + val linkOptionBottomSheetType = _linkOptionBottomSheetType.asStateFlow() + init { initLinkUpdateEventDetector() initPokitUpdateEventDetector() @@ -288,17 +291,17 @@ class PokitViewModel @Inject constructor( } fun showLinkOptionBottomSheet(link: DetailLink) { - _pokitOptionBottomSheetType.update { BottomSheetType.MODIFY } + _linkOptionBottomSheetType.update { BottomSheetType.MODIFY } _currentSelectedLink.update { link } } fun hideLinkOptionBottomSheet() { - _pokitOptionBottomSheetType.update { null } + _linkOptionBottomSheetType.update { null } _currentSelectedLink.update { null } } fun showLinkRemoveBottomSheet() { - _pokitOptionBottomSheetType.update { BottomSheetType.REMOVE } + _linkOptionBottomSheetType.update { BottomSheetType.REMOVE } } fun removeCurrentSelectedLink() { diff --git a/feature/home/src/main/java/pokitmons/pokit/home/pokit/UnclassifiedScreen.kt b/feature/home/src/main/java/pokitmons/pokit/home/pokit/UnclassifiedScreen.kt index ad18e172..1dcea235 100644 --- a/feature/home/src/main/java/pokitmons/pokit/home/pokit/UnclassifiedScreen.kt +++ b/feature/home/src/main/java/pokitmons/pokit/home/pokit/UnclassifiedScreen.kt @@ -29,7 +29,7 @@ fun UnclassifiedScreen( ) { val unCategoryLinks = viewModel.unCategoryLinks.collectAsState() - val pokitOptionBottomSheetType by viewModel.pokitOptionBottomSheetType.collectAsState() + val pokitOptionBottomSheetType by viewModel.linkOptionBottomSheetType.collectAsState() val currentSelectedLink by viewModel.currentSelectedLink.collectAsState() val currentDetailShowLink by viewModel.currentDetailShowLink.collectAsState()