Add network spinner to add members.

This commit is contained in:
Alan Evans 2020-09-30 13:59:39 -03:00 committed by GitHub
parent e60eae27fb
commit 3a4bae88ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 83 deletions

View File

@ -1,11 +0,0 @@
package org.thoughtcrime.securesms.groups.ui;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.recipients.RecipientId;
import java.util.List;
public interface AddMembersResultCallback {
void onMembersAdded(int numberOfMembersAdded, @NonNull List<RecipientId> invitedMembers);
}

View File

@ -11,6 +11,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -36,6 +37,8 @@ import org.thoughtcrime.securesms.components.ThreadPhotoRailView;
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.FallbackPhoto80dp; import org.thoughtcrime.securesms.contacts.avatars.FallbackPhoto80dp;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.groups.ui.GroupErrors;
import org.thoughtcrime.securesms.groups.ui.GroupMemberListView; import org.thoughtcrime.securesms.groups.ui.GroupMemberListView;
import org.thoughtcrime.securesms.groups.ui.LeaveGroupDialog; import org.thoughtcrime.securesms.groups.ui.LeaveGroupDialog;
import org.thoughtcrime.securesms.groups.ui.invitesandrequests.ManagePendingAndRequestingMembersActivity; import org.thoughtcrime.securesms.groups.ui.invitesandrequests.ManagePendingAndRequestingMembersActivity;
@ -53,10 +56,12 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment; import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;
import org.thoughtcrime.securesms.recipients.ui.notifications.CustomNotificationsDialogFragment; import org.thoughtcrime.securesms.recipients.ui.notifications.CustomNotificationsDialogFragment;
import org.thoughtcrime.securesms.recipients.ui.sharablegrouplink.ShareableGroupLinkDialogFragment; import org.thoughtcrime.securesms.recipients.ui.sharablegrouplink.ShareableGroupLinkDialogFragment;
import org.thoughtcrime.securesms.util.AsynchronousCallback;
import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.LifecycleCursorWrapper; import org.thoughtcrime.securesms.util.LifecycleCursorWrapper;
import org.thoughtcrime.securesms.util.views.LearnMoreTextView; import org.thoughtcrime.securesms.util.views.LearnMoreTextView;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -365,9 +370,6 @@ public class ManageGroupFragment extends LoggingFragment {
mentionsRow.setOnClickListener(v -> viewModel.handleMentionNotificationSelection()); mentionsRow.setOnClickListener(v -> viewModel.handleMentionNotificationSelection());
viewModel.getMentionSetting().observe(getViewLifecycleOwner(), value -> mentionsValue.setText(value)); viewModel.getMentionSetting().observe(getViewLifecycleOwner(), value -> mentionsValue.setText(value));
viewModel.getSnackbarEvents().observe(getViewLifecycleOwner(), this::handleSnackbarEvent);
viewModel.getInvitedDialogEvents().observe(getViewLifecycleOwner(), this::handleInvitedDialogEvent);
viewModel.getCanLeaveGroup().observe(getViewLifecycleOwner(), canLeave -> leaveGroup.setVisibility(canLeave ? View.VISIBLE : View.GONE)); viewModel.getCanLeaveGroup().observe(getViewLifecycleOwner(), canLeave -> leaveGroup.setVisibility(canLeave ? View.VISIBLE : View.GONE));
viewModel.getCanBlockGroup().observe(getViewLifecycleOwner(), canBlock -> { viewModel.getCanBlockGroup().observe(getViewLifecycleOwner(), canBlock -> {
blockGroup.setVisibility(canBlock ? View.VISIBLE : View.GONE); blockGroup.setVisibility(canBlock ? View.VISIBLE : View.GONE);
@ -435,28 +437,38 @@ public class ManageGroupFragment extends LoggingFragment {
} }
} }
private void handleSnackbarEvent(@NonNull ManageGroupViewModel.SnackbarEvent snackbarEvent) {
Snackbar.make(requireView(), buildSnackbarString(snackbarEvent), Snackbar.LENGTH_SHORT).setTextColor(Color.WHITE).show();
}
private void handleInvitedDialogEvent(@NonNull ManageGroupViewModel.InvitedDialogEvent invitedDialogEvent) {
GroupInviteSentDialog.showInvitesSent(requireContext(), invitedDialogEvent.getNewInvitedMembers());
}
private @NonNull String buildSnackbarString(@NonNull ManageGroupViewModel.SnackbarEvent snackbarEvent) {
return getResources().getQuantityString(R.plurals.ManageGroupActivity_added,
snackbarEvent.getNumberOfMembersAdded(),
snackbarEvent.getNumberOfMembersAdded());
}
@Override @Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RETURN_FROM_MEDIA) { if (requestCode == RETURN_FROM_MEDIA) {
applyMediaCursorFactory(); applyMediaCursorFactory();
} else if (requestCode == PICK_CONTACT && data != null) { } else if (requestCode == PICK_CONTACT && data != null) {
List<RecipientId> selected = data.getParcelableArrayListExtra(PushContactSelectionActivity.KEY_SELECTED_RECIPIENTS); List<RecipientId> selected = data.getParcelableArrayListExtra(PushContactSelectionActivity.KEY_SELECTED_RECIPIENTS);
viewModel.onAddMembers(selected); SimpleProgressDialog.DismissibleDialog progress = SimpleProgressDialog.showDelayed(requireContext());
viewModel.onAddMembers(selected, new AsynchronousCallback.MainThread<ManageGroupViewModel.AddMembersResult, GroupChangeFailureReason>() {
@Override
public void onComplete(ManageGroupViewModel.AddMembersResult result) {
progress.dismiss();
if (!result.getNewInvitedMembers().isEmpty()) {
GroupInviteSentDialog.showInvitesSent(requireContext(), result.getNewInvitedMembers());
}
if (result.getNumberOfMembersAdded() > 0) {
String string = getResources().getQuantityString(R.plurals.ManageGroupActivity_added,
result.getNumberOfMembersAdded(),
result.getNumberOfMembersAdded());
Snackbar.make(requireView(), string, Snackbar.LENGTH_SHORT).setTextColor(Color.WHITE).show();
}
}
@Override
public void onError(@Nullable GroupChangeFailureReason error) {
progress.dismiss();
Toast.makeText(requireContext(), GroupErrors.getUserDisplayMessage(error), Toast.LENGTH_LONG).show();
}
});
} }
} }
} }

View File

@ -20,13 +20,13 @@ import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupProtoUtil; import org.thoughtcrime.securesms.groups.GroupProtoUtil;
import org.thoughtcrime.securesms.groups.MembershipNotSuitableForV2Exception; import org.thoughtcrime.securesms.groups.MembershipNotSuitableForV2Exception;
import org.thoughtcrime.securesms.groups.ui.AddMembersResultCallback;
import org.thoughtcrime.securesms.groups.ui.GroupChangeErrorCallback; import org.thoughtcrime.securesms.groups.ui.GroupChangeErrorCallback;
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason; import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.util.AsynchronousCallback;
import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask; import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
@ -130,14 +130,16 @@ final class ManageGroupRepository {
}); });
} }
void addMembers(@NonNull List<RecipientId> selected, @NonNull AddMembersResultCallback addMembersResultCallback, @NonNull GroupChangeErrorCallback error) { void addMembers(@NonNull List<RecipientId> selected,
@NonNull AsynchronousCallback.WorkerThread<ManageGroupViewModel.AddMembersResult, GroupChangeFailureReason> callback)
{
SignalExecutors.UNBOUNDED.execute(() -> { SignalExecutors.UNBOUNDED.execute(() -> {
try { try {
GroupManager.GroupActionResult groupActionResult = GroupManager.addMembers(context, groupId.requirePush(), selected); GroupManager.GroupActionResult groupActionResult = GroupManager.addMembers(context, groupId.requirePush(), selected);
addMembersResultCallback.onMembersAdded(groupActionResult.getAddedMemberCount(), groupActionResult.getInvitedMembers()); callback.onComplete(new ManageGroupViewModel.AddMembersResult(groupActionResult.getAddedMemberCount(), Recipient.resolvedList(groupActionResult.getInvitedMembers())));
} catch (GroupChangeException | MembershipNotSuitableForV2Exception | IOException e) { } catch (GroupChangeException | MembershipNotSuitableForV2Exception | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.fromException(e)); callback.onError(GroupChangeFailureReason.fromException(e));
} }
}); });
} }

View File

@ -38,10 +38,10 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.util.AsynchronousCallback;
import org.thoughtcrime.securesms.util.DefaultValueLiveData; import org.thoughtcrime.securesms.util.DefaultValueLiveData;
import org.thoughtcrime.securesms.util.ExpirationUtil; import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.SingleLiveEvent;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog; import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
@ -55,8 +55,6 @@ public class ManageGroupViewModel extends ViewModel {
private final Context context; private final Context context;
private final ManageGroupRepository manageGroupRepository; private final ManageGroupRepository manageGroupRepository;
private final SingleLiveEvent<SnackbarEvent> snackbarEvents = new SingleLiveEvent<>();
private final SingleLiveEvent<InvitedDialogEvent> invitedDialogEvents = new SingleLiveEvent<>();
private final LiveData<String> title; private final LiveData<String> title;
private final LiveData<Boolean> isAdmin; private final LiveData<Boolean> isAdmin;
private final LiveData<Boolean> canEditGroupAttributes; private final LiveData<Boolean> canEditGroupAttributes;
@ -207,14 +205,6 @@ public class ManageGroupViewModel extends ViewModel {
return hasCustomNotifications; return hasCustomNotifications;
} }
SingleLiveEvent<SnackbarEvent> getSnackbarEvents() {
return snackbarEvents;
}
SingleLiveEvent<InvitedDialogEvent> getInvitedDialogEvents() {
return invitedDialogEvents;
}
LiveData<Boolean> getCanCollapseMemberList() { LiveData<Boolean> getCanCollapseMemberList() {
return canCollapseMemberList; return canCollapseMemberList;
} }
@ -266,8 +256,10 @@ public class ManageGroupViewModel extends ViewModel {
() -> RecipientUtil.unblock(context, recipient))); () -> RecipientUtil.unblock(context, recipient)));
} }
void onAddMembers(List<RecipientId> selected) { void onAddMembers(@NonNull List<RecipientId> selected,
manageGroupRepository.addMembers(selected, this::showAddSuccess, this::showErrorToast); @NonNull AsynchronousCallback.MainThread<AddMembersResult, GroupChangeFailureReason> callback)
{
manageGroupRepository.addMembers(selected, callback.toWorkerCallback());
} }
void setMuteUntil(long muteUntil) { void setMuteUntil(long muteUntil) {
@ -306,17 +298,6 @@ public class ManageGroupViewModel extends ViewModel {
} }
} }
@WorkerThread
private void showAddSuccess(int numberOfMembersAdded, @NonNull List<RecipientId> newInvitedMembers) {
if (!newInvitedMembers.isEmpty()) {
invitedDialogEvents.postValue(new InvitedDialogEvent(Recipient.resolvedList(newInvitedMembers)));
}
if (numberOfMembersAdded > 0) {
snackbarEvents.postValue(new SnackbarEvent(numberOfMembersAdded));
}
}
@WorkerThread @WorkerThread
private void showErrorToast(@NonNull GroupChangeFailureReason e) { private void showErrorToast(@NonNull GroupChangeFailureReason e) {
Util.runOnMain(() -> Toast.makeText(context, GroupErrors.getUserDisplayMessage(e), Toast.LENGTH_LONG).show()); Util.runOnMain(() -> Toast.makeText(context, GroupErrors.getUserDisplayMessage(e), Toast.LENGTH_LONG).show());
@ -338,6 +319,24 @@ public class ManageGroupViewModel extends ViewModel {
}); });
} }
static final class AddMembersResult {
private final int numberOfMembersAdded;
private final List<Recipient> newInvitedMembers;
AddMembersResult(int numberOfMembersAdded, @NonNull List<Recipient> newInvitedMembers) {
this.numberOfMembersAdded = numberOfMembersAdded;
this.newInvitedMembers = newInvitedMembers;
}
int getNumberOfMembersAdded() {
return numberOfMembersAdded;
}
List<Recipient> getNewInvitedMembers() {
return newInvitedMembers;
}
}
static final class GroupViewState { static final class GroupViewState {
private final long threadId; private final long threadId;
@NonNull private final Recipient groupRecipient; @NonNull private final Recipient groupRecipient;
@ -383,31 +382,6 @@ public class ManageGroupViewModel extends ViewModel {
} }
} }
static final class SnackbarEvent {
private final int numberOfMembersAdded;
private SnackbarEvent(int numberOfMembersAdded) {
this.numberOfMembersAdded = numberOfMembersAdded;
}
public int getNumberOfMembersAdded() {
return numberOfMembersAdded;
}
}
static final class InvitedDialogEvent {
private final List<Recipient> newInvitedMembers;
private InvitedDialogEvent(@NonNull List<Recipient> newInvitedMembers) {
this.newInvitedMembers = newInvitedMembers;
}
public @NonNull List<Recipient> getNewInvitedMembers() {
return newInvitedMembers;
}
}
enum GroupInfoMessage { enum GroupInfoMessage {
NONE, NONE,
LEGACY_GROUP_LEARN_MORE, LEGACY_GROUP_LEARN_MORE,