mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-19 08:09:12 +01:00
Add nicer call quality animation.
This commit is contained in:
@@ -9,7 +9,6 @@ import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.core.CubicBezierEasing
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.expandVertically
|
||||
@@ -23,7 +22,6 @@ import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Arrangement.spacedBy
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@@ -65,6 +63,8 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
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.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.AnimatedFlowRow
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.Dialogs
|
||||
import org.signal.core.ui.compose.IconButtons
|
||||
@@ -221,85 +221,103 @@ private fun WhatIssuesDidYouHave(
|
||||
val isAudioExpanded = CallQualityIssue.AUDIO_ISSUE in selectedQualityIssues
|
||||
val isVideoExpanded = CallQualityIssue.VIDEO_ISSUE in selectedQualityIssues
|
||||
|
||||
FlowRow(
|
||||
AnimatedFlowRow(
|
||||
modifier = Modifier
|
||||
.animateContentSize()
|
||||
.fillMaxWidth()
|
||||
.horizontalGutters(),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
.padding(top = 24.dp)
|
||||
.horizontalGutters()
|
||||
) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.AUDIO_ISSUE,
|
||||
isSelected = isAudioExpanded,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_ISSUE) }
|
||||
)
|
||||
item(CallQualityIssue.AUDIO_ISSUE) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.AUDIO_ISSUE,
|
||||
isSelected = isAudioExpanded,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_ISSUE) }
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedIssueChip(
|
||||
visible = isAudioExpanded,
|
||||
issue = CallQualityIssue.AUDIO_STUTTERING,
|
||||
isSelected = CallQualityIssue.AUDIO_STUTTERING in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_STUTTERING) }
|
||||
)
|
||||
if (isAudioExpanded) {
|
||||
item(CallQualityIssue.AUDIO_STUTTERING) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.AUDIO_STUTTERING,
|
||||
isSelected = CallQualityIssue.AUDIO_STUTTERING in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_STUTTERING) }
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedIssueChip(
|
||||
visible = isAudioExpanded,
|
||||
issue = CallQualityIssue.AUDIO_CUT_OUT,
|
||||
isSelected = CallQualityIssue.AUDIO_CUT_OUT in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_CUT_OUT) }
|
||||
)
|
||||
item(CallQualityIssue.AUDIO_CUT_OUT) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.AUDIO_CUT_OUT,
|
||||
isSelected = CallQualityIssue.AUDIO_CUT_OUT in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_CUT_OUT) }
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedIssueChip(
|
||||
visible = isAudioExpanded,
|
||||
issue = CallQualityIssue.AUDIO_I_HEARD_ECHO,
|
||||
isSelected = CallQualityIssue.AUDIO_I_HEARD_ECHO in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_I_HEARD_ECHO) }
|
||||
)
|
||||
item(CallQualityIssue.AUDIO_I_HEARD_ECHO) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.AUDIO_I_HEARD_ECHO,
|
||||
isSelected = CallQualityIssue.AUDIO_I_HEARD_ECHO in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_I_HEARD_ECHO) }
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedIssueChip(
|
||||
visible = isAudioExpanded,
|
||||
issue = CallQualityIssue.AUDIO_OTHERS_HEARD_ECHO,
|
||||
isSelected = CallQualityIssue.AUDIO_OTHERS_HEARD_ECHO in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_OTHERS_HEARD_ECHO) }
|
||||
)
|
||||
item(CallQualityIssue.AUDIO_OTHERS_HEARD_ECHO) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.AUDIO_OTHERS_HEARD_ECHO,
|
||||
isSelected = CallQualityIssue.AUDIO_OTHERS_HEARD_ECHO in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.AUDIO_OTHERS_HEARD_ECHO) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.VIDEO_ISSUE,
|
||||
isSelected = isVideoExpanded,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.VIDEO_ISSUE) }
|
||||
)
|
||||
item(CallQualityIssue.VIDEO_ISSUE) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.VIDEO_ISSUE,
|
||||
isSelected = isVideoExpanded,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.VIDEO_ISSUE) }
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedIssueChip(
|
||||
visible = isVideoExpanded,
|
||||
issue = CallQualityIssue.VIDEO_POOR_QUALITY,
|
||||
isSelected = CallQualityIssue.VIDEO_POOR_QUALITY in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.VIDEO_POOR_QUALITY) }
|
||||
)
|
||||
if (isVideoExpanded) {
|
||||
item(CallQualityIssue.VIDEO_POOR_QUALITY) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.VIDEO_POOR_QUALITY,
|
||||
isSelected = CallQualityIssue.VIDEO_POOR_QUALITY in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.VIDEO_POOR_QUALITY) }
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedIssueChip(
|
||||
visible = isVideoExpanded,
|
||||
issue = CallQualityIssue.VIDEO_LOW_RESOLUTION,
|
||||
isSelected = CallQualityIssue.VIDEO_LOW_RESOLUTION in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.VIDEO_LOW_RESOLUTION) }
|
||||
)
|
||||
item(CallQualityIssue.VIDEO_LOW_RESOLUTION) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.VIDEO_LOW_RESOLUTION,
|
||||
isSelected = CallQualityIssue.VIDEO_LOW_RESOLUTION in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.VIDEO_LOW_RESOLUTION) }
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedIssueChip(
|
||||
visible = isVideoExpanded,
|
||||
issue = CallQualityIssue.VIDEO_CAMERA_MALFUNCTION,
|
||||
isSelected = CallQualityIssue.VIDEO_CAMERA_MALFUNCTION in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.VIDEO_CAMERA_MALFUNCTION) }
|
||||
)
|
||||
item(CallQualityIssue.VIDEO_CAMERA_MALFUNCTION) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.VIDEO_CAMERA_MALFUNCTION,
|
||||
isSelected = CallQualityIssue.VIDEO_CAMERA_MALFUNCTION in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.VIDEO_CAMERA_MALFUNCTION) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.CALL_DROPPED,
|
||||
isSelected = CallQualityIssue.CALL_DROPPED in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.CALL_DROPPED) }
|
||||
)
|
||||
item(CallQualityIssue.CALL_DROPPED) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.CALL_DROPPED,
|
||||
isSelected = CallQualityIssue.CALL_DROPPED in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.CALL_DROPPED) }
|
||||
)
|
||||
}
|
||||
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.SOMETHING_ELSE,
|
||||
isSelected = CallQualityIssue.SOMETHING_ELSE in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.SOMETHING_ELSE) }
|
||||
)
|
||||
item(CallQualityIssue.SOMETHING_ELSE) {
|
||||
IssueChip(
|
||||
issue = CallQualityIssue.SOMETHING_ELSE,
|
||||
isSelected = CallQualityIssue.SOMETHING_ELSE in selectedQualityIssues,
|
||||
onClick = { onCallQualityIssueClick(CallQualityIssue.SOMETHING_ELSE) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
@@ -404,41 +422,10 @@ private fun IssueChip(
|
||||
label = {
|
||||
Text(text = stringResource(issue.label))
|
||||
},
|
||||
modifier = modifier.padding(horizontal = 4.dp)
|
||||
modifier = modifier.padding(horizontal = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AnimatedIssueChip(
|
||||
visible: Boolean,
|
||||
issue: CallQualityIssue,
|
||||
isSelected: Boolean,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = fadeIn(
|
||||
animationSpec = tween(
|
||||
durationMillis = 300,
|
||||
delayMillis = 300,
|
||||
easing = CubicBezierEasing(0f, 0f, 0.58f, 1f)
|
||||
)
|
||||
),
|
||||
exit = fadeOut(
|
||||
animationSpec = tween(
|
||||
durationMillis = 300,
|
||||
easing = CubicBezierEasing(0f, 0f, 0.58f, 1f)
|
||||
)
|
||||
)
|
||||
) {
|
||||
IssueChip(
|
||||
issue = issue,
|
||||
isSelected = isSelected,
|
||||
onClick = onClick
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun HelpUsImprove(
|
||||
@@ -639,7 +626,7 @@ fun CancelButton(
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewLightDark
|
||||
@AllDevicePreviews
|
||||
@Composable
|
||||
private fun CallQualityScreenPreview() {
|
||||
var state by remember { mutableStateOf(CallQualitySheetState()) }
|
||||
|
||||
Reference in New Issue
Block a user