Added progress indicator for group editing (#875)

* Added progress indicator for group editing

* Max size on AndroidView and remove background, add semantics

* More update

* Reuse LoadingDialog

* Comment
pull/1709/head
SessionHero01 4 months ago committed by GitHub
parent 6b7afb8969
commit 46653d9229
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -264,6 +264,9 @@ class GroupManagerV2Impl @Inject constructor(
subAccountTokens = subAccountTokens subAccountTokens = subAccountTokens
) )
// Before we send the invitation, we need to make sure the configs are pushed
configFactory.waitUntilGroupConfigsPushed(group)
// Call the API // Call the API
try { try {
val swarmNode = SnodeAPI.getSingleTargetSnode(group.hexString).await() val swarmNode = SnodeAPI.getSingleTargetSnode(group.hexString).await()

@ -28,6 +28,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
@ -53,9 +54,10 @@ import org.thoughtcrime.securesms.groups.getLabel
import org.thoughtcrime.securesms.ui.AlertDialog import org.thoughtcrime.securesms.ui.AlertDialog
import org.thoughtcrime.securesms.ui.DialogButtonModel import org.thoughtcrime.securesms.ui.DialogButtonModel
import org.thoughtcrime.securesms.ui.GetString import org.thoughtcrime.securesms.ui.GetString
import org.thoughtcrime.securesms.ui.components.BackAppBar import org.thoughtcrime.securesms.ui.LoadingDialog
import org.thoughtcrime.securesms.ui.components.ActionSheet import org.thoughtcrime.securesms.ui.components.ActionSheet
import org.thoughtcrime.securesms.ui.components.ActionSheetItemData import org.thoughtcrime.securesms.ui.components.ActionSheetItemData
import org.thoughtcrime.securesms.ui.components.BackAppBar
import org.thoughtcrime.securesms.ui.components.PrimaryOutlineButton import org.thoughtcrime.securesms.ui.components.PrimaryOutlineButton
import org.thoughtcrime.securesms.ui.components.SessionOutlinedTextField import org.thoughtcrime.securesms.ui.components.SessionOutlinedTextField
import org.thoughtcrime.securesms.ui.components.annotatedStringResource import org.thoughtcrime.securesms.ui.components.annotatedStringResource
@ -99,6 +101,7 @@ fun EditGroupScreen(
onMemberClicked = viewModel::onMemberClicked, onMemberClicked = viewModel::onMemberClicked,
hideActionSheet = viewModel::hideActionBottomSheet, hideActionSheet = viewModel::hideActionBottomSheet,
clickedMember = viewModel.clickedMember.collectAsState().value, clickedMember = viewModel.clickedMember.collectAsState().value,
showLoading = viewModel.inProgress.collectAsState().value,
) )
} }
@ -119,7 +122,7 @@ fun EditGroupScreen(
@Serializable @Serializable
private object RouteEditGroup private object RouteEditGroup
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable @Composable
fun EditGroup( fun EditGroup(
onBack: () -> Unit, onBack: () -> Unit,
@ -141,6 +144,7 @@ fun EditGroup(
members: List<GroupMemberState>, members: List<GroupMemberState>,
showAddMembers: Boolean, showAddMembers: Boolean,
showingError: String?, showingError: String?,
showLoading: Boolean,
onErrorDismissed: () -> Unit, onErrorDismissed: () -> Unit,
) { ) {
val (showingConfirmRemovingMember, setShowingConfirmRemovingMember) = remember { val (showingConfirmRemovingMember, setShowingConfirmRemovingMember) = remember {
@ -157,115 +161,120 @@ fun EditGroup(
) )
} }
) { paddingValues -> ) { paddingValues ->
Column(modifier = Modifier.padding(paddingValues)) { Box {
Column(modifier = Modifier.padding(paddingValues)) {
GroupMinimumVersionBanner() GroupMinimumVersionBanner()
// Group name title // Group name title
Crossfade(editingName != null, label = "Editable group name") { showNameEditing -> Crossfade(editingName != null, label = "Editable group name") { showNameEditing ->
if (showNameEditing) { if (showNameEditing) {
GroupNameContainer { GroupNameContainer {
IconButton( IconButton(
modifier = Modifier.size(LocalDimensions.current.spacing), modifier = Modifier.size(LocalDimensions.current.spacing),
onClick = onEditNameCancelClicked) { onClick = onEditNameCancelClicked
Icon( ) {
painter = painterResource(R.drawable.ic_x), Icon(
contentDescription = stringResource(R.string.AccessibilityId_cancel), painter = painterResource(R.drawable.ic_x),
tint = LocalColors.current.text, contentDescription = stringResource(R.string.AccessibilityId_cancel),
) tint = LocalColors.current.text,
} )
}
SessionOutlinedTextField( SessionOutlinedTextField(
modifier = Modifier.widthIn( modifier = Modifier
min = LocalDimensions.current.mediumSpacing, .widthIn(
max = maxNameWidth min = LocalDimensions.current.mediumSpacing,
) max = maxNameWidth
.qaTag(stringResource(R.string.AccessibilityId_groupName)), )
text = editingName.orEmpty(), .qaTag(stringResource(R.string.AccessibilityId_groupName)),
onChange = onEditingNameValueChanged, text = editingName.orEmpty(),
textStyle = LocalType.current.h8, onChange = onEditingNameValueChanged,
singleLine = true, textStyle = LocalType.current.h8,
innerPadding = PaddingValues( singleLine = true,
horizontal = LocalDimensions.current.spacing, innerPadding = PaddingValues(
vertical = LocalDimensions.current.smallSpacing horizontal = LocalDimensions.current.spacing,
vertical = LocalDimensions.current.smallSpacing
)
) )
)
IconButton( IconButton(
modifier = Modifier.size(LocalDimensions.current.spacing), modifier = Modifier.size(LocalDimensions.current.spacing),
onClick = onEditNameConfirmed) { onClick = onEditNameConfirmed
Icon( ) {
painter = painterResource(R.drawable.check), Icon(
contentDescription = stringResource(R.string.AccessibilityId_confirm), painter = painterResource(R.drawable.check),
tint = LocalColors.current.text, contentDescription = stringResource(R.string.AccessibilityId_confirm),
) tint = LocalColors.current.text,
)
}
} }
}
} else { } else {
GroupNameContainer { GroupNameContainer {
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
Text( Text(
text = groupName, text = groupName,
style = LocalType.current.h4, style = LocalType.current.h4,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.widthIn(max = maxNameWidth) modifier = Modifier
.padding(vertical = LocalDimensions.current.smallSpacing), .widthIn(max = maxNameWidth)
) .padding(vertical = LocalDimensions.current.smallSpacing),
)
Box(modifier = Modifier.weight(1f)) { Box(modifier = Modifier.weight(1f)) {
if (canEditName) { if (canEditName) {
IconButton( IconButton(
modifier = Modifier.qaTag(stringResource(R.string.AccessibilityId_groupName)), modifier = Modifier.qaTag(stringResource(R.string.AccessibilityId_groupName)),
onClick = onEditNameClicked onClick = onEditNameClicked
) { ) {
Icon( Icon(
painterResource(R.drawable.ic_baseline_edit_24), painterResource(R.drawable.ic_baseline_edit_24),
contentDescription = stringResource(R.string.edit), contentDescription = stringResource(R.string.edit),
tint = LocalColors.current.text, tint = LocalColors.current.text,
) )
}
} }
} }
} }
} }
} }
}
// Header & Add member button
Row(
modifier = Modifier.padding(
horizontal = LocalDimensions.current.smallSpacing,
vertical = LocalDimensions.current.xxsSpacing
),
verticalAlignment = CenterVertically
) {
Text(
stringResource(R.string.groupMembers),
modifier = Modifier.weight(1f),
style = LocalType.current.large,
color = LocalColors.current.text
)
if (showAddMembers) { // Header & Add member button
PrimaryOutlineButton( Row(
stringResource(R.string.membersInvite), modifier = Modifier.padding(
onClick = onAddMemberClick, horizontal = LocalDimensions.current.smallSpacing,
modifier = Modifier.qaTag(stringResource(R.string.AccessibilityId_membersInvite)) vertical = LocalDimensions.current.xxsSpacing
),
verticalAlignment = CenterVertically
) {
Text(
stringResource(R.string.groupMembers),
modifier = Modifier.weight(1f),
style = LocalType.current.large,
color = LocalColors.current.text
) )
if (showAddMembers) {
PrimaryOutlineButton(
stringResource(R.string.membersInvite),
onClick = onAddMemberClick,
modifier = Modifier.qaTag(stringResource(R.string.AccessibilityId_membersInvite))
)
}
} }
}
// List of members // List of members
LazyColumn(modifier = Modifier) { LazyColumn(modifier = Modifier) {
items(members) { member -> items(members) { member ->
// Each member's view // Each member's view
EditMemberItem( EditMemberItem(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
member = member, member = member,
onClick = { onMemberClicked(member) } onClick = { onMemberClicked(member) }
) )
}
} }
} }
} }
@ -305,6 +314,10 @@ fun EditGroup(
) )
} }
if (showLoading) {
LoadingDialog()
}
val context = LocalContext.current val context = LocalContext.current
LaunchedEffect(showingError) { LaunchedEffect(showingError) {
@ -515,7 +528,8 @@ private fun EditGroupPreview3() {
onErrorDismissed = {}, onErrorDismissed = {},
onMemberClicked = {}, onMemberClicked = {},
hideActionSheet = {}, hideActionSheet = {},
clickedMember = null clickedMember = null,
showLoading = true,
) )
} }
} }
@ -589,7 +603,8 @@ private fun EditGroupPreview() {
onErrorDismissed = {}, onErrorDismissed = {},
onMemberClicked = {}, onMemberClicked = {},
hideActionSheet = {}, hideActionSheet = {},
clickedMember = null clickedMember = null,
showLoading = false,
) )
} }
} }
@ -655,7 +670,8 @@ private fun EditGroupEditNamePreview() {
onErrorDismissed = {}, onErrorDismissed = {},
onMemberClicked = {}, onMemberClicked = {},
hideActionSheet = {}, hideActionSheet = {},
clickedMember = null clickedMember = null,
showLoading = false,
) )
} }
} }

@ -128,7 +128,8 @@ fun AlertDialog(
text = it, text = it,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
style = LocalType.current.h7, style = LocalType.current.h7,
modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing) modifier = Modifier
.padding(bottom = LocalDimensions.current.xxsSpacing)
.qaTag(stringResource(R.string.AccessibilityId_modalTitle)) .qaTag(stringResource(R.string.AccessibilityId_modalTitle))
) )
} }
@ -281,22 +282,33 @@ fun LoadingDialog(
modifier = modifier, modifier = modifier,
onDismissRequest = {}, onDismissRequest = {},
content = { content = {
DialogBg { if (title.isNullOrBlank()) {
Column( Box {
modifier = Modifier
.fillMaxWidth()
.padding(LocalDimensions.current.spacing)
) {
CircularProgressIndicator( CircularProgressIndicator(
modifier = Modifier.align(Alignment.CenterHorizontally) modifier = Modifier.align(Alignment.Center),
//TODO: Leave this as hardcoded color for now as the dialog background (scrim)
// always seems to be dark. Can can revisit later when we have more control over
// the scrim color.
color = Color.White
) )
}
} else {
DialogBg {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(LocalDimensions.current.spacing)
) {
CircularProgressIndicator(
modifier = Modifier.align(Alignment.CenterHorizontally)
)
Spacer(modifier = Modifier.height(LocalDimensions.current.spacing)) Spacer(modifier = Modifier.height(LocalDimensions.current.spacing))
title?.let {
Text( Text(
it, title,
modifier = Modifier.align(Alignment.CenterHorizontally) modifier = Modifier
.align(Alignment.CenterHorizontally)
.qaTag(stringResource(R.string.AccessibilityId_modalTitle)), .qaTag(stringResource(R.string.AccessibilityId_modalTitle)),
style = LocalType.current.large style = LocalType.current.large
) )

Loading…
Cancel
Save