Call quality icons and config rotation.

This commit is contained in:
Alex Hart
2025-12-03 16:22:57 -04:00
committed by jeffrey-signal
parent c6de4c7650
commit 6594b8532e
11 changed files with 57 additions and 21 deletions

View File

@@ -125,7 +125,7 @@ object CallQuality {
}
private fun isFeatureEnabled(): Boolean {
return (RemoteConfig.callQualitySurvey || SignalStore.internal.callQualitySurveys) && SignalStore.callQuality.isQualitySurveyEnabled
return RemoteConfig.callQualitySurvey && SignalStore.callQuality.isQualitySurveyEnabled
}
private enum class CallType(val code: String) {

View File

@@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
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.jobs.CallQualitySurveySubmissionJob
@@ -17,6 +18,10 @@ class CallQualityScreenViewModel(
val initialRequest: SubmitCallQualitySurveyRequest
) : ViewModel() {
companion object {
private val TAG = Log.tag(CallQualityScreenViewModel::class)
}
private val internalState = MutableStateFlow(CallQualitySheetState())
val state: StateFlow<CallQualitySheetState> = internalState
@@ -37,6 +42,11 @@ class CallQualityScreenViewModel(
}
fun submit() {
if (initialRequest.call_type.isEmpty()) {
Log.i(TAG, "Ignoring survey submission for blank call_type.")
return
}
val stateSnapshot = state.value
val somethingElseDescription: String? = if (stateSnapshot.selectedQualityIssues.contains(CallQualityIssue.SOMETHING_ELSE)) {
stateSnapshot.somethingElseDescription.takeIf { it.isNotEmpty() }

View File

@@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -556,7 +557,9 @@ private fun HadIssuesButton(
text = stringResource(R.string.CallQualitySheet__had_issues),
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.error,
onClick = onClick
onClick = onClick,
contentDescription = stringResource(R.string.CallQualitySheet__had_issues_content_description),
imageVector = ImageVector.vectorResource(R.drawable.symbol_thumbs_down_24)
)
}
@@ -568,7 +571,9 @@ private fun GreatButton(
text = stringResource(R.string.CallQualitySheet__great),
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary,
onClick = onClick
onClick = onClick,
contentDescription = stringResource(R.string.CallQualitySheet__great_content_description),
imageVector = ImageVector.vectorResource(R.drawable.symbol_thumbs_up_24)
)
}
@@ -577,8 +582,9 @@ private fun FeedbackButton(
text: String,
onClick: () -> Unit,
containerColor: Color,
contentColor: Color
// imageVector icon
contentColor: Color,
imageVector: ImageVector,
contentDescription: String
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
@@ -591,7 +597,12 @@ private fun FeedbackButton(
.clip(CircleShape)
.background(color = containerColor)
) {
// TODO - icon with contentcolor tint
Icon(
imageVector = imageVector,
contentDescription = contentDescription,
tint = contentColor,
modifier = Modifier.size(36.dp)
)
}
Text(

View File

@@ -23,6 +23,7 @@ import org.signal.core.util.readToList
import org.signal.core.util.requireLong
import org.signal.core.util.requireString
import org.signal.ringrtc.CallManager
import org.signal.storageservice.protos.calls.quality.SubmitCallQualitySurveyRequest
import org.thoughtcrime.securesms.BuildConfig
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.calls.quality.CallQualityBottomSheetFragment
@@ -59,6 +60,7 @@ import org.thoughtcrime.securesms.payments.DataExportUtil
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.util.BottomSheetUtil
import org.thoughtcrime.securesms.util.ConversationUtil
import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
@@ -580,11 +582,12 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
}
)
switchPref(
title = DSLSettingsText.from("Enable call quality surveys"),
isChecked = state.callQualitySurveys,
clickPref(
title = DSLSettingsText.from("Display call quality survey"),
onClick = {
viewModel.setEnableCallQualitySurveys(!state.callQualitySurveys)
CallQualityBottomSheetFragment
.create(SubmitCallQualitySurveyRequest())
.show(parentFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
}
)

View File

@@ -31,6 +31,5 @@ data class InternalSettingsState(
val hasPendingOneTimeDonation: Boolean,
val hevcEncoding: Boolean,
val newCallingUi: Boolean,
val callQualitySurveys: Boolean,
val forceSplitPane: Boolean
)

View File

@@ -197,7 +197,6 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
hasPendingOneTimeDonation = SignalStore.inAppPayments.getPendingOneTimeDonation() != null,
hevcEncoding = SignalStore.internal.hevcEncoding,
newCallingUi = SignalStore.internal.newCallingUi,
callQualitySurveys = SignalStore.internal.callQualitySurveys,
forceSplitPane = SignalStore.internal.forceSplitPane
)
@@ -214,11 +213,6 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
refresh()
}
fun setEnableCallQualitySurveys(enabled: Boolean) {
SignalStore.internal.callQualitySurveys = enabled
refresh()
}
fun setForceSplitPane(forceSplitPane: Boolean) {
SignalStore.internal.forceSplitPane = forceSplitPane
refresh()

View File

@@ -32,7 +32,6 @@ class InternalValues internal constructor(store: KeyValueStore) : SignalStoreVal
const val WEB_SOCKET_SHADOWING_STATS: String = "internal.web_socket_shadowing_stats"
const val ENCODE_HEVC: String = "internal.hevc_encoding"
const val NEW_CALL_UI: String = "internal.new.call.ui"
const val CALL_QUALITY_SURVEYS: String = "internal.call_quality_surveys"
const val FORCE_SPLIT_PANE_ON_COMPACT_LANDSCAPE: String = "internal.force.split.pane.on.compact.landscape.ui"
const val SHOW_ARCHIVE_STATE_HINT: String = "internal.show_archive_state_hint"
const val INCLUDE_DEBUGLOG_IN_BACKUP: String = "internal.include_debuglog_in_backup"
@@ -171,8 +170,6 @@ class InternalValues internal constructor(store: KeyValueStore) : SignalStoreVal
var newCallingUi: Boolean by booleanValue(NEW_CALL_UI, false).defaultForExternalUsers()
var callQualitySurveys: Boolean by booleanValue(CALL_QUALITY_SURVEYS, false).defaultForExternalUsers()
var lastScrollPosition: Int by integerValue(LAST_SCROLL_POSITION, 0).defaultForExternalUsers()
var useConversationItemV2Media by booleanValue(CONVERSATION_ITEM_V2_MEDIA, false).defaultForExternalUsers()

View File

@@ -1233,7 +1233,7 @@ object RemoteConfig {
@JvmStatic
@get:JvmName("callQualitySurvey")
val callQualitySurvey: Boolean by remoteBoolean(
key = "android.callQualitySurvey",
key = "android.callQualitySurvey.2",
defaultValue = false,
hotSwappable = true
)