diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt index d3939a9518..5ea00b2a5e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt @@ -264,6 +264,9 @@ class GroupManagerV2Impl @Inject constructor( subAccountTokens = subAccountTokens ) + // Before we send the invitation, we need to make sure the configs are pushed + configFactory.waitUntilGroupConfigsPushed(group) + // Call the API try { val swarmNode = SnodeAPI.getSingleTargetSnode(group.hexString).await() diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/compose/EditGroupScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/compose/EditGroupScreen.kt index 6c4a9b3572..e2141bfbf0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/compose/EditGroupScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/compose/EditGroupScreen.kt @@ -28,6 +28,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Alignment.Companion.CenterVertically +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext 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.DialogButtonModel 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.ActionSheetItemData +import org.thoughtcrime.securesms.ui.components.BackAppBar import org.thoughtcrime.securesms.ui.components.PrimaryOutlineButton import org.thoughtcrime.securesms.ui.components.SessionOutlinedTextField import org.thoughtcrime.securesms.ui.components.annotatedStringResource @@ -99,6 +101,7 @@ fun EditGroupScreen( onMemberClicked = viewModel::onMemberClicked, hideActionSheet = viewModel::hideActionBottomSheet, clickedMember = viewModel.clickedMember.collectAsState().value, + showLoading = viewModel.inProgress.collectAsState().value, ) } @@ -119,7 +122,7 @@ fun EditGroupScreen( @Serializable private object RouteEditGroup -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @Composable fun EditGroup( onBack: () -> Unit, @@ -141,6 +144,7 @@ fun EditGroup( members: List, showAddMembers: Boolean, showingError: String?, + showLoading: Boolean, onErrorDismissed: () -> Unit, ) { val (showingConfirmRemovingMember, setShowingConfirmRemovingMember) = remember { @@ -157,115 +161,120 @@ fun EditGroup( ) } ) { paddingValues -> - Column(modifier = Modifier.padding(paddingValues)) { - - GroupMinimumVersionBanner() - - // Group name title - Crossfade(editingName != null, label = "Editable group name") { showNameEditing -> - if (showNameEditing) { - GroupNameContainer { - IconButton( - modifier = Modifier.size(LocalDimensions.current.spacing), - onClick = onEditNameCancelClicked) { - Icon( - painter = painterResource(R.drawable.ic_x), - contentDescription = stringResource(R.string.AccessibilityId_cancel), - tint = LocalColors.current.text, - ) - } + Box { + Column(modifier = Modifier.padding(paddingValues)) { + GroupMinimumVersionBanner() + + // Group name title + Crossfade(editingName != null, label = "Editable group name") { showNameEditing -> + if (showNameEditing) { + GroupNameContainer { + IconButton( + modifier = Modifier.size(LocalDimensions.current.spacing), + onClick = onEditNameCancelClicked + ) { + Icon( + painter = painterResource(R.drawable.ic_x), + contentDescription = stringResource(R.string.AccessibilityId_cancel), + tint = LocalColors.current.text, + ) + } - SessionOutlinedTextField( - modifier = Modifier.widthIn( - min = LocalDimensions.current.mediumSpacing, - max = maxNameWidth - ) - .qaTag(stringResource(R.string.AccessibilityId_groupName)), - text = editingName.orEmpty(), - onChange = onEditingNameValueChanged, - textStyle = LocalType.current.h8, - singleLine = true, - innerPadding = PaddingValues( - horizontal = LocalDimensions.current.spacing, - vertical = LocalDimensions.current.smallSpacing + SessionOutlinedTextField( + modifier = Modifier + .widthIn( + min = LocalDimensions.current.mediumSpacing, + max = maxNameWidth + ) + .qaTag(stringResource(R.string.AccessibilityId_groupName)), + text = editingName.orEmpty(), + onChange = onEditingNameValueChanged, + textStyle = LocalType.current.h8, + singleLine = true, + innerPadding = PaddingValues( + horizontal = LocalDimensions.current.spacing, + vertical = LocalDimensions.current.smallSpacing + ) ) - ) - IconButton( - modifier = Modifier.size(LocalDimensions.current.spacing), - onClick = onEditNameConfirmed) { - Icon( - painter = painterResource(R.drawable.check), - contentDescription = stringResource(R.string.AccessibilityId_confirm), - tint = LocalColors.current.text, - ) + IconButton( + modifier = Modifier.size(LocalDimensions.current.spacing), + onClick = onEditNameConfirmed + ) { + Icon( + painter = painterResource(R.drawable.check), + contentDescription = stringResource(R.string.AccessibilityId_confirm), + tint = LocalColors.current.text, + ) + } } - } - } else { - GroupNameContainer { - Spacer(modifier = Modifier.weight(1f)) - Text( - text = groupName, - style = LocalType.current.h4, - textAlign = TextAlign.Center, - modifier = Modifier.widthIn(max = maxNameWidth) - .padding(vertical = LocalDimensions.current.smallSpacing), - ) + } else { + GroupNameContainer { + Spacer(modifier = Modifier.weight(1f)) + Text( + text = groupName, + style = LocalType.current.h4, + textAlign = TextAlign.Center, + modifier = Modifier + .widthIn(max = maxNameWidth) + .padding(vertical = LocalDimensions.current.smallSpacing), + ) - Box(modifier = Modifier.weight(1f)) { - if (canEditName) { - IconButton( - modifier = Modifier.qaTag(stringResource(R.string.AccessibilityId_groupName)), - onClick = onEditNameClicked - ) { - Icon( - painterResource(R.drawable.ic_baseline_edit_24), - contentDescription = stringResource(R.string.edit), - tint = LocalColors.current.text, - ) + Box(modifier = Modifier.weight(1f)) { + if (canEditName) { + IconButton( + modifier = Modifier.qaTag(stringResource(R.string.AccessibilityId_groupName)), + onClick = onEditNameClicked + ) { + Icon( + painterResource(R.drawable.ic_baseline_edit_24), + contentDescription = stringResource(R.string.edit), + 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) { - PrimaryOutlineButton( - stringResource(R.string.membersInvite), - onClick = onAddMemberClick, - modifier = Modifier.qaTag(stringResource(R.string.AccessibilityId_membersInvite)) + // 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) { + PrimaryOutlineButton( + stringResource(R.string.membersInvite), + onClick = onAddMemberClick, + modifier = Modifier.qaTag(stringResource(R.string.AccessibilityId_membersInvite)) + ) + } } - } - // List of members - LazyColumn(modifier = Modifier) { - items(members) { member -> - // Each member's view - EditMemberItem( - modifier = Modifier.fillMaxWidth(), - member = member, - onClick = { onMemberClicked(member) } - ) + // List of members + LazyColumn(modifier = Modifier) { + items(members) { member -> + // Each member's view + EditMemberItem( + modifier = Modifier.fillMaxWidth(), + member = member, + onClick = { onMemberClicked(member) } + ) + } } } } @@ -305,6 +314,10 @@ fun EditGroup( ) } + if (showLoading) { + LoadingDialog() + } + val context = LocalContext.current LaunchedEffect(showingError) { @@ -515,7 +528,8 @@ private fun EditGroupPreview3() { onErrorDismissed = {}, onMemberClicked = {}, hideActionSheet = {}, - clickedMember = null + clickedMember = null, + showLoading = true, ) } } @@ -589,7 +603,8 @@ private fun EditGroupPreview() { onErrorDismissed = {}, onMemberClicked = {}, hideActionSheet = {}, - clickedMember = null + clickedMember = null, + showLoading = false, ) } } @@ -655,7 +670,8 @@ private fun EditGroupEditNamePreview() { onErrorDismissed = {}, onMemberClicked = {}, hideActionSheet = {}, - clickedMember = null + clickedMember = null, + showLoading = false, ) } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/AlertDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/AlertDialog.kt index 988220960e..155082ad32 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/AlertDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/AlertDialog.kt @@ -128,7 +128,8 @@ fun AlertDialog( text = it, textAlign = TextAlign.Center, style = LocalType.current.h7, - modifier = Modifier.padding(bottom = LocalDimensions.current.xxsSpacing) + modifier = Modifier + .padding(bottom = LocalDimensions.current.xxsSpacing) .qaTag(stringResource(R.string.AccessibilityId_modalTitle)) ) } @@ -281,22 +282,33 @@ fun LoadingDialog( modifier = modifier, onDismissRequest = {}, content = { - DialogBg { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(LocalDimensions.current.spacing) - ) { + if (title.isNullOrBlank()) { + Box { 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( - it, - modifier = Modifier.align(Alignment.CenterHorizontally) + title, + modifier = Modifier + .align(Alignment.CenterHorizontally) .qaTag(stringResource(R.string.AccessibilityId_modalTitle)), style = LocalType.current.large )