From 4093616f7e3a212498c2a8999021a18d51c87f1c Mon Sep 17 00:00:00 2001 From: mariiapanasetskaia Date: Mon, 29 Jun 2026 11:39:11 +0200 Subject: [PATCH 1/8] entrypoints with resumable claim --- .../app/navigation/HedvigEntryProvider.kt | 8 +++- .../system/hedvig/StartClaimBottomSheet.kt | 40 ++++++++++++++++++- .../feature/chat/inbox/InboxDestination.kt | 6 ++- .../claim/chat/navigation/ClaimChatEntries.kt | 1 + .../src/main/graphql/QueryHome.graphql | 3 ++ .../home/home/data/GetHomeDataUseCase.kt | 2 + .../home/home/data/GetHomeDataUseCaseDemo.kt | 1 + .../home/home/navigation/HomeEntries.kt | 4 +- .../feature/home/home/ui/HomeDestination.kt | 22 +++++++--- .../feature/home/home/ui/HomePresenter.kt | 5 +++ 10 files changed, 79 insertions(+), 13 deletions(-) diff --git a/app/app/src/main/kotlin/com/hedvig/android/app/navigation/HedvigEntryProvider.kt b/app/app/src/main/kotlin/com/hedvig/android/app/navigation/HedvigEntryProvider.kt index 36905da0e5..7b6f04cc6e 100644 --- a/app/app/src/main/kotlin/com/hedvig/android/app/navigation/HedvigEntryProvider.kt +++ b/app/app/src/main/kotlin/com/hedvig/android/app/navigation/HedvigEntryProvider.kt @@ -230,8 +230,12 @@ private fun EntryProviderScope.addHomeEntries( backstack.add(CoInsuredAddInfoKey(contractId, type)) }, navigateToHelpCenter = { backstack.add(HelpCenterKey) }, - navigateToClaimChat = { - backstack.add(ClaimChatKey(messageId = null, isDevelopmentFlow = false)) + navigateToClaimChat = { resumableClaimId -> + backstack.add(ClaimChatKey( + messageId = null, + isDevelopmentFlow = false, + resumableClaimId = resumableClaimId, + )) }, navigateToChipIdScreen = { backstack.add(ChipIdKey()) }, openAppSettings = externalNavigator::openAppSettings, diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/StartClaimBottomSheet.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/StartClaimBottomSheet.kt index 558f31da43..6b168aeef1 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/StartClaimBottomSheet.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/StartClaimBottomSheet.kt @@ -23,8 +23,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.dropUnlessResumed +import com.hedvig.android.compose.ui.preview.BooleanCollectionPreviewParameterProvider import com.hedvig.android.design.system.hedvig.api.HedvigBottomSheetState import com.hedvig.android.design.system.hedvig.icon.Checkmark import com.hedvig.android.design.system.hedvig.icon.HedvigIcons @@ -40,10 +42,12 @@ import hedvig.resources.general_cancel_button import hedvig.resources.general_continue_button import org.jetbrains.compose.resources.stringResource +data class StartClaimSheetData(val resumableClaimId: String?) @Composable fun StartClaimBottomSheet( - state: HedvigBottomSheetState, + state: HedvigBottomSheetState, navigateToClaimChat: () -> Unit, + navigateToOldClaim: () -> Unit, ) { HedvigBottomSheet( hedvigBottomSheetState = state, @@ -57,6 +61,12 @@ fun StartClaimBottomSheet( navigateToClaimChat() } }, + navigateToOldClaim = { + state.dismiss { + navigateToOldClaim() + } + }, + resumableClaimId = state.data?.resumableClaimId ) }, ) @@ -82,6 +92,8 @@ fun StartClaimPledgeScreen( }, navigateToClaimChat = navigateToClaimChat, dismiss = navigateUp, + resumableClaimId = null, + navigateToOldClaim = {} ) Spacer(Modifier.height(8.dp)) Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) @@ -92,6 +104,8 @@ fun StartClaimPledgeScreen( private fun StartClaimBottomSheetContent( dismiss: () -> Unit, navigateToClaimChat: () -> Unit, + navigateToOldClaim: () -> Unit, + resumableClaimId: String? ) { var isChecked by remember { mutableStateOf(false) } Column { @@ -113,6 +127,8 @@ private fun StartClaimBottomSheetContent( }, navigateToClaimChat = navigateToClaimChat, dismiss = dismiss, + navigateToOldClaim = navigateToOldClaim, + resumableClaimId = resumableClaimId ) Spacer(Modifier.height(8.dp)) Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) @@ -125,6 +141,8 @@ private fun StartClaimBottomContent( onCheckedChange: () -> Unit, navigateToClaimChat: () -> Unit, dismiss: () -> Unit, + navigateToOldClaim: () -> Unit, + resumableClaimId: String? ) { Column { ImportantInfoCheckBox( @@ -141,6 +159,18 @@ private fun StartClaimBottomContent( modifier = Modifier.fillMaxWidth(), ) Spacer(Modifier.height(16.dp)) + if (resumableClaimId!=null) { + HedvigButton( + buttonStyle = ButtonDefaults.ButtonStyle.PrimaryAlt, + text = "Continue with the draft claim", + enabled = true, + onClick = dropUnlessResumed { + navigateToOldClaim() + }, + modifier = Modifier.fillMaxWidth(), + ) + Spacer(Modifier.height(16.dp)) + } HedvigButton( text = stringResource(Res.string.general_cancel_button), enabled = true, @@ -216,12 +246,18 @@ private fun ImportantInfoCheckBox(isChecked: Boolean, onCheckedChange: () -> Uni @HedvigPreview @Composable -private fun PreviewStartClaimBottomSheetContent() { +private fun PreviewStartClaimBottomSheetContent( + @PreviewParameter( + BooleanCollectionPreviewParameterProvider::class, + ) hasResumableClaim: Boolean, +) { HedvigTheme { Surface(color = HedvigTheme.colorScheme.backgroundPrimary) { StartClaimBottomSheetContent( {}, navigateToClaimChat = {}, + navigateToOldClaim = {}, + resumableClaimId = if (hasResumableClaim) "" else null ) } } diff --git a/app/feature/feature-chat/src/main/kotlin/com/hedvig/android/feature/chat/inbox/InboxDestination.kt b/app/feature/feature-chat/src/main/kotlin/com/hedvig/android/feature/chat/inbox/InboxDestination.kt index 390005cba1..59d8410e99 100644 --- a/app/feature/feature-chat/src/main/kotlin/com/hedvig/android/feature/chat/inbox/InboxDestination.kt +++ b/app/feature/feature-chat/src/main/kotlin/com/hedvig/android/feature/chat/inbox/InboxDestination.kt @@ -61,6 +61,7 @@ import com.hedvig.android.design.system.hedvig.HighlightLabelDefaults.HighlightS import com.hedvig.android.design.system.hedvig.HorizontalItemsWithMaximumSpaceTaken import com.hedvig.android.design.system.hedvig.Icon import com.hedvig.android.design.system.hedvig.StartClaimBottomSheet +import com.hedvig.android.design.system.hedvig.StartClaimSheetData import com.hedvig.android.design.system.hedvig.Surface import com.hedvig.android.design.system.hedvig.TopAppBar import com.hedvig.android.design.system.hedvig.TopAppBarActionType @@ -131,7 +132,7 @@ private fun InboxScreen( navigateToClaimChat: () -> Unit, ) { val newChatSelectBottomSheetState = rememberHedvigBottomSheetState() - val startClaimBottomSheetState = rememberHedvigBottomSheetState() + val startClaimBottomSheetState = rememberHedvigBottomSheetState() HedvigBottomSheet( newChatSelectBottomSheetState, content = { @@ -142,7 +143,7 @@ private fun InboxScreen( }, onStartNewClaim = { newChatSelectBottomSheetState.dismiss() - startClaimBottomSheetState.show(Unit) + startClaimBottomSheetState.show(StartClaimSheetData(null)) }, dismiss = { newChatSelectBottomSheetState.dismiss() @@ -156,6 +157,7 @@ private fun InboxScreen( startClaimBottomSheetState.dismiss() navigateToClaimChat() }, + navigateToOldClaim = {} ) Surface( color = HedvigTheme.colorScheme.backgroundPrimary, diff --git a/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt b/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt index 93494fd1bc..f0e6c7308b 100644 --- a/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt +++ b/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt @@ -21,6 +21,7 @@ import kotlinx.serialization.Serializable data class ClaimChatKey( val isDevelopmentFlow: Boolean = false, val messageId: String? = null, + val resumableClaimId: String? = null, ) : HedvigNavKey @Serializable diff --git a/app/feature/feature-home/src/main/graphql/QueryHome.graphql b/app/feature/feature-home/src/main/graphql/QueryHome.graphql index c333001488..c971555513 100644 --- a/app/feature/feature-home/src/main/graphql/QueryHome.graphql +++ b/app/feature/feature-home/src/main/graphql/QueryHome.graphql @@ -1,5 +1,8 @@ query Home($claimsHistoryFlag: Boolean!) { currentMember { + resumableClaimIntent { + id + } claims@skip(if: $claimsHistoryFlag) { ...ClaimFragment } diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/data/GetHomeDataUseCase.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/data/GetHomeDataUseCase.kt index c4624d0ea3..86a890c4c1 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/data/GetHomeDataUseCase.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/data/GetHomeDataUseCase.kt @@ -172,6 +172,7 @@ internal class GetHomeDataUseCaseImpl( crossSells = crossSells, travelBannerInfo = travelBannerInfo?.firstOrNull(), showChatIcon = showChatIcon, + resumableClaimId = homeQueryData.currentMember.resumableClaimIntent?.id ) }.onLeft { error: ApolloOperationError -> logcat(operationError = error) { "GetHomeDataUseCase failed with $error" } @@ -280,6 +281,7 @@ data class HomeData( val firstVetSections: List, val crossSells: CrossSellSheetData, val travelBannerInfo: AddonBannerInfo?, + val resumableClaimId: String? ) { @Immutable data class ClaimStatusCardsData( diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/data/GetHomeDataUseCaseDemo.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/data/GetHomeDataUseCaseDemo.kt index 4ee160b208..fc50dfc2ea 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/data/GetHomeDataUseCaseDemo.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/data/GetHomeDataUseCaseDemo.kt @@ -56,6 +56,7 @@ internal class GetHomeDataUseCaseDemo : GetHomeDataUseCase { ), travelBannerInfo = null, showChatIcon = false, + resumableClaimId = null ).right(), ) } diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/navigation/HomeEntries.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/navigation/HomeEntries.kt index fbac21457e..885cc4c4f9 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/navigation/HomeEntries.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/navigation/HomeEntries.kt @@ -25,7 +25,7 @@ fun EntryProviderScope.homeEntries( navigateToContactInfo: () -> Unit, navigateToMissingInfo: (String, CoInsuredFlowType) -> Unit, navigateToHelpCenter: () -> Unit, - navigateToClaimChat: () -> Unit, + navigateToClaimChat: (String?) -> Unit, navigateToChipIdScreen: () -> Unit, openAppSettings: () -> Unit, openUrl: (String) -> Unit, @@ -38,7 +38,7 @@ fun EntryProviderScope.homeEntries( viewModel = viewModel, onNavigateToInbox = dropUnlessResumed { onNavigateToInbox() }, onNavigateToNewConversation = dropUnlessResumed { onNavigateToNewConversation() }, - navigateToClaimChat = dropUnlessResumed { navigateToClaimChat() }, + navigateToClaimChat = navigateToClaimChat, onClaimDetailCardClicked = dropUnlessResumed { claimId: String -> navigateToClaimDetails(claimId) }, diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt index d0c15818c5..9ef4a72fa3 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt @@ -86,6 +86,7 @@ import com.hedvig.android.design.system.hedvig.LocalContentColor import com.hedvig.android.design.system.hedvig.NotificationDefaults import com.hedvig.android.design.system.hedvig.NotificationDefaults.NotificationPriority import com.hedvig.android.design.system.hedvig.StartClaimBottomSheet +import com.hedvig.android.design.system.hedvig.StartClaimSheetData import com.hedvig.android.design.system.hedvig.Surface import com.hedvig.android.design.system.hedvig.TooltipDefaults import com.hedvig.android.design.system.hedvig.TooltipDefaults.BeakDirection.TopEnd @@ -155,7 +156,7 @@ internal fun HomeDestination( viewModel: HomeViewModel, onNavigateToInbox: () -> Unit, onNavigateToNewConversation: () -> Unit, - navigateToClaimChat: () -> Unit, + navigateToClaimChat: (String?) -> Unit, onClaimDetailCardClicked: (claimId: String) -> Unit, navigateToConnectPayment: () -> Unit, navigateToConnectPayout: () -> Unit, @@ -205,7 +206,7 @@ private fun HomeScreen( reload: () -> Unit, onNavigateToInbox: () -> Unit, onNavigateToNewConversation: () -> Unit, - navigateToClaimChat: () -> Unit, + navigateToClaimChat: (String?) -> Unit, onClaimDetailCardClicked: (claimId: String) -> Unit, navigateToConnectPayment: () -> Unit, navigateToConnectPayout: () -> Unit, @@ -237,10 +238,17 @@ private fun HomeScreen( onCrossSellClick = openCrossSellUrl, imageLoader = imageLoader, ) - val startClaimBottomSheetState = rememberHedvigBottomSheetState() + + val resumableClaimId = (uiState as? Success)?.resumableClaimId + val startClaimBottomSheetState = rememberHedvigBottomSheetState() StartClaimBottomSheet( state = startClaimBottomSheetState, - navigateToClaimChat = navigateToClaimChat, + navigateToOldClaim = { + navigateToClaimChat(resumableClaimId) + }, + navigateToClaimChat = { + navigateToClaimChat(null) + }, ) Box(Modifier.fillMaxSize()) { val toolbarHeight = 64.dp @@ -277,7 +285,9 @@ private fun HomeScreen( navigateToConnectPayment = navigateToConnectPayment, navigateToConnectPayout = navigateToConnectPayout, navigateToHelpCenter = navigateToHelpCenter, - openClaimFlowSheet = startClaimBottomSheetState::show, + openClaimFlowSheet = { + startClaimBottomSheetState.show(StartClaimSheetData(resumableClaimId)) + }, openAppSettings = openAppSettings, openUrl = openUrl, navigateToMissingInfo = navigateToMissingInfo, @@ -796,6 +806,7 @@ private fun PreviewHomeScreen( flowType = FlowType.APP_TRAVEL_PLUS_SELL_OR_UPGRADE, ), isProduction = true, + resumableClaimId = null ), notificationPermissionState = rememberPreviewNotificationPermissionState(), reload = {}, @@ -881,6 +892,7 @@ private fun PreviewHomeScreenAllHomeTextTypes( chatAction = ChatAction, addonBannerInfo = null, isProduction = true, + resumableClaimId = null ), notificationPermissionState = rememberPreviewNotificationPermissionState(), reload = {}, diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomePresenter.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomePresenter.kt index fafa5cb3bc..3569e4b513 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomePresenter.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomePresenter.kt @@ -138,6 +138,7 @@ internal class HomePresenter( crossSellsAction = successData.crossSellsAction, addonBannerInfo = successData.addonBannerInfo, isProduction = isProduction, + resumableClaimId = successData.resumableClaimId ) } } @@ -177,6 +178,7 @@ internal sealed interface HomeUiState { val isProduction: Boolean, override val isHelpCenterEnabled: Boolean, override val hasUnseenChatMessages: Boolean, + val resumableClaimId: String? ) : HomeUiState data class Error(val message: String?) : HomeUiState @@ -195,6 +197,7 @@ private data class SuccessData( val crossSellsAction: HomeTopBarAction.CrossSellsAction?, val hasUnseenChatMessages: Boolean, val addonBannerInfo: AddonBannerInfo?, + val resumableClaimId: String? ) { companion object { fun fromLastState(lastState: HomeUiState): SuccessData? { @@ -210,6 +213,7 @@ private data class SuccessData( hasUnseenChatMessages = lastState.hasUnseenChatMessages, addonBannerInfo = lastState.addonBannerInfo, chatAction = lastState.chatAction, + resumableClaimId = lastState.resumableClaimId ) } @@ -257,6 +261,7 @@ private data class SuccessData( hasUnseenChatMessages = homeData.hasUnseenChatMessages, addonBannerInfo = homeData.travelBannerInfo, chatAction = if (homeData.showChatIcon) HomeTopBarAction.ChatAction else null, + resumableClaimId = homeData.resumableClaimId ) } } From 8817524e0ab6751c95710891378b32e0dac2592b Mon Sep 17 00:00:00 2001 From: mariiapanasetskaia Date: Mon, 29 Jun 2026 16:17:08 +0200 Subject: [PATCH 2/8] mapping of previous steps --- .../claim/chat/data/AudioRecordingManager.kt | 4 +- .../claim/chat/navigation/ClaimChatEntries.kt | 1 + .../graphql/FragmentClaimIntent.graphql | 19 ++++ .../graphql/ResumeClaimQuery.graphql | 7 ++ .../feature/claim/chat/ClaimChatViewModel.kt | 87 ++++++++++++++----- .../feature/claim/chat/data/ClaimIntent.kt | 14 ++- .../feature/claim/chat/data/ClaimIntentExt.kt | 37 +++++++- .../claim/chat/data/ResumeClaimUseCase.kt | 39 +++++++++ .../claim/chat/ui/ClaimChatDestination.kt | 3 +- .../claim/chat/ui/step/UploadFilesStep.kt | 1 + .../AudioRecordingStepSections.kt | 28 ++++-- 11 files changed, 202 insertions(+), 38 deletions(-) create mode 100644 app/feature/feature-claim-chat/src/commonMain/graphql/ResumeClaimQuery.graphql create mode 100644 app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ResumeClaimUseCase.kt diff --git a/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/data/AudioRecordingManager.kt b/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/data/AudioRecordingManager.kt index f1e086ab48..63eead9f66 100644 --- a/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/data/AudioRecordingManager.kt +++ b/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/data/AudioRecordingManager.kt @@ -86,7 +86,7 @@ internal class AndroidAudioRecordingManager( if (!file.exists()) { onStateUpdate( AudioRecordingStepState.AudioRecording.Playback( - filePath = filePath, + audioPath = AudioPath.FilePath(filePath), isPlaying = false, isPrepared = false, hasError = true, @@ -100,7 +100,7 @@ internal class AndroidAudioRecordingManager( setOnPreparedListener { onStateUpdate( AudioRecordingStepState.AudioRecording.Playback( - filePath = filePath, + audioPath = AudioPath.FilePath(filePath), isPlaying = false, isPrepared = true, hasError = false, diff --git a/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt b/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt index f0e6c7308b..7ca634c95f 100644 --- a/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt +++ b/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt @@ -59,6 +59,7 @@ fun EntryProviderScope.claimChatEntries( ) { entry { key -> ClaimChatDestination( + resumableClaimId = key.resumableClaimId, isDevelopmentFlow = key.isDevelopmentFlow, shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale, openAppSettings = openAppSettings, diff --git a/app/feature/feature-claim-chat/src/commonMain/graphql/FragmentClaimIntent.graphql b/app/feature/feature-claim-chat/src/commonMain/graphql/FragmentClaimIntent.graphql index 14e8d0d94e..bc37b4b02e 100644 --- a/app/feature/feature-claim-chat/src/commonMain/graphql/FragmentClaimIntent.graphql +++ b/app/feature/feature-claim-chat/src/commonMain/graphql/FragmentClaimIntent.graphql @@ -14,6 +14,16 @@ fragment ClaimIntentFragment on ClaimIntent { id submittedAt } + createdAt + previousSteps { + id + text + hint + content { + ...ClaimIntentStepContentFragment + } + isRegrettable + } } fragment ClaimIntentStepContentFragment on ClaimIntentStepContent { @@ -44,6 +54,7 @@ fragment FormFragment on ClaimIntentStepContentForm { value } defaultValues + currentValues minValue maxValue searchData { @@ -63,6 +74,7 @@ fragment ContentSelectFragment on ClaimIntentStepContentSelect { isSkippable style defaultSelectedId + currentSelectedId } fragment TaskFragment on ClaimIntentStepContentTask { @@ -75,11 +87,18 @@ fragment AudioRecordingFragment on ClaimIntentStepContentAudioRecording { isSkippable freeTextMinLength freeTextMaxLength + currentAudioUrl + currentFreeText } fragment FileUploadFragment on ClaimIntentStepContentFileUpload { uploadUri isSkippable + currentFiles { + url + contentType + fileName + } } fragment SummaryFragment on ClaimIntentStepContentSummary { diff --git a/app/feature/feature-claim-chat/src/commonMain/graphql/ResumeClaimQuery.graphql b/app/feature/feature-claim-chat/src/commonMain/graphql/ResumeClaimQuery.graphql new file mode 100644 index 0000000000..21231fdcd1 --- /dev/null +++ b/app/feature/feature-claim-chat/src/commonMain/graphql/ResumeClaimQuery.graphql @@ -0,0 +1,7 @@ +query ResumeClaim { + currentMember { + resumableClaimIntent { + ...ClaimIntentFragment + } + } +} diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt index 97e4b68f97..fb7d9210a6 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt @@ -34,6 +34,7 @@ import com.hedvig.feature.claim.chat.data.FormSubmissionData.FieldToSubmit import com.hedvig.feature.claim.chat.data.FreeTextErrorType.TooShort import com.hedvig.feature.claim.chat.data.GetClaimIntentUseCase import com.hedvig.feature.claim.chat.data.RegretStepUseCase +import com.hedvig.feature.claim.chat.data.ResumeClaimUseCase import com.hedvig.feature.claim.chat.data.SkipStepUseCase import com.hedvig.feature.claim.chat.data.StartClaimIntentUseCase import com.hedvig.feature.claim.chat.data.StepContent @@ -164,6 +165,7 @@ internal sealed interface ClaimChatUiState { @HedvigViewModel(ActivityRetainedScope::class) internal class ClaimChatViewModel( @Assisted developmentFlow: Boolean, + @Assisted resumableClaimId: String?, startClaimIntentUseCase: StartClaimIntentUseCase, getClaimIntentUseCase: GetClaimIntentUseCase, submitTaskUseCase: SubmitTaskUseCase, @@ -177,6 +179,7 @@ internal class ClaimChatViewModel( regretStepUseCase: RegretStepUseCase, formFieldSearchUseCase: FormFieldSearchUseCase, fileService: FileService, + resumeClaimUseCase: ResumeClaimUseCase ) : MoleculeViewModel( ClaimChatUiState.Initializing, ClaimChatPresenter( @@ -194,6 +197,8 @@ internal class ClaimChatViewModel( fileService, regretStepUseCase, formFieldSearchUseCase, + resumableClaimId, + resumeClaimUseCase ), ) { override fun onCleared() { @@ -217,6 +222,8 @@ internal class ClaimChatPresenter( private val fileService: FileService, private val regretStepUseCase: RegretStepUseCase, private val formFieldSearchUseCase: FormFieldSearchUseCase, + private val resumableClaimId: String?, + private val resumeClaimUseCase: ResumeClaimUseCase ) : MoleculePresenter { @Composable override fun MoleculePresenterScope.present(lastState: ClaimChatUiState): ClaimChatUiState { @@ -254,34 +261,70 @@ internal class ClaimChatPresenter( var searchQuery by remember { mutableStateOf(null) } - if (initializing) { + if (initializing) { //TODO LaunchedEffect(Unit) { - startClaimIntentUseCase - .invoke(developmentFlow) - .fold( - ifLeft = { - initializing = false - failedToStart = true - }, - ifRight = { claimIntent -> - Snapshot.withMutableSnapshot { + val isResumingClaim = resumableClaimId!=null + if (isResumingClaim) { + resumeClaimUseCase + .invoke() + .fold( + ifLeft = { initializing = false - failedToStart = false - claimIntentId = claimIntent.id - steps.clear() - progress = claimIntent.progress - when (val next = claimIntent.next) { - is ClaimIntent.Next.Outcome -> { - outcome = next.claimIntentOutcome + failedToStart = true + }, + ifRight = { claimIntent -> + if (claimIntent==null) { + initializing = false + failedToStart = true + } else { + Snapshot.withMutableSnapshot { + initializing = false + failedToStart = false + claimIntentId = claimIntent.id + steps.clear() + steps.addAll(claimIntent.previousSteps) + progress = claimIntent.progress + when (val next = claimIntent.next) { + is ClaimIntent.Next.Outcome -> { + outcome = next.claimIntentOutcome + } + + is ClaimIntent.Next.Step -> { + steps.add(next.claimIntentStep) + } + } } + } + }, + ) + } else { + startClaimIntentUseCase + .invoke(developmentFlow) + .fold( + ifLeft = { + initializing = false + failedToStart = true + }, + ifRight = { claimIntent -> + Snapshot.withMutableSnapshot { + initializing = false + failedToStart = false + claimIntentId = claimIntent.id + steps.clear() + progress = claimIntent.progress + when (val next = claimIntent.next) { + is ClaimIntent.Next.Outcome -> { + outcome = next.claimIntentOutcome + } - is ClaimIntent.Next.Step -> { - steps.add(next.claimIntentStep) + is ClaimIntent.Next.Step -> { + steps.add(next.claimIntentStep) + } } } - } - }, - ) + }, + ) + } } } diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt index 6df1fd1eed..d7a6263661 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt @@ -15,6 +15,7 @@ internal data class ClaimIntent( val id: ClaimIntentId, val next: Next, val progress: Float?, + val previousSteps: List ) { sealed interface Next { val step: Step? @@ -62,7 +63,10 @@ internal sealed interface StepContent { val uploadUri: String, override val isSkippable: Boolean, val localFiles: List, - ) : StepContent + val remoteFiles: List? + ) : StepContent { + data class RemoteFile(val url: String, val contentType: String, val fileName: String) + } data class Task( val descriptions: List, @@ -83,6 +87,7 @@ internal sealed interface StepContent { val suffix: String?, val title: String, val defaultValues: List, + val currentValues: List, val maxValue: String?, val minValue: String?, val type: FieldType?, @@ -198,7 +203,7 @@ sealed interface AudioRecordingStepState { ) : AudioRecording data class Playback( - val filePath: String, + val audioPath: AudioPath, val isPlaying: Boolean, val isPrepared: Boolean, val hasError: Boolean, @@ -206,6 +211,11 @@ sealed interface AudioRecordingStepState { } } +sealed interface AudioPath { + data class FilePath(val filePath: String): AudioPath + data class RemoteUrl(val remoteUrl: String): AudioPath +} + sealed interface FreeTextErrorType { data class TooShort(val minLength: Int) : FreeTextErrorType } diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt index 9848835497..696435dbaa 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt @@ -56,6 +56,9 @@ internal fun ClaimIntentFragment.toClaimIntent(locale: CommonLocale): ClaimInten else -> error("ClaimIntentFragment contained null currentStep and null outcome") }, progress = progress?.toFloat(), + previousSteps = previousSteps.map { + it.toClaimIntentStep(locale) + } ) } @@ -70,6 +73,17 @@ private fun ClaimIntentFragment.CurrentStep.toClaimIntentStep(locale: CommonLoca ) } +context(raise: Raise) +private fun ClaimIntentFragment.PreviousStep.toClaimIntentStep(locale: CommonLocale): ClaimIntentStep { + return ClaimIntentStep( + id = StepId(id), + text = text, + stepContent = this.content.toStepContent(locale), + isRegrettable = this.isRegrettable, + hint = hint, + ) +} + context(raise: Raise) private fun ClaimIntentStepContentFragment.toStepContent(locale: CommonLocale): StepContent { return when (this) { @@ -83,7 +97,7 @@ private fun ClaimIntentStepContentFragment.toStepContent(locale: CommonLocale): is ContentSelectFragment -> { StepContent.ContentSelect( options = options.toOptions(), - selectedOptionId = defaultSelectedId, + selectedOptionId = currentSelectedId ?: defaultSelectedId, isSkippable = isSkippable, style = when (style) { ClaimIntentStepContentSelectStyle.PILL -> StepContent.ContentSelectStyle.PILL @@ -102,10 +116,21 @@ private fun ClaimIntentStepContentFragment.toStepContent(locale: CommonLocale): } is AudioRecordingFragment -> { + val audioIrl = this.currentAudioUrl + val freeText = this.currentFreeText + val recordingState = if(audioIrl!=null) AudioRecordingStepState.AudioRecording.Playback( + audioPath = AudioPath.RemoteUrl(audioIrl), + isPlaying = false, + isPrepared = true, //TODO: check + hasError = false + ) + //else if (freeText!=null) AudioRecordingStepState.FreeTextDescription() //TODO: fix freeText - move it to + // FreeTextDescription instead of hanging in UiState + else AudioRecordingStepState.AudioRecording.NotRecording StepContent.AudioRecording( uploadUri = uploadUri, isSkippable = isSkippable, - recordingState = AudioRecordingStepState.AudioRecording.NotRecording, + recordingState = recordingState, freeTextMinLength = freeTextMinLength, freeTextMaxLength = freeTextMaxLength, ) @@ -116,6 +141,13 @@ private fun ClaimIntentStepContentFragment.toStepContent(locale: CommonLocale): uploadUri = uploadUri, isSkippable = isSkippable, localFiles = emptyList(), + remoteFiles = this.currentFiles?.map { + StepContent.FileUpload.RemoteFile( + it.url, + it.contentType, + it.fileName, + ) + } ) } @@ -213,6 +245,7 @@ private fun List.toFields(locale: CommonLocale): List { + return either { + apolloClient + .query( + ResumeClaimQuery(), + ) + .fetchPolicy(FetchPolicy.NetworkOnly) + .safeExecute() + .mapLeft { + logcat { "StartClaimIntentUseCase error: $it" } + ClaimChatErrorMessage.GeneralError + } + .bind() + .currentMember.resumableClaimIntent + ?.toClaimIntent(languageService.getLocale()) + } + } +} diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt index b998d9d84f..f45c426c66 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt @@ -136,10 +136,11 @@ internal fun ClaimChatDestination( isDevelopmentFlow: Boolean, navigateUp: () -> Unit, openPlayStore: () -> Unit, + resumableClaimId: String? ) { val claimChatViewModel = assistedMetroViewModel { - create(isDevelopmentFlow) + create(isDevelopmentFlow, resumableClaimId) } Box(Modifier.fillMaxSize(), propagateMinConstraints = true) { BlurredGradientBackground() diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/UploadFilesStep.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/UploadFilesStep.kt index d1e41861dc..bcd8df47c2 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/UploadFilesStep.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/UploadFilesStep.kt @@ -361,6 +361,7 @@ private fun PreviewUploadFilesStep( id = "1", ), ).takeIf { hasFiles }.orEmpty(), + remoteFiles = null ), appPackageId = "", isCurrentStep = true, diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecordingStepSections.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecordingStepSections.kt index 4a063a4a89..1f2fdcfe9e 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecordingStepSections.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecordingStepSections.kt @@ -98,8 +98,10 @@ import com.hedvig.audio.player.data.AudioPlayer import com.hedvig.audio.player.data.AudioPlayerState import com.hedvig.audio.player.data.PlayableAudioSource import com.hedvig.audio.player.data.ProgressPercentage +import com.hedvig.audio.player.data.SignedAudioUrl import com.hedvig.feature.claim.chat.ClaimChatEvent import com.hedvig.feature.claim.chat.FreeTextRestrictions +import com.hedvig.feature.claim.chat.data.AudioPath import com.hedvig.feature.claim.chat.data.AudioRecordingStepState import com.hedvig.feature.claim.chat.data.ClaimIntentStep import com.hedvig.feature.claim.chat.data.FreeTextErrorType @@ -284,9 +286,15 @@ internal fun AudioRecorderBubble( } } else { if (recordingState is AudioRecordingStepState.AudioRecording.Playback) { - val audioPlayer = rememberAudioPlayer( - PlayableAudioSource.LocalFilePath(recordingState.filePath), - ) + val audioPlayer = when (recordingState.audioPath) { + is AudioPath.FilePath -> rememberAudioPlayer( + PlayableAudioSource.LocalFilePath(recordingState.audioPath.filePath)) + is AudioPath.RemoteUrl -> rememberAudioPlayer( + PlayableAudioSource.RemoteUrl( + SignedAudioUrl.fromSignedAudioUrlString(recordingState.audioPath.remoteUrl), + ), + ) + } HedvigAudioPlayer( audioPlayer = audioPlayer, Modifier.padding(start = sentAnswersStartPadding), @@ -355,9 +363,11 @@ private fun AudioRecordingBottomSheet( } val audioPlayer = (audioRecordingState as? AudioRecordingStepState.AudioRecording.Playback)?.let { - rememberAudioPlayer( - PlayableAudioSource.LocalFilePath(it.filePath), - ) + if (it.audioPath is AudioPath.FilePath) { + rememberAudioPlayer( + PlayableAudioSource.LocalFilePath(it.audioPath.filePath), + ) + } else null } LaunchedEffect(bottomSheetState.isVisible) { @@ -1156,19 +1166,19 @@ private class AudioRecordingSheetContentStateProvider : filePath = "/path/to/recording.mp4", ), AudioRecordingStepState.AudioRecording.Playback( - filePath = "/path/to/recording.mp4", + audioPath = AudioPath.FilePath("/path/to/recording.mp4"), isPlaying = false, isPrepared = true, hasError = false, ), AudioRecordingStepState.AudioRecording.Playback( - filePath = "/path/to/recording.mp4", + audioPath = AudioPath.FilePath("/path/to/recording.mp4"), isPlaying = false, isPrepared = false, hasError = false, ), AudioRecordingStepState.AudioRecording.Playback( - filePath = "/path/to/recording.mp4", + audioPath = AudioPath.FilePath("/path/to/recording.mp4"), isPlaying = false, isPrepared = false, hasError = true, From 4664c5bdeec59a56b62cd0c73ae962f7eb9f8435 Mon Sep 17 00:00:00 2001 From: mariiapanasetskaia Date: Mon, 29 Jun 2026 16:17:29 +0200 Subject: [PATCH 3/8] add todo --- .../kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt index d7a6263661..c24e3ad222 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt @@ -63,7 +63,7 @@ internal sealed interface StepContent { val uploadUri: String, override val isSkippable: Boolean, val localFiles: List, - val remoteFiles: List? + val remoteFiles: List? //TODO: reuse!! ) : StepContent { data class RemoteFile(val url: String, val contentType: String, val fileName: String) } From 4ef191e9735bd019fae6c075279cb40bbcab3f0f Mon Sep 17 00:00:00 2001 From: mariiapanasetskaia Date: Mon, 29 Jun 2026 16:41:28 +0200 Subject: [PATCH 4/8] use default values --- .../feature/claim/chat/ClaimChatViewModel.kt | 4 +++- .../feature/claim/chat/data/ClaimIntent.kt | 4 +--- .../feature/claim/chat/data/ClaimIntentExt.kt | 22 ++++++++++--------- .../claim/chat/ui/step/UploadFilesStep.kt | 1 - .../ui/step/audiorecording/AudioRecorder.kt | 12 +++++++++- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt index fb7d9210a6..d6849ce853 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt @@ -282,7 +282,9 @@ internal class ClaimChatPresenter( failedToStart = false claimIntentId = claimIntent.id steps.clear() - steps.addAll(claimIntent.previousSteps) + steps.addAll(claimIntent.previousSteps.filter { + it.stepContent !is StepContent.Task + }) progress = claimIntent.progress when (val next = claimIntent.next) { is ClaimIntent.Next.Outcome -> { diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt index c24e3ad222..498b07856b 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt @@ -62,8 +62,7 @@ internal sealed interface StepContent { data class FileUpload( val uploadUri: String, override val isSkippable: Boolean, - val localFiles: List, - val remoteFiles: List? //TODO: reuse!! + val localFiles: List ) : StepContent { data class RemoteFile(val url: String, val contentType: String, val fileName: String) } @@ -87,7 +86,6 @@ internal sealed interface StepContent { val suffix: String?, val title: String, val defaultValues: List, - val currentValues: List, val maxValue: String?, val minValue: String?, val type: FieldType?, diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt index 696435dbaa..1e925e63cc 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt @@ -4,6 +4,7 @@ import arrow.core.raise.Raise import arrow.core.raise.context.raise import com.hedvig.android.core.common.ErrorMessage import com.hedvig.android.core.locale.CommonLocale +import com.hedvig.android.core.uidata.UiFile import com.hedvig.android.design.system.hedvig.DatePickerUiState import com.hedvig.android.logger.logcat import com.hedvig.android.shared.partners.deflect.DeflectData @@ -140,14 +141,15 @@ private fun ClaimIntentStepContentFragment.toStepContent(locale: CommonLocale): StepContent.FileUpload( uploadUri = uploadUri, isSkippable = isSkippable, - localFiles = emptyList(), - remoteFiles = this.currentFiles?.map { - StepContent.FileUpload.RemoteFile( - it.url, - it.contentType, - it.fileName, - ) - } + localFiles = this.currentFiles?.map { + UiFile( + name = it.fileName, + localPath = null, + url = it.url, + mimeType = it.contentType, + id = it.url, + ) + } ?: emptyList() ) } @@ -244,8 +246,8 @@ private fun List.toFields(locale: CommonLocale): List rememberAudioPlayer( + PlayableAudioSource.LocalFilePath(uiState.audioPath.filePath)) + is AudioPath.RemoteUrl -> rememberAudioPlayer( + PlayableAudioSource.RemoteUrl( + SignedAudioUrl.fromSignedAudioUrlString(uiState.audioPath.remoteUrl), + ), + ) + } if (!isCurrentStep) { HedvigAudioPlayer( audioPlayer = audioPlayer, From 85bc292a9cea19ad2730eba96131e642dee45d17 Mon Sep 17 00:00:00 2001 From: mariiapanasetskaia Date: Mon, 29 Jun 2026 16:58:53 +0200 Subject: [PATCH 5/8] use default values better --- .../com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt | 9 +++++---- .../com/hedvig/feature/claim/chat/ui/step/FormStep.kt | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt index 1e925e63cc..fcc2ab8a7d 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt @@ -241,13 +241,14 @@ private fun List.toOptions(): List) private fun List.toFields(locale: CommonLocale): List { return this.map { field -> + val defaultValues = if(field.currentValues.isNotEmpty()) field.currentValues.toFieldOptions(field.options) + else field.defaultValues.toFieldOptions(field.options) StepContent.Form.Field( id = FieldId(field.id), isRequired = field.isRequired, suffix = field.suffix, title = field.title, - defaultValues = if(field.currentValues.isNotEmpty()) field.currentValues.toFieldOptions(field.options) - else field.defaultValues.toFieldOptions(field.options), + defaultValues = defaultValues, maxValue = field.maxValue, minValue = field.minValue, type = when (field.type) { @@ -295,12 +296,12 @@ private fun List.toFields(locale: CommonLocale): List { DatePickerUiState( locale = locale, - initiallySelectedDate = field.defaultValues.getOrNull(0)?.let { LocalDate.parse(it) }, + initiallySelectedDate = defaultValues.getOrNull(0)?.let { LocalDate.parse(it.text) }, minDate = field.minValue?.let { LocalDate.parse(it) } ?: LocalDate(1900, 1, 1), maxDate = field.maxValue?.let { LocalDate.parse(it) } ?: LocalDate(2100, 1, 1), ) diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/FormStep.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/FormStep.kt index 512c1689f7..b0da4e687f 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/FormStep.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/FormStep.kt @@ -190,7 +190,8 @@ private fun FormContent( FieldType.TEXT -> { TextInputBubble( questionLabel = field.title, - text = field.selectedOptions.getOrNull(0)?.text, + text = field.selectedOptions.getOrNull(0)?.text + ?: field.defaultValues.getOrNull(0)?.text, suffix = field.suffix, onInput = { answer -> onSelectFieldAnswer( From 3c6f5908406980fbcd47094a17f3dad744d580bc Mon Sep 17 00:00:00 2001 From: mariiapanasetskaia Date: Tue, 30 Jun 2026 14:10:32 +0200 Subject: [PATCH 6/8] move freeText to stepContent instead of singleton in ui state --- .../claim/chat/navigation/ClaimChatEntries.kt | 4 +- .../feature/claim/chat/ClaimChatViewModel.kt | 40 +++++++------- .../feature/claim/chat/data/ClaimIntent.kt | 10 ++-- .../feature/claim/chat/data/ClaimIntentExt.kt | 52 +++++++++++-------- .../claim/chat/ui/ClaimChatDestination.kt | 13 +++-- .../claim/chat/ui/ClaimChatUiComponents.kt | 2 +- .../claim/chat/ui/StartClaimPledgeScreen.kt | 14 ++--- .../ui/step/audiorecording/AudioRecorder.kt | 4 +- .../AudioRecordingStepSections.kt | 13 ++--- 9 files changed, 77 insertions(+), 75 deletions(-) diff --git a/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt b/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt index 7ca634c95f..efa88f89da 100644 --- a/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt +++ b/app/feature/feature-claim-chat/src/androidMain/kotlin/com/hedvig/feature/claim/chat/navigation/ClaimChatEntries.kt @@ -38,7 +38,7 @@ internal data class ClaimOutcomeNewClaimKey( internal data object UpdateAppKey : HedvigNavKey @Serializable -internal data object StartClaimPledgeKey: HedvigNavKey +internal data object StartClaimPledgeKey : HedvigNavKey fun EntryProviderScope.claimChatEntries( backstack: Backstack, @@ -112,7 +112,7 @@ fun EntryProviderScope.claimChatEntries( ClaimChatKey(), inclusive = true, ) - } + }, ) } } diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt index d6849ce853..9740ad56ea 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ClaimChatViewModel.kt @@ -148,7 +148,6 @@ internal sealed interface ClaimChatUiState { val claimIntentId: ClaimIntentId, val steps: List, val currentStep: ClaimIntentStep?, - val freeText: String?, val outcome: ClaimIntentOutcome?, val errorSubmittingStep: ClaimChatErrorMessage?, val currentContinueButtonLoading: Boolean = false, @@ -179,7 +178,7 @@ internal class ClaimChatViewModel( regretStepUseCase: RegretStepUseCase, formFieldSearchUseCase: FormFieldSearchUseCase, fileService: FileService, - resumeClaimUseCase: ResumeClaimUseCase + resumeClaimUseCase: ResumeClaimUseCase, ) : MoleculeViewModel( ClaimChatUiState.Initializing, ClaimChatPresenter( @@ -198,7 +197,7 @@ internal class ClaimChatViewModel( regretStepUseCase, formFieldSearchUseCase, resumableClaimId, - resumeClaimUseCase + resumeClaimUseCase, ), ) { override fun onCleared() { @@ -223,7 +222,7 @@ internal class ClaimChatPresenter( private val regretStepUseCase: RegretStepUseCase, private val formFieldSearchUseCase: FormFieldSearchUseCase, private val resumableClaimId: String?, - private val resumeClaimUseCase: ResumeClaimUseCase + private val resumeClaimUseCase: ResumeClaimUseCase, ) : MoleculePresenter { @Composable override fun MoleculePresenterScope.present(lastState: ClaimChatUiState): ClaimChatUiState { @@ -247,7 +246,6 @@ internal class ClaimChatPresenter( var currentContinueButtonLoading by remember { mutableStateOf(false) } var currentSkipButtonLoading by remember { mutableStateOf(false) } var errorSubmittingStep by remember { mutableStateOf(null) } - var freeText by remember { mutableStateOf(null) } var showConfirmEditDialogForStep by remember { mutableStateOf(null) } var progress by remember { mutableStateOf( @@ -261,9 +259,9 @@ internal class ClaimChatPresenter( var searchQuery by remember { mutableStateOf(null) } - if (initializing) { //TODO + if (initializing) { LaunchedEffect(Unit) { - val isResumingClaim = resumableClaimId!=null + val isResumingClaim = resumableClaimId != null if (isResumingClaim) { resumeClaimUseCase .invoke() @@ -273,7 +271,7 @@ internal class ClaimChatPresenter( failedToStart = true }, ifRight = { claimIntent -> - if (claimIntent==null) { + if (claimIntent == null) { initializing = false failedToStart = true } else { @@ -282,9 +280,11 @@ internal class ClaimChatPresenter( failedToStart = false claimIntentId = claimIntent.id steps.clear() - steps.addAll(claimIntent.previousSteps.filter { - it.stepContent !is StepContent.Task - }) + steps.addAll( + claimIntent.previousSteps.filter { + it.stepContent !is StepContent.Task + }, + ) progress = claimIntent.progress when (val next = claimIntent.next) { is ClaimIntent.Next.Outcome -> { @@ -476,7 +476,10 @@ internal class ClaimChatPresenter( } is ClaimChatEvent.AudioRecording.SubmitTextInput -> { - val freeTextInput = freeText ?: return@CollectEvents + val recordingState = steps.find { it.id == event.id } + ?.stepContent.let { it as? StepContent.AudioRecording } + ?.recordingState as? FreeTextDescription + val freeTextInput = recordingState?.freeText ?: return@CollectEvents currentContinueButtonLoading = true launch { submitAudioRecordingUseCase @@ -524,13 +527,7 @@ internal class ClaimChatPresenter( } is ClaimChatEvent.AudioRecording.SwitchToFreeText -> { - val currentContent = currentStep?.stepContent as? StepContent.AudioRecording - ?: return@CollectEvents - val textTooShort = freeText?.length?.let { - currentContent.freeTextMinLength > it - } ?: true steps.updateStepWithSuccess(event.id) { step, content -> - val canSubmit = !currentContinueButtonLoading && !freeText.isNullOrEmpty() && !textTooShort showFreeTextOverlay = FreeTextRestrictions( content.freeTextMinLength, content.freeTextMaxLength, @@ -539,7 +536,8 @@ internal class ClaimChatPresenter( stepContent = content.copy( recordingState = FreeTextDescription( errorType = null, - canSubmit = canSubmit, + canSubmit = false, + freeText = null, ), ), ) @@ -735,11 +733,11 @@ internal class ClaimChatPresenter( null }, canSubmit = canSubmit, + freeText = event.text, ), ), ) } - freeText = event.text } } @@ -788,7 +786,6 @@ internal class ClaimChatPresenter( val index = steps.indexOf(stepToUpdate) if (index >= 0) { steps.subList(index, steps.size).clear() - if (steps.none { it.stepContent is StepContent.AudioRecording }) freeText = null } currentContinueButtonLoading = false currentSkipButtonLoading = false @@ -995,7 +992,6 @@ internal class ClaimChatPresenter( currentStep = currentStep, outcome = outcome, showFreeTextOverlay = showFreeTextOverlay, - freeText = freeText, errorSubmittingStep = errorSubmittingStep, currentContinueButtonLoading = currentContinueButtonLoading, currentSkipButtonLoading = currentSkipButtonLoading, diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt index 498b07856b..b36c5c229c 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntent.kt @@ -15,7 +15,7 @@ internal data class ClaimIntent( val id: ClaimIntentId, val next: Next, val progress: Float?, - val previousSteps: List + val previousSteps: List, ) { sealed interface Next { val step: Step? @@ -62,7 +62,7 @@ internal sealed interface StepContent { data class FileUpload( val uploadUri: String, override val isSkippable: Boolean, - val localFiles: List + val localFiles: List, ) : StepContent { data class RemoteFile(val url: String, val contentType: String, val fileName: String) } @@ -189,6 +189,7 @@ sealed interface AudioRecordingStepState { val errorType: FreeTextErrorType?, val canSubmit: Boolean, val hasError: Boolean = false, + val freeText: String? = null, ) : AudioRecordingStepState sealed interface AudioRecording : AudioRecordingStepState { @@ -210,8 +211,9 @@ sealed interface AudioRecordingStepState { } sealed interface AudioPath { - data class FilePath(val filePath: String): AudioPath - data class RemoteUrl(val remoteUrl: String): AudioPath + data class FilePath(val filePath: String) : AudioPath + + data class RemoteUrl(val remoteUrl: String) : AudioPath } sealed interface FreeTextErrorType { diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt index fcc2ab8a7d..b9e7a14aa4 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/data/ClaimIntentExt.kt @@ -59,7 +59,7 @@ internal fun ClaimIntentFragment.toClaimIntent(locale: CommonLocale): ClaimInten progress = progress?.toFloat(), previousSteps = previousSteps.map { it.toClaimIntentStep(locale) - } + }, ) } @@ -117,17 +117,24 @@ private fun ClaimIntentStepContentFragment.toStepContent(locale: CommonLocale): } is AudioRecordingFragment -> { - val audioIrl = this.currentAudioUrl + val audioUrl = this.currentAudioUrl val freeText = this.currentFreeText - val recordingState = if(audioIrl!=null) AudioRecordingStepState.AudioRecording.Playback( - audioPath = AudioPath.RemoteUrl(audioIrl), - isPlaying = false, - isPrepared = true, //TODO: check - hasError = false - ) - //else if (freeText!=null) AudioRecordingStepState.FreeTextDescription() //TODO: fix freeText - move it to - // FreeTextDescription instead of hanging in UiState - else AudioRecordingStepState.AudioRecording.NotRecording + val recordingState = if (audioUrl != null) { + AudioRecordingStepState.AudioRecording.Playback( + audioPath = AudioPath.RemoteUrl(audioUrl), + isPlaying = false, + isPrepared = true, // TODO: check + hasError = false, + ) + } else if (freeText != null) { + AudioRecordingStepState.FreeTextDescription( + errorType = null, + canSubmit = true, + freeText = freeText, + ) + } else { + AudioRecordingStepState.AudioRecording.NotRecording + } StepContent.AudioRecording( uploadUri = uploadUri, isSkippable = isSkippable, @@ -142,14 +149,14 @@ private fun ClaimIntentStepContentFragment.toStepContent(locale: CommonLocale): uploadUri = uploadUri, isSkippable = isSkippable, localFiles = this.currentFiles?.map { - UiFile( - name = it.fileName, - localPath = null, - url = it.url, - mimeType = it.contentType, - id = it.url, - ) - } ?: emptyList() + UiFile( + name = it.fileName, + localPath = null, + url = it.url, + mimeType = it.contentType, + id = it.url, + ) + } ?: emptyList(), ) } @@ -241,8 +248,11 @@ private fun List.toOptions(): List) private fun List.toFields(locale: CommonLocale): List { return this.map { field -> - val defaultValues = if(field.currentValues.isNotEmpty()) field.currentValues.toFieldOptions(field.options) - else field.defaultValues.toFieldOptions(field.options) + val defaultValues = if (field.currentValues.isNotEmpty()) { + field.currentValues.toFieldOptions(field.options) + } else { + field.defaultValues.toFieldOptions(field.options) + } StepContent.Form.Field( id = FieldId(field.id), isRequired = field.isRequired, diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt index f45c426c66..a7b7d217e9 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt @@ -88,6 +88,7 @@ import com.hedvig.feature.claim.chat.ClaimChatEvent.AudioRecording.* import com.hedvig.feature.claim.chat.ClaimChatUiState import com.hedvig.feature.claim.chat.ClaimChatViewModel import com.hedvig.feature.claim.chat.ClaimChatViewModelFactory +import com.hedvig.feature.claim.chat.data.AudioRecordingStepState import com.hedvig.feature.claim.chat.data.ClaimChatErrorMessage import com.hedvig.feature.claim.chat.data.ClaimIntentOutcome import com.hedvig.feature.claim.chat.data.ClaimIntentStep @@ -136,7 +137,7 @@ internal fun ClaimChatDestination( isDevelopmentFlow: Boolean, navigateUp: () -> Unit, openPlayStore: () -> Unit, - resumableClaimId: String? + resumableClaimId: String?, ) { val claimChatViewModel = assistedMetroViewModel { @@ -228,9 +229,12 @@ private fun ClaimChatScreen( openAppSettings: () -> Unit, openPlayStore: () -> Unit, ) { + val currentFreeText = (uiState.currentStep?.stepContent as? StepContent.AudioRecording) + ?.recordingState.let { it as? AudioRecordingStepState.FreeTextDescription } + ?.freeText FreeTextOverlay( freeTextMaxLength = uiState.showFreeTextOverlay?.maxLength ?: 2000, - freeTextValue = uiState.freeText, + freeTextValue = currentFreeText, freeTextHint = stringResource(Res.string.CLAIMS_TEXT_INPUT_POPOVER_PLACEHOLDER), freeTextTitle = stringResource(Res.string.CLAIMS_TEXT_INPUT_PLACEHOLDER), freeTextOnCancelClick = { @@ -486,7 +490,6 @@ private fun ClaimChatScrollableContent( StepContentSection( stepItem = item, - freeText = uiState.freeText, isCurrentStep = isCurrentStep, showAnimationSequence = showAnimationSequence, currentContinueButtonLoading = uiState.currentContinueButtonLoading, @@ -544,7 +547,6 @@ private fun ScrollToBottomButton(onClick: () -> Unit, modifier: Modifier = Modif @Composable private fun StepContentSection( stepItem: ClaimIntentStep, - freeText: String?, isCurrentStep: Boolean, showAnimationSequence: Boolean, currentContinueButtonLoading: Boolean, @@ -620,7 +622,6 @@ private fun StepContentSection( ) { StepBottomContent( stepItem = stepItem, - freeText = freeText, isCurrentStep = isCurrentStep, currentContinueButtonLoading = currentContinueButtonLoading, currentSkipButtonLoading = currentSkipButtonLoading, @@ -757,7 +758,6 @@ private fun CommonPaddingWrapper(content: @Composable () -> Unit) { @Composable private fun StepBottomContent( stepItem: ClaimIntentStep, - freeText: String?, isCurrentStep: Boolean, currentContinueButtonLoading: Boolean, currentSkipButtonLoading: Boolean, @@ -808,7 +808,6 @@ private fun StepBottomContent( clock = Clock.System, onShouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale, openAppSettings = openAppSettings, - freeText = freeText, onEvent = onEvent, continueButtonLoading = currentContinueButtonLoading, skipButtonLoading = currentSkipButtonLoading, diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatUiComponents.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatUiComponents.kt index 5f6836c811..446d357903 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatUiComponents.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatUiComponents.kt @@ -43,6 +43,7 @@ private fun PreviewClaimChatComponents() { recordingState = AudioRecordingStepState.FreeTextDescription( errorType = null, canSubmit = true, + freeText = "some not really long free text", ), clock = Clock.System, onShouldShowRequestPermissionRationale = { @@ -60,7 +61,6 @@ private fun PreviewClaimChatComponents() { onLaunchFullScreenEditText = {}, canSkip = true, onSkip = {}, - freeText = "some not really long free text", continueButtonLoading = false, skipButtonLoading = false, ) diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/StartClaimPledgeScreen.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/StartClaimPledgeScreen.kt index 543d1c9100..e0a9bc96f8 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/StartClaimPledgeScreen.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/StartClaimPledgeScreen.kt @@ -25,10 +25,7 @@ import hedvig.resources.Res import org.jetbrains.compose.resources.stringResource @Composable -internal fun StartClaimPledgeDestination( - navigateUp: () -> Unit, - navigateToClaimChat: () -> Unit -) { +internal fun StartClaimPledgeDestination(navigateUp: () -> Unit, navigateToClaimChat: () -> Unit) { Surface( color = HedvigTheme.colorScheme.backgroundPrimary, ) { @@ -47,21 +44,18 @@ internal fun StartClaimPledgeDestination( navigateToClaimChat = navigateToClaimChat, modifier = Modifier .weight(1f) - .padding(horizontal = 16.dp) + .padding(horizontal = 16.dp), ) } } } - @HedvigShortMultiScreenPreview @Composable -private fun PreviewStartClaimPledgeDestination( -) { +private fun PreviewStartClaimPledgeDestination() { HedvigTheme { Surface(color = HedvigTheme.colorScheme.backgroundPrimary) { - StartClaimPledgeDestination({},{} - ) + StartClaimPledgeDestination({}, {}) } } } diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecorder.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecorder.kt index d1301639fe..8209440bb3 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecorder.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecorder.kt @@ -255,8 +255,8 @@ private fun Playback( HedvigCircularProgressIndicator() } else { val audioPlayer = when (uiState.audioPath) { - is AudioPath.FilePath -> rememberAudioPlayer( - PlayableAudioSource.LocalFilePath(uiState.audioPath.filePath)) + is AudioPath.FilePath -> rememberAudioPlayer(PlayableAudioSource.LocalFilePath(uiState.audioPath.filePath)) + is AudioPath.RemoteUrl -> rememberAudioPlayer( PlayableAudioSource.RemoteUrl( SignedAudioUrl.fromSignedAudioUrlString(uiState.audioPath.remoteUrl), diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecordingStepSections.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecordingStepSections.kt index 1f2fdcfe9e..34f584d9ea 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecordingStepSections.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/step/audiorecording/AudioRecordingStepSections.kt @@ -142,7 +142,6 @@ import org.jetbrains.compose.resources.stringResource @Composable internal fun AudioRecordingStep( item: ClaimIntentStep, - freeText: String?, stepContent: StepContent.AudioRecording, onShowFreeText: () -> Unit, onSwitchToAudioRecording: () -> Unit, @@ -187,7 +186,6 @@ internal fun AudioRecordingStep( canSkip = stepContent.isSkippable, onSkip = onSkip, isCurrentStep = isCurrentStep, - freeText = freeText, continueButtonLoading = continueButtonLoading, skipButtonLoading = skipButtonLoading, ) @@ -203,7 +201,6 @@ internal fun AudioRecordingStep( @Composable internal fun AudioRecorderBubble( recordingState: AudioRecordingStepState, - freeText: String?, clock: Clock, onShouldShowRequestPermissionRationale: (String) -> Boolean, startRecording: () -> Unit, @@ -240,7 +237,7 @@ internal fun AudioRecorderBubble( submitFreeText = submitFreeText, showAudioRecording = onSwitchToAudioRecording, onLaunchFullScreenEditText = onLaunchFullScreenEditText, - freeText = freeText, + freeText = recordingState.freeText, hasError = recordingState.hasError, errorType = recordingState.errorType, isCurrentStep = isCurrentStep, @@ -288,7 +285,9 @@ internal fun AudioRecorderBubble( if (recordingState is AudioRecordingStepState.AudioRecording.Playback) { val audioPlayer = when (recordingState.audioPath) { is AudioPath.FilePath -> rememberAudioPlayer( - PlayableAudioSource.LocalFilePath(recordingState.audioPath.filePath)) + PlayableAudioSource.LocalFilePath(recordingState.audioPath.filePath), + ) + is AudioPath.RemoteUrl -> rememberAudioPlayer( PlayableAudioSource.RemoteUrl( SignedAudioUrl.fromSignedAudioUrlString(recordingState.audioPath.remoteUrl), @@ -367,7 +366,9 @@ private fun AudioRecordingBottomSheet( rememberAudioPlayer( PlayableAudioSource.LocalFilePath(it.audioPath.filePath), ) - } else null + } else { + null + } } LaunchedEffect(bottomSheetState.isVisible) { From bde0ea61a2ea4ffe563d7dde5eb470f070125a67 Mon Sep 17 00:00:00 2001 From: mariiapanasetskaia Date: Wed, 1 Jul 2026 09:43:45 +0200 Subject: [PATCH 7/8] test add missing param --- .../feature/home/home/ui/HomePresenterTest.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/app/feature/feature-home/src/test/kotlin/com/hedvig/android/feature/home/home/ui/HomePresenterTest.kt b/app/feature/feature-home/src/test/kotlin/com/hedvig/android/feature/home/home/ui/HomePresenterTest.kt index 4f7fde4823..c122a4ee87 100644 --- a/app/feature/feature-home/src/test/kotlin/com/hedvig/android/feature/home/home/ui/HomePresenterTest.kt +++ b/app/feature/feature-home/src/test/kotlin/com/hedvig/android/feature/home/home/ui/HomePresenterTest.kt @@ -143,6 +143,7 @@ internal class HomePresenterTest { crossSells = CrossSellSheetData(testCrossSell, listOf()), firstVetSections = listOf(), travelBannerInfo = null, + resumableClaimId = null ).right(), ) assertThat(awaitItem()).isEqualTo( @@ -174,6 +175,8 @@ internal class HomePresenterTest { hasUnseenChatMessages = false, addonBannerInfo = null, isProduction = false, + resumableClaimId = null + ), ) } @@ -207,6 +210,8 @@ internal class HomePresenterTest { firstVetSections = listOf(), showHelpCenter = false, travelBannerInfo = null, + resumableClaimId = null + ).right(), ) assertThat(awaitItem()).isEqualTo( @@ -225,6 +230,8 @@ internal class HomePresenterTest { crossSellsAction = null, addonBannerInfo = null, isProduction = false, + resumableClaimId = null + ), ) } @@ -282,6 +289,8 @@ internal class HomePresenterTest { firstVetSections = listOf(), crossSells = CrossSellSheetData(null, listOf()), travelBannerInfo = null, + resumableClaimId = null + ).right(), ) assertThat(awaitItem()) @@ -317,6 +326,8 @@ internal class HomePresenterTest { firstVetSections = listOf(), showHelpCenter = false, travelBannerInfo = null, + resumableClaimId = null + ).right(), ) assertThat(awaitItem()).isEqualTo( @@ -333,6 +344,8 @@ internal class HomePresenterTest { crossSellsAction = null, addonBannerInfo = null, isProduction = false, + resumableClaimId = null + ), ) } @@ -371,6 +384,8 @@ internal class HomePresenterTest { ), showHelpCenter = false, travelBannerInfo = null, + resumableClaimId = null + ).right(), ) assertThat(awaitItem()).isEqualTo( @@ -387,6 +402,8 @@ internal class HomePresenterTest { crossSellsAction = null, addonBannerInfo = null, isProduction = false, + resumableClaimId = null + ), ) } @@ -424,6 +441,8 @@ internal class HomePresenterTest { firstVetSections = listOf(), showHelpCenter = false, travelBannerInfo = null, + resumableClaimId = null + ).right(), ) assertThat(awaitItem()).isEqualTo( @@ -444,6 +463,7 @@ internal class HomePresenterTest { ), addonBannerInfo = null, isProduction = false, + resumableClaimId = null ), ) } @@ -474,6 +494,8 @@ internal class HomePresenterTest { firstVetSections = listOf(), showHelpCenter = false, travelBannerInfo = null, + resumableClaimId = null + ).right(), ) assertThat(awaitItem()).isEqualTo( @@ -490,6 +512,8 @@ internal class HomePresenterTest { crossSellsAction = null, addonBannerInfo = null, isProduction = false, + resumableClaimId = null + ), ) } @@ -520,6 +544,8 @@ internal class HomePresenterTest { firstVetSections = listOf(), showHelpCenter = false, travelBannerInfo = null, + resumableClaimId = null + ).right(), ) assertThat(awaitItem()).isEqualTo( @@ -536,6 +562,8 @@ internal class HomePresenterTest { crossSellsAction = null, addonBannerInfo = null, isProduction = false, + resumableClaimId = null + ), ) } @@ -562,6 +590,8 @@ internal class HomePresenterTest { firstVetSections = listOf(), crossSells = CrossSellSheetData(null, emptyList()), travelBannerInfo = null, + resumableClaimId = null + ) } From c1172815f6c5dbd6783febe6ce93282f803c4300 Mon Sep 17 00:00:00 2001 From: mariiapanasetskaia Date: Wed, 1 Jul 2026 11:56:49 +0200 Subject: [PATCH 8/8] todo text in dialog --- .../com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt index a7b7d217e9..6c3d602e1a 100644 --- a/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt +++ b/app/feature/feature-claim-chat/src/commonMain/kotlin/com/hedvig/feature/claim/chat/ui/ClaimChatDestination.kt @@ -323,7 +323,8 @@ private fun ClaimChatScreenContent( if (showCloseFlowDialog) { HedvigAlertDialog( title = stringResource(Res.string.GENERAL_ARE_YOU_SURE), - text = stringResource(Res.string.claims_alert_body), + // text = stringResource(Res.string.claims_alert_body), + text = "Your answers will be saved in a draft claim", //TODO onDismissRequest = { showCloseFlowDialog = false },