diff --git a/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorAndroidTest.kt b/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorAndroidTest.kt index ab19796188..d97050715a 100644 --- a/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorAndroidTest.kt +++ b/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorAndroidTest.kt @@ -15,10 +15,10 @@ import androidx.paging.PagingData import androidx.test.ext.junit.runners.AndroidJUnit4 import com.afternote.afternote_fe.test.FailureArtifactRule import com.afternote.afternote_fe.test.FakeErrorReporter +import com.afternote.afternote_fe.test.FakeUserRepository import com.afternote.core.ui.theme.AfternoteTheme import com.afternote.feature.afternote.domain.AfternoteType import com.afternote.feature.afternote.domain.model.author.AfternoteUpdatePayload -import com.afternote.feature.afternote.domain.model.author.AuthorReceiverEntry import com.afternote.feature.afternote.domain.model.author.CreateAccountPayload import com.afternote.feature.afternote.domain.model.author.CreateGalleryPayload import com.afternote.feature.afternote.domain.model.author.CreateMemorialPayload @@ -26,7 +26,6 @@ import com.afternote.feature.afternote.domain.model.author.Detail import com.afternote.feature.afternote.domain.model.author.ListItem import com.afternote.feature.afternote.domain.model.author.ProcessingMethod import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository -import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository import com.afternote.feature.afternote.domain.repository.author.MediaInput import com.afternote.feature.afternote.domain.repository.author.MediaKind import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository @@ -39,7 +38,6 @@ import com.afternote.feature.afternote.presentation.author.editor.model.EditorCa import com.afternote.feature.afternote.presentation.author.editor.model.RegisterAfternotePayload import com.afternote.feature.afternote.presentation.author.editor.state.AfternoteValidationError import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import org.junit.Assert.assertEquals import org.junit.Assert.assertNull @@ -171,7 +169,7 @@ class AfternoteAuthorAndroidTest { ): AfternoteEditorViewModel = AfternoteEditorViewModel( savedStateHandle = savedStateHandle, - authorReceiverRepository = FakeAuthorReceiverRepository(), + userRepository = FakeUserRepository(), afternoteRepository = repository, memorialThumbnailUploadRepository = MemorialThumbnailUploadRepository { Result.success("https://cdn.test/thumb.jpg") }, resolveMemorialMediaForSave = @@ -202,22 +200,6 @@ class AfternoteAuthorAndroidTest { ) } -private class FakeAuthorReceiverRepository : AuthorReceiverRepository { - private val receivers = MutableStateFlow(listOf(AuthorReceiverEntry(7L, "김수신", "가족"))) - - override fun currentAuthorUserId(): Long = 1L - - override fun observeReceivers(): Flow> = receivers - - override fun currentReceivers(): List = receivers.value - - override suspend fun refreshReceivers(): Result = Result.success(Unit) - - override suspend fun clearReceivers() { - receivers.value = emptyList() - } -} - private class FakeAfternoteRepository : AfternoteRepository { val createSocialPayloads = mutableListOf() val createSocialResults = ArrayDeque>() diff --git a/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorExtendedAndroidTest.kt b/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorExtendedAndroidTest.kt index 228984cd67..a920dfac69 100644 --- a/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorExtendedAndroidTest.kt +++ b/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorExtendedAndroidTest.kt @@ -46,7 +46,6 @@ import com.afternote.core.ui.theme.AfternoteTheme import com.afternote.feature.afternote.domain.AfternoteType import com.afternote.feature.afternote.domain.model.LeaveMessageBlock import com.afternote.feature.afternote.domain.model.author.AfternoteUpdatePayload -import com.afternote.feature.afternote.domain.model.author.AuthorReceiverEntry import com.afternote.feature.afternote.domain.model.author.CreateAccountPayload import com.afternote.feature.afternote.domain.model.author.CreateGalleryPayload import com.afternote.feature.afternote.domain.model.author.CreateMemorialPayload @@ -58,7 +57,6 @@ import com.afternote.feature.afternote.domain.model.author.ListItem import com.afternote.feature.afternote.domain.model.author.ProcessingMethod import com.afternote.feature.afternote.domain.model.author.ReceiverRefPayload import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository -import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository import com.afternote.feature.afternote.domain.repository.author.MediaInput import com.afternote.feature.afternote.domain.repository.author.MediaKind import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository @@ -81,7 +79,6 @@ import com.afternote.feature.afternote.presentation.author.home.AfternoteHomeEnt import com.afternote.feature.afternote.presentation.author.home.AfternoteHomeViewModel import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.launch import org.junit.Assert.assertEquals @@ -517,22 +514,6 @@ private class AdvancedAfternoteRepository( } } -private class ExtendedAuthorReceiverRepository : AuthorReceiverRepository { - private val receivers = MutableStateFlow(listOf(AuthorReceiverEntry(7L, "김수신", "가족"))) - - override fun currentAuthorUserId(): Long = 1L - - override fun observeReceivers(): Flow> = receivers - - override fun currentReceivers(): List = receivers.value - - override suspend fun refreshReceivers(): Result = Result.success(Unit) - - override suspend fun clearReceivers() { - receivers.value = emptyList() - } -} - private fun detailViewModel( repository: AdvancedAfternoteRepository, itemId: Long, @@ -550,7 +531,7 @@ private fun editorViewModel( ): AfternoteEditorViewModel = AfternoteEditorViewModel( savedStateHandle = SavedStateHandle(mapOf("itemId" to itemId)), - authorReceiverRepository = ExtendedAuthorReceiverRepository(), + userRepository = FakeUserRepository(), afternoteRepository = repository, memorialThumbnailUploadRepository = MemorialThumbnailUploadRepository { diff --git a/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorImplementedCoverageAndroidTest.kt b/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorImplementedCoverageAndroidTest.kt index b700a38714..3c6b817cf2 100644 --- a/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorImplementedCoverageAndroidTest.kt +++ b/app/src/androidTest/java/com/afternote/afternote_fe/AfternoteAuthorImplementedCoverageAndroidTest.kt @@ -12,12 +12,12 @@ import androidx.paging.PagingData import androidx.test.ext.junit.runners.AndroidJUnit4 import com.afternote.afternote_fe.test.FailureArtifactRule import com.afternote.afternote_fe.test.FakeErrorReporter +import com.afternote.afternote_fe.test.FakeUserRepository import com.afternote.core.ui.theme.AfternoteTheme import com.afternote.feature.afternote.domain.AfternoteType import com.afternote.feature.afternote.domain.model.LeaveMessageBlock import com.afternote.feature.afternote.domain.model.author.AfternoteAccountCredentials import com.afternote.feature.afternote.domain.model.author.AfternoteUpdatePayload -import com.afternote.feature.afternote.domain.model.author.AuthorReceiverEntry import com.afternote.feature.afternote.domain.model.author.CreateAccountPayload import com.afternote.feature.afternote.domain.model.author.CreateGalleryPayload import com.afternote.feature.afternote.domain.model.author.CreateMemorialPayload @@ -28,7 +28,6 @@ import com.afternote.feature.afternote.domain.model.author.MemorialVideoPayload import com.afternote.feature.afternote.domain.model.author.MemorialWritePayload import com.afternote.feature.afternote.domain.model.author.ProcessingMethod import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository -import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository import com.afternote.feature.afternote.domain.repository.author.MediaInput import com.afternote.feature.afternote.domain.repository.author.MediaKind import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository @@ -41,7 +40,6 @@ import com.afternote.feature.afternote.presentation.author.editor.message.Editor import com.afternote.feature.afternote.presentation.author.editor.model.EditorCategory import com.afternote.feature.afternote.presentation.author.editor.model.RegisterAfternotePayload import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import org.junit.Assert.assertEquals import org.junit.Rule @@ -310,22 +308,6 @@ private class ImplementedCoverageAfternoteRepository : AfternoteRepository { override suspend fun delete(id: Long): Result = error("unexpected delete") } -private class ImplementedCoverageAuthorReceiverRepository : AuthorReceiverRepository { - private val receivers = MutableStateFlow(listOf(AuthorReceiverEntry(7L, "김수신", "가족"))) - - override fun currentAuthorUserId(): Long = 1L - - override fun observeReceivers(): Flow> = receivers - - override fun currentReceivers(): List = receivers.value - - override suspend fun refreshReceivers(): Result = Result.success(Unit) - - override suspend fun clearReceivers() { - receivers.value = emptyList() - } -} - private fun implementedCoverageViewModel( repository: ImplementedCoverageAfternoteRepository, savedStateHandle: SavedStateHandle = SavedStateHandle(), @@ -334,7 +316,7 @@ private fun implementedCoverageViewModel( ): AfternoteEditorViewModel = AfternoteEditorViewModel( savedStateHandle = savedStateHandle, - authorReceiverRepository = ImplementedCoverageAuthorReceiverRepository(), + userRepository = FakeUserRepository(), afternoteRepository = repository, memorialThumbnailUploadRepository = MemorialThumbnailUploadRepository { diff --git a/feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/di/AfternoteAuthorRepositoryModule.kt b/feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/di/AfternoteAuthorRepositoryModule.kt index a64b3d80dc..b93becda86 100644 --- a/feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/di/AfternoteAuthorRepositoryModule.kt +++ b/feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/di/AfternoteAuthorRepositoryModule.kt @@ -1,12 +1,10 @@ package com.afternote.feature.afternote.data.di import com.afternote.feature.afternote.data.repositoryimpl.author.AfternoteRepositoryImpl -import com.afternote.feature.afternote.data.repositoryimpl.author.AuthorReceiverRepositoryImpl import com.afternote.feature.afternote.data.repositoryimpl.author.MemorialMediaUploadRepositoryImpl import com.afternote.feature.afternote.data.repositoryimpl.author.MemorialThumbnailUploadRepositoryImpl import com.afternote.feature.afternote.data.repositoryimpl.author.MusicSearchRepositoryImpl import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository -import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository import com.afternote.feature.afternote.domain.repository.author.MemorialThumbnailUploadRepository import com.afternote.feature.afternote.domain.repository.author.MusicSearchRepository @@ -24,11 +22,6 @@ interface AfternoteAuthorRepositoryModule { @Singleton fun bindAfternoteRepository(impl: AfternoteRepositoryImpl): AfternoteRepository - @Suppress("unused") - @Binds - @Singleton - fun bindAuthorReceiverRepository(impl: AuthorReceiverRepositoryImpl): AuthorReceiverRepository - @Suppress("unused") @Binds @Singleton diff --git a/feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/repositoryimpl/author/AuthorReceiverRepositoryImpl.kt b/feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/repositoryimpl/author/AuthorReceiverRepositoryImpl.kt deleted file mode 100644 index 9d54bf7d22..0000000000 --- a/feature/afternote/data/src/main/kotlin/com/afternote/feature/afternote/data/repositoryimpl/author/AuthorReceiverRepositoryImpl.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.afternote.feature.afternote.data.repositoryimpl.author - -import com.afternote.feature.afternote.domain.model.author.AuthorReceiverEntry -import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import javax.inject.Inject -import javax.inject.Singleton - -/** - * 작성자 수신자 목록 SSOT. API 연동 시 [refreshReceivers]에서 원격을 받아 갱신합니다. - */ -@Singleton -class AuthorReceiverRepositoryImpl - @Inject - constructor() : AuthorReceiverRepository { - private val receivers = - MutableStateFlow>(emptyList()) - - override fun observeReceivers(): Flow> = receivers.asStateFlow() - - override fun currentReceivers(): List = receivers.value - - // TODO: AuthDataSource 등 사용자 정보 의존성 주입 후 실제 값으로 교체 - override fun currentAuthorUserId(): Long? = null - - override suspend fun refreshReceivers(): Result { - val userId = - currentAuthorUserId() ?: run { - clearReceivers() - return Result.failure(IllegalStateException("No current author user id")) - } - return fetchReceiversForUser(userId) - .onSuccess { entries -> receivers.update { entries } } - .map { } - } - - override suspend fun clearReceivers() { - receivers.update { emptyList() } - } - - private suspend fun fetchReceiversForUser(userId: Long): Result> = Result.success(emptyList()) - } diff --git a/feature/afternote/domain/src/main/java/com/afternote/feature/afternote/domain/model/author/AuthorReceiverEntry.kt b/feature/afternote/domain/src/main/java/com/afternote/feature/afternote/domain/model/author/AuthorReceiverEntry.kt deleted file mode 100644 index 1851f135ab..0000000000 --- a/feature/afternote/domain/src/main/java/com/afternote/feature/afternote/domain/model/author/AuthorReceiverEntry.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.afternote.feature.afternote.domain.model.author - -data class AuthorReceiverEntry( - val receiverId: Long, - val name: String, - val relation: String, - val phone: String = "", -) diff --git a/feature/afternote/domain/src/main/java/com/afternote/feature/afternote/domain/repository/author/AuthorReceiverRepository.kt b/feature/afternote/domain/src/main/java/com/afternote/feature/afternote/domain/repository/author/AuthorReceiverRepository.kt deleted file mode 100644 index 4b444d57e7..0000000000 --- a/feature/afternote/domain/src/main/java/com/afternote/feature/afternote/domain/repository/author/AuthorReceiverRepository.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.afternote.feature.afternote.domain.repository.author - -import com.afternote.feature.afternote.domain.model.author.AuthorReceiverEntry -import kotlinx.coroutines.flow.Flow - -/** - * 작성자 본인의 userId 및 수신자 목록(이름/관계 조회용) 접근. - * - * 수신자 목록의 SSOT는 데이터 레이어 구현의 [observeReceivers] / [currentReceivers] 입니다. - * 로그아웃·계정 전환 시 [clearReceivers]로 비워 두면 UI 상태 오염을 막을 수 있습니다. - */ -interface AuthorReceiverRepository { - fun currentAuthorUserId(): Long? - - fun observeReceivers(): Flow> - - fun currentReceivers(): List - - suspend fun refreshReceivers(): Result - - suspend fun clearReceivers() -} diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/AfternoteEditorViewModel.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/AfternoteEditorViewModel.kt index 890477520d..43bb7afea9 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/AfternoteEditorViewModel.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/AfternoteEditorViewModel.kt @@ -6,13 +6,13 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute import com.afternote.core.common.reporting.ErrorReporter +import com.afternote.core.common.result.runCatchingCancellable +import com.afternote.core.domain.repository.UserRepository import com.afternote.feature.afternote.domain.error.AfternoteAuthoringValidationException import com.afternote.feature.afternote.domain.error.AfternoteAuthoringValidationKind -import com.afternote.feature.afternote.domain.model.author.AuthorReceiverEntry import com.afternote.feature.afternote.domain.model.author.CreateAfternoteInput import com.afternote.feature.afternote.domain.model.author.SaveAfternoteCommand import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository -import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository import com.afternote.feature.afternote.domain.repository.author.MediaInput import com.afternote.feature.afternote.domain.repository.author.MemorialThumbnailUploadRepository import com.afternote.feature.afternote.domain.usecase.editor.ResolveMemorialMediaForSaveUseCase @@ -194,7 +194,7 @@ class AfternoteEditorViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, - private val authorReceiverRepository: AuthorReceiverRepository, + private val userRepository: UserRepository, private val afternoteRepository: AfternoteRepository, private val memorialThumbnailUploadRepository: MemorialThumbnailUploadRepository, private val resolveMemorialMediaForSave: ResolveMemorialMediaForSaveUseCase, @@ -272,14 +272,6 @@ class AfternoteEditorViewModel ) = mutateForm { it.withProcessingMethodEdited(itemId = itemId, newText = newText) } init { - viewModelScope.launch { - authorReceiverRepository - .observeReceivers() - .map { it.toAfternoteEditorReceivers() } - .collect { mapped -> - internalState.update { it.copy(authorReceivers = mapped) } - } - } val editItemId = readEditItemId() if (editItemId == null) { savedStateHandle.remove(EDITOR_ORIGINAL_CATEGORY_FOR_API_KEY) @@ -307,9 +299,21 @@ class AfternoteEditorViewModel } } + /** + * 작성자가 등록한 수신자 전체를 받아 [InternalState.authorReceivers] 에 채운다. + * + * 신규 작성 진입 시 1회 호출된다. 폼이 비어 있으면 화면이 이 목록으로 수신자를 채우고 + * (`AfternoteNavGraphEditor` 의 `replaceReceiversIfEmpty`), 사용자는 불필요한 수신자를 지운다. + * 수정 진입은 상세 응답 prefill 이 지정 수신자를 채우므로 이 목록을 쓰지 않는다. + */ fun refreshAuthorReceivers() { viewModelScope.launch { - authorReceiverRepository.refreshReceivers() + runCatchingCancellable { userRepository.getReceivers() } + .onSuccess { receivers -> + internalState.update { it.copy(authorReceivers = receivers.toAfternoteEditorReceivers()) } + }.onFailure { e -> + errorReporter.recordAfternoteFailure(AfternoteFailureStage.AUTHOR_RECEIVER_LOAD, e) + } } } @@ -555,7 +559,8 @@ class AfternoteEditorViewModel } } - fun getReceiverById(id: Long): AuthorReceiverEntry? = authorReceiverRepository.currentReceivers().find { it.receiverId == id } + /** 수신자 선택 결과(id)를 폼에 넣기 위해 [refreshAuthorReceivers] 로 받아 둔 목록에서 이름·관계를 찾는다. */ + fun getReceiverById(id: Long): AfternoteEditorReceiver? = internalState.value.authorReceivers.find { it.id == id.toString() } private fun readOriginalCategoryForApiFromSavedState(): EditorCategory? = savedStateHandle diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/mapper/AuthorReceiverMapping.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/mapper/AuthorReceiverMapping.kt deleted file mode 100644 index 4a07922bbc..0000000000 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/mapper/AuthorReceiverMapping.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.afternote.feature.afternote.presentation.author.editor.mapper - -import com.afternote.feature.afternote.domain.model.author.AuthorReceiverEntry -import com.afternote.feature.afternote.presentation.author.editor.receiver.model.AfternoteEditorReceiver - -internal fun AuthorReceiverEntry.toAfternoteEditorReceiver(): AfternoteEditorReceiver = - AfternoteEditorReceiver( - id = receiverId.toString(), - name = name, - label = relation, - ) - -/** [AuthorReceiverEntry] 목록을 Edit 화면용 [AfternoteEditorReceiver] 목록으로 변환합니다. */ -internal fun Iterable.toAfternoteEditorReceivers(): List = - map { it.toAfternoteEditorReceiver() } diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/mapper/EditorReceiverMapping.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/mapper/EditorReceiverMapping.kt new file mode 100644 index 0000000000..fa5b93c717 --- /dev/null +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/mapper/EditorReceiverMapping.kt @@ -0,0 +1,14 @@ +package com.afternote.feature.afternote.presentation.author.editor.mapper + +import com.afternote.core.model.user.Receiver +import com.afternote.feature.afternote.presentation.author.editor.receiver.model.AfternoteEditorReceiver + +internal fun Receiver.toAfternoteEditorReceiver(): AfternoteEditorReceiver = + AfternoteEditorReceiver( + id = receiverId.toString(), + name = name, + label = relation, + ) + +/** 사용자가 등록한 수신자([Receiver]) 목록을 에디터 표시 모델로 변환합니다. */ +internal fun List.toAfternoteEditorReceivers(): List = map { it.toAfternoteEditorReceiver() } diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/navigation/AfternoteNavGraphEditor.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/navigation/AfternoteNavGraphEditor.kt index 7caa8ff649..724c6b7544 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/navigation/AfternoteNavGraphEditor.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/navigation/AfternoteNavGraphEditor.kt @@ -33,7 +33,7 @@ internal fun tryApplyReceiverSelectionFromSavedState( val id = backStackEntry.savedStateHandle[SELECTED_RECEIVER_ID_KEY] as? Long ?: return backStackEntry.savedStateHandle.remove(SELECTED_RECEIVER_ID_KEY) val receiver = viewModel.getReceiverById(id) ?: return - state.addReceiverById(receiver.receiverId, receiver.name, receiver.relation) + state.addReceiverById(id, receiver.name, receiver.label) } internal fun buildOnRegisterClick( diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/reporting/AfternoteFailureReporting.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/reporting/AfternoteFailureReporting.kt index 4bbdb997bb..30074dca2f 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/reporting/AfternoteFailureReporting.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/reporting/AfternoteFailureReporting.kt @@ -21,6 +21,15 @@ enum class AfternoteFailureStage( /** 수정 진입 시 기존 애프터노트 로드 — 여기서 깨지면 빈 폼으로 덮어쓸 위험이 있다. */ PREFILL_LOAD("prefill_load"), + /** + * 신규 작성 진입 시 작성자가 등록한 수신자 목록 조회. + * + * 실패해도 화면에는 수신자 자리가 비어 보일 뿐이라 계측하지 않으면 흔적이 남지 않는다. + * 수신자는 저장 필수값(서버 코드 475)이므로, 여기서 조용히 실패하면 사용자는 원인을 알 수 없는 + * 검증 오류만 만나게 된다. + */ + AUTHOR_RECEIVER_LOAD("author_receiver_load"), + MEMORIAL_THUMBNAIL_UPLOAD("memorial_thumbnail_upload"), /**