Skip to content

다시 대화하기(화면 이동), 삭제하기(카드 삭제하기) #143

@theBettor

Description

@theBettor

1. 대화 전체 보기 : eed379e

이 화면은 2개의 유즈케이스가 필요할듯(질문과, 답변)

2. 다시 대화하기

:
탐구 방법

  1. 추억카드 생성 -> 추억저장소 로 이동하게됨
  2. 피그마가 매우 불친절하게 되어있음.. '모니는 새로운 대화 내용이 아닌 이전 대화 데이터를 반영하여 그와 연결되는 대화를 시작한다.'
    -> MemoryCard의 text를 초기화해야겠다. 질문은 어떻게 해야할지 확신이 안선다.
  3. 그렇다면 뷰모델에 새로운 함수가 필요하다
    : 파라미터에 메모리카드가 필요할 것이고, 그 중에 text만 초기화해야함.

❗️❗️❗️-> 중단!!!

: text를 초기화한다는게 RoomDB를 업데이트 해야하기 때문에 엔티티로 변환하는 작업이 필요하대서 잘 몰라가지고 중단

3. 삭제하기 : 10f6267

: id는 뷰모델을 통해 삭제됨을 보여주고, 동시에 Routed의 파리미터는 전화면으로 가게 만들어줬다.

배경

사용자가 카드 상세 보기에서 삭제하기를 눌렀을 때 DB 및 UI에서 제거되어야 함
ViewModel은 UseCase만 의존해야 하므로, 직접 Repository를 호출하는 대신 전용 UseCase가 필요
Room에서 DELETE는 반드시 비동기(Dispatchers.IO) 에서 실행되어야 하므로 안전한 실행 흐름이 요구됨

🧩 Step 1. MemoryCardRepository에 삭제 함수 추가
🧩 Step 2. Repository 구현에 삭제 로직 추가 (LocalMemoryCardRepositoryImpl)

override suspend fun deleteMemoryCard(memoryCardId: String) {
    withContext(Dispatchers.IO) { // ✅ Room DB는 IO 디스패처에서 실행
        val id = memoryCardId.toLong()
        memoryCardDao.deleteMemoryStorageById(id)
    }
}

🧩 Step 3. Usecase생성
🧩 Step 4. MemoryStorageDetailViewModel에서 삭제 로직 추가
🧩 Step 5. MemoryStorageDetailScreen → BottomSheet로 삭제 이벤트 전달

BottomSheetForMemory(
    showBottomSheet = showBottomSheet,
    onDismiss = { showBottomSheet = false },
    onRestartConversation = {
        showBottomSheet = false
        onRestartConversation()
    },
    memoryCardId = memory?.id ?: "", // ✅ id 전달
    deleteCardRequest = deleteCardRequest // (String) -> Unit
)

🧩 Step 6. BottomSheetForMemory에서 삭제 요청 처리

Text(
    text = "삭제하기",
    modifier = Modifier
        .fillMaxWidth()
        .padding(top = 23.dp)
        .clickable {
            deleteCardRequest(memoryCardId) // 전달받은 ID 사용
        }
)

🧩 Step 7. MemoryStorageDetailRoute에서 ViewModel + 삭제 후처리 조합

when (uiState) {
        is MemoryStorageDetailUiState.Loading -> {
            // TODO: 로딩 UI
        }

        is MemoryStorageDetailUiState.Error -> {
            // TODO: 에러 UI
        }

        is MemoryStorageDetailUiState.Success -> {
            val state = uiState as MemoryStorageDetailUiState.Success
            when (state.screenState) {
                MemoryStorageDetailScreenState.Detail -> {
                    MemoryStorageDetailScreen(
                        memoryStorageDetailUiState = state,
                        onBackRequest = onBackRequest,
                        onShowConversation = viewModel::showConversation,
                        onRestartConversation = onRestartConversation,
                        deleteCardRequest = {
                            viewModel.deleteMemoryCard()
                        }
                    )
                }

                MemoryStorageDetailScreenState.Conversation -> {
                    ConversationView(
                        onDismiss = viewModel::showDetail,
                        onRestartConversation = onRestartConversation
                    )
                }
            }
        }
    }
    LaunchedEffect(Unit) {
        lifecycleOwner.lifecycleScope.launch {
            viewModel.event.collect { event ->
                when (event) {
                    is MemoryStorageDetailEvent.Deleted -> {
                        deleteCardRequest()
                    }

                    is MemoryStorageDetailEvent.DeleteError -> {
                        Toast.makeText(context, event.message, Toast.LENGTH_SHORT).show()
                    }

                    else -> {}
                }
            }
        }
    }

✅ 테스트 결과 및 결론

  • ViewModel은 memoryCardId를 안전하게 처리하고 예외도 전송함
  • 실제 DB에서는 withContext(Dispatchers.IO) 덕분에 Room의 IllegalStateException 방지
  • 삭제 성공 시 Deleted 이벤트, 실패 시 DeleteError 이벤트로 사용자에게 피드백 제공
  • UI에서 Toast, popBackStack() 등으로 자연스러운 UX 흐름 제공 가능

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions