diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityBottomSheetFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityBottomSheetFragment.kt index 166b61bcc2..dd493dd392 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityBottomSheetFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityBottomSheetFragment.kt @@ -99,5 +99,9 @@ class CallQualityBottomSheetFragment : ComposeBottomSheetDialogFragment() { dismiss() setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to true)) } + + override fun tryAgain() { + viewModel.clearFailedDueToNetworkAvailability() + } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityScreenViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityScreenViewModel.kt index ad7d39c538..ab0ca97e28 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityScreenViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityScreenViewModel.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.update import org.signal.core.util.logging.Log import org.signal.storageservice.protos.calls.quality.SubmitCallQualitySurveyRequest import org.thoughtcrime.securesms.dependencies.AppDependencies +import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint import org.thoughtcrime.securesms.jobs.CallQualitySurveySubmissionJob class CallQualityScreenViewModel( @@ -41,7 +42,17 @@ class CallQualityScreenViewModel( internalState.update { it.copy(isShareDebugLogSelected = shareDebugLog) } } + fun clearFailedDueToNetworkAvailability() { + internalState.update { it.copy(failedDueToNetworkAvailability = false) } + } + fun submit() { + if (!NetworkConstraint.isMet(AppDependencies.application)) { + Log.w(TAG, "User does not have a network connection. Failing immediately with retry dialog.") + internalState.update { it.copy(failedDueToNetworkAvailability = true) } + return + } + if (initialRequest.call_type.isEmpty()) { Log.i(TAG, "Ignoring survey submission for blank call_type.") return diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityScreens.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityScreens.kt index d51a57fcb9..079e16a76c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityScreens.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/quality/CallQualityScreens.kt @@ -66,6 +66,7 @@ import androidx.compose.ui.text.withLink import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import org.signal.core.ui.compose.Buttons +import org.signal.core.ui.compose.Dialogs import org.signal.core.ui.compose.IconButtons import org.signal.core.ui.compose.Previews import org.signal.core.ui.compose.Rows @@ -80,6 +81,19 @@ fun CallQualitySheet( ) { var navEntry: CallQualitySheetNavEntry by remember { mutableStateOf(CallQualitySheetNavEntry.HowWasYourCall) } + if (state.failedDueToNetworkAvailability) { + Dialogs.SimpleAlertDialog( + title = "", + body = stringResource(R.string.CallQualitySheet__your_feedback_failed_to_send), + confirm = stringResource(R.string.CallQualitySheet__try_again), + onConfirm = callback::tryAgain, + dismiss = stringResource(android.R.string.cancel), + onDeny = callback::dismiss + ) + + return + } + Sheet(onDismissRequest = callback::dismiss) { AnimatedContent( targetState = navEntry, @@ -106,7 +120,7 @@ fun CallQualitySheet( navEntry = CallQualitySheetNavEntry.HelpUsImprove }, onHadIssuesClick = { - callback.onUserSatisfiedWithCall(true) + callback.onUserSatisfiedWithCall(false) navEntry = CallQualitySheetNavEntry.WhatIssuesDidYouHave }, onCancelClick = callback::dismiss @@ -115,6 +129,7 @@ fun CallQualitySheet( CallQualitySheetNavEntry.WhatIssuesDidYouHave -> WhatIssuesDidYouHave( selectedQualityIssues = state.selectedQualityIssues, somethingElseDescription = state.somethingElseDescription, + isContinueEnabled = state.canContinueAfterIssueSelection(), onCallQualityIssueSelectionChanged = callback::onCallQualityIssueSelectionChanged, onContinueClick = { navEntry = CallQualitySheetNavEntry.HelpUsImprove @@ -169,6 +184,7 @@ private fun ColumnScope.HowWasYourCall( private fun WhatIssuesDidYouHave( selectedQualityIssues: Set, somethingElseDescription: String, + isContinueEnabled: Boolean, onCallQualityIssueSelectionChanged: (Set) -> Unit, onCancelClick: () -> Unit, onContinueClick: () -> Unit, @@ -352,7 +368,8 @@ private fun WhatIssuesDidYouHave( ) Buttons.LargeTonal( - onClick = onContinueClick + onClick = onContinueClick, + enabled = isContinueEnabled ) { Text(text = stringResource(R.string.CallQualitySheet__continue)) } @@ -665,6 +682,7 @@ private fun WhatIssuesDidYouHavePreview() { WhatIssuesDidYouHave( selectedQualityIssues = userSelection, somethingElseDescription = "", + isContinueEnabled = false, onCallQualityIssueSelectionChanged = { userSelection = it }, @@ -708,8 +726,17 @@ data class CallQualitySheetState( val isUserSatisfiedWithCall: Boolean = false, val selectedQualityIssues: Set = emptySet(), val somethingElseDescription: String = "", - val isShareDebugLogSelected: Boolean = false -) + val isShareDebugLogSelected: Boolean = false, + val failedDueToNetworkAvailability: Boolean = false +) { + fun canContinueAfterIssueSelection(): Boolean { + val isSomethingElseSelected = selectedQualityIssues.contains(CallQualityIssue.SOMETHING_ELSE) + val isSomethingElseFieldComplete = somethingElseDescription.isNotEmpty() + val isSomethingElseValid = isSomethingElseSelected && isSomethingElseFieldComplete || !isSomethingElseSelected + + return selectedQualityIssues.isNotEmpty() && isSomethingElseValid + } +} interface CallQualitySheetCallback { fun dismiss() @@ -719,6 +746,7 @@ interface CallQualitySheetCallback { fun onCallQualityIssueSelectionChanged(selection: Set) fun onShareDebugLogChanged(shareDebugLog: Boolean) fun submit() + fun tryAgain() object Empty : CallQualitySheetCallback { override fun dismiss() = Unit @@ -728,6 +756,7 @@ interface CallQualitySheetCallback { override fun onCallQualityIssueSelectionChanged(selection: Set) = Unit override fun onShareDebugLogChanged(shareDebugLog: Boolean) = Unit override fun submit() = Unit + override fun tryAgain() = Unit } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2fddbf60e..7a65f01d99 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9033,6 +9033,10 @@ I had issues with the call The call was great + + Your feedback failed to send. + + Try again %1$s pinned a message