From ff41cb12575981e45868936b76ce81b626413796 Mon Sep 17 00:00:00 2001 From: Hugo Linder Date: Mon, 27 Apr 2026 14:41:15 +0200 Subject: [PATCH 1/2] eng: handle nullable targetFileUploadUri (RND-1677) Backend is collapsing PartnerClaim into Claim, which loosens targetFileUploadUri from String! to String. Partner claims have no upload URI; the existing isUploadingFilesEnabled gate already hides the add-files button for them, but the type chain needs to permit null. - Schema: targetFileUploadUri: String! -> String (hand-edited; re-run downloadOctopusApolloSchemaFromIntrospection after the backend change deploys to staging to catch any unrelated drift). - ClaimDetailUiState.Content.uploadUri: String -> String? - Picker callbacks at ClaimDetailsDestination guard with ?.let so the (List, String) -> Unit callback signature stays non-null. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../com/hedvig/android/apollo/octopus/schema.graphqls | 2 +- .../feature/claim/details/ui/ClaimDetailsDestination.kt | 6 +++--- .../feature/claim/details/ui/ClaimDetailsViewModel.kt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/apollo/apollo-octopus-public/src/commonMain/graphql/com/hedvig/android/apollo/octopus/schema.graphqls b/app/apollo/apollo-octopus-public/src/commonMain/graphql/com/hedvig/android/apollo/octopus/schema.graphqls index 288983627b..871e3a81a9 100644 --- a/app/apollo/apollo-octopus-public/src/commonMain/graphql/com/hedvig/android/apollo/octopus/schema.graphqls +++ b/app/apollo/apollo-octopus-public/src/commonMain/graphql/com/hedvig/android/apollo/octopus/schema.graphqls @@ -844,7 +844,7 @@ type Claim { This target accepts multipart file uploads, and will automatically attach the uploaded files to the given claim. Therefore, the same claim can be refreshed in GraphQL and it should be visible in the `Claim.files` field. """ - targetFileUploadUri: String! + targetFileUploadUri: String """ A list of all the member-visible, uploaded files for this claim. """ diff --git a/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsDestination.kt b/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsDestination.kt index 7ab7f80e6a..07be7c91ec 100644 --- a/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsDestination.kt +++ b/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsDestination.kt @@ -194,19 +194,19 @@ private fun ClaimDetailScreen( is ClaimDetailUiState.Content -> { val photoCaptureState = rememberPhotoCaptureState(appPackageId = appPackageId) { uri -> logcat { "ChatFileState sending photoCaptureState uri:$uri" } - onFilesToUploadSelected(listOf(uri.toAndroidUri()), uiState.uploadUri) + uiState.uploadUri?.let { onFilesToUploadSelected(listOf(uri.toAndroidUri()), it) } } val photoPicker = rememberLauncherForActivityResult( contract = ActivityResultContracts.PickMultipleVisualMedia(), ) { resultingUriList: List -> logcat { "ChatFileState sending photoPicker uris:$resultingUriList" } - onFilesToUploadSelected(resultingUriList, uiState.uploadUri) + uiState.uploadUri?.let { onFilesToUploadSelected(resultingUriList, it) } } val filePicker = rememberLauncherForActivityResult( contract = ActivityResultContracts.GetMultipleContents(), ) { resultingUriList: List -> logcat { "ChatFileState sending filePicker uris:$resultingUriList" } - onFilesToUploadSelected(resultingUriList, uiState.uploadUri) + uiState.uploadUri?.let { onFilesToUploadSelected(resultingUriList, it) } } ClaimDetailContentScreen( uiState = uiState, diff --git a/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsViewModel.kt b/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsViewModel.kt index 4276b6be30..43af3f6755 100644 --- a/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsViewModel.kt +++ b/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsViewModel.kt @@ -177,7 +177,7 @@ internal sealed interface ClaimDetailUiState { val claimStatusCardUiState: ClaimStatusCardUiState, val claimStatus: ClaimStatus, val claimOutcome: ClaimOutcome, - val uploadUri: String, + val uploadUri: String?, val isUploadingFile: Boolean, val uploadError: String?, val claimType: String?, From fe36d55571146b17adf721c47f317d039a6ab295 Mon Sep 17 00:00:00 2001 From: Hugo Linder Date: Mon, 27 Apr 2026 14:44:48 +0200 Subject: [PATCH 2/2] chore: hide empty 'Uploaded files' section header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'Uploaded files' title rendered unconditionally, even when there was no submitted content, no files, and uploads were disabled — leaving a dangling header with nothing under it. Triggered by partner claims (no audio, no free text, empty files, isUploadingFilesEnabled = false) but also affects pre-existing regular closed-non-pet claims with no submitted content. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../details/ui/ClaimDetailsDestination.kt | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsDestination.kt b/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsDestination.kt index 07be7c91ec..26f5290573 100644 --- a/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsDestination.kt +++ b/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/ClaimDetailsDestination.kt @@ -504,29 +504,34 @@ private fun BeforeGridContent( .fillMaxWidth() .padding(horizontal = 2.dp), ) - Spacer(Modifier.height(24.dp)) - HedvigText( - stringResource(Res.string.claim_status_detail_uploaded_files_info_title), - Modifier.padding(horizontal = 2.dp), - ) - Spacer(Modifier.height(8.dp)) - when (uiState.submittedContent) { - is ClaimDetailUiState.Content.SubmittedContent.Audio -> { - ClaimDetailHedvigAudioPlayerItem(uiState.submittedContent.signedAudioURL) - } + val hasUploadedFilesSection = uiState.submittedContent != null || + uiState.files.isNotEmpty() || + uiState.isUploadingFilesEnabled + if (hasUploadedFilesSection) { + Spacer(Modifier.height(24.dp)) + HedvigText( + stringResource(Res.string.claim_status_detail_uploaded_files_info_title), + Modifier.padding(horizontal = 2.dp), + ) + Spacer(Modifier.height(8.dp)) + when (uiState.submittedContent) { + is ClaimDetailUiState.Content.SubmittedContent.Audio -> { + ClaimDetailHedvigAudioPlayerItem(uiState.submittedContent.signedAudioURL) + } - is ClaimDetailUiState.Content.SubmittedContent.FreeText -> { - HedvigCard(Modifier.fillMaxWidth()) { - HedvigText( - uiState.submittedContent.text, - Modifier.padding(16.dp), - ) + is ClaimDetailUiState.Content.SubmittedContent.FreeText -> { + HedvigCard(Modifier.fillMaxWidth()) { + HedvigText( + uiState.submittedContent.text, + Modifier.padding(16.dp), + ) + } } - } - else -> {} + null -> {} + } + Spacer(Modifier.height(8.dp)) } - Spacer(Modifier.height(8.dp)) } @Composable