Added progress feedback to leave and block group actions and additional group v2 error handling.

This commit is contained in:
Alan Evans 2020-07-20 15:20:56 -03:00 committed by GitHub
parent 9a566e5559
commit a33771b15d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 216 additions and 188 deletions

View File

@ -148,12 +148,10 @@ import org.thoughtcrime.securesms.database.model.StickerRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.events.ReminderUpdateEvent; import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
import org.thoughtcrime.securesms.giph.ui.GiphyActivity; import org.thoughtcrime.securesms.giph.ui.GiphyActivity;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason; import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.groups.ui.GroupChangeResult;
import org.thoughtcrime.securesms.groups.ui.GroupErrors; import org.thoughtcrime.securesms.groups.ui.GroupErrors;
import org.thoughtcrime.securesms.groups.ui.LeaveGroupDialog; import org.thoughtcrime.securesms.groups.ui.LeaveGroupDialog;
import org.thoughtcrime.securesms.groups.ui.managegroup.ManageGroupActivity; import org.thoughtcrime.securesms.groups.ui.managegroup.ManageGroupActivity;
@ -1003,26 +1001,20 @@ public class ConversationActivity extends PassphraseRequiredActivity
if (activeGroup) { if (activeGroup) {
try { try {
GroupManager.updateGroupTimer(ConversationActivity.this, getRecipient().requireGroupId().requirePush(), expirationTime); GroupManager.updateGroupTimer(ConversationActivity.this, getRecipient().requireGroupId().requirePush(), expirationTime);
} catch (GroupInsufficientRightsException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
return ConversationActivity.this.getString(R.string.ManageGroupActivity_you_dont_have_the_rights_to_do_this); return GroupChangeResult.failure(GroupChangeFailureReason.fromException(e));
} catch (GroupNotAMemberException e) {
Log.w(TAG, e);
return ConversationActivity.this.getString(R.string.ManageGroupActivity_youre_not_a_member_of_the_group);
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
Log.w(TAG, e);
return ConversationActivity.this.getString(R.string.ManageGroupActivity_failed_to_update_the_group);
} }
} else { } else {
DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient.getId(), expirationTime); DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient.getId(), expirationTime);
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(getRecipient(), System.currentTimeMillis(), expirationTime * 1000L); OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(getRecipient(), System.currentTimeMillis(), expirationTime * 1000L);
MessageSender.send(ConversationActivity.this, outgoingMessage, threadId, false, null); MessageSender.send(ConversationActivity.this, outgoingMessage, threadId, false, null);
} }
return null; return GroupChangeResult.SUCCESS;
}, },
(errorString) -> { (changeResult) -> {
if (errorString != null) { if (changeResult.isSuccess()) {
Toast.makeText(ConversationActivity.this, errorString, Toast.LENGTH_SHORT).show(); Toast.makeText(ConversationActivity.this, GroupErrors.getUserDisplayMessage(changeResult.getFailureReason()), Toast.LENGTH_SHORT).show();
} else { } else {
invalidateOptionsMenu(); invalidateOptionsMenu();
if (fragment != null) fragment.setLastSeen(0); if (fragment != null) fragment.setLastSeen(0);

View File

@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.groups;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
public final class GroupChangeBusyException extends Exception { public final class GroupChangeBusyException extends GroupChangeException {
public GroupChangeBusyException(@NonNull Throwable throwable) { public GroupChangeBusyException(@NonNull Throwable throwable) {
super(throwable); super(throwable);

View File

@ -0,0 +1,17 @@
package org.thoughtcrime.securesms.groups;
import androidx.annotation.NonNull;
public abstract class GroupChangeException extends Exception {
GroupChangeException() {
}
GroupChangeException(@NonNull Throwable throwable) {
super(throwable);
}
GroupChangeException(@NonNull String message) {
super(message);
}
}

View File

@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.groups;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
public final class GroupChangeFailedException extends Exception { public final class GroupChangeFailedException extends GroupChangeException {
GroupChangeFailedException() { GroupChangeFailedException() {
} }

View File

@ -1,6 +1,6 @@
package org.thoughtcrime.securesms.groups; package org.thoughtcrime.securesms.groups;
public final class GroupInsufficientRightsException extends Exception { public final class GroupInsufficientRightsException extends GroupChangeException {
GroupInsufficientRightsException(Throwable throwable) { GroupInsufficientRightsException(Throwable throwable) {
super(throwable); super(throwable);

View File

@ -1,6 +1,6 @@
package org.thoughtcrime.securesms.groups; package org.thoughtcrime.securesms.groups;
public final class GroupNotAMemberException extends Exception { public final class GroupNotAMemberException extends GroupChangeException {
public GroupNotAMemberException(Throwable throwable) { public GroupNotAMemberException(Throwable throwable) {
super(throwable); super(throwable);

View File

@ -1,8 +1,28 @@
package org.thoughtcrime.securesms.groups.ui; package org.thoughtcrime.securesms.groups.ui;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
import org.thoughtcrime.securesms.groups.MembershipNotSuitableForV2Exception;
import java.io.IOException;
public enum GroupChangeFailureReason { public enum GroupChangeFailureReason {
NO_RIGHTS, NO_RIGHTS,
NOT_CAPABLE, NOT_CAPABLE,
NOT_A_MEMBER, NOT_A_MEMBER,
OTHER BUSY,
NETWORK,
OTHER;
public static @NonNull GroupChangeFailureReason fromException(@NonNull Exception e) {
if (e instanceof MembershipNotSuitableForV2Exception) return GroupChangeFailureReason.NOT_CAPABLE;
if (e instanceof IOException) return GroupChangeFailureReason.NETWORK;
if (e instanceof GroupNotAMemberException) return GroupChangeFailureReason.NOT_A_MEMBER;
if (e instanceof GroupChangeBusyException) return GroupChangeFailureReason.BUSY;
if (e instanceof GroupInsufficientRightsException) return GroupChangeFailureReason.NO_RIGHTS;
return GroupChangeFailureReason.OTHER;
}
} }

View File

@ -0,0 +1,31 @@
package org.thoughtcrime.securesms.groups.ui;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public final class GroupChangeResult {
public final static GroupChangeResult SUCCESS = new GroupChangeResult(null);
private final @Nullable GroupChangeFailureReason failureReason;
GroupChangeResult(@Nullable GroupChangeFailureReason failureReason) {
this.failureReason = failureReason;
}
public static GroupChangeResult failure(@NonNull GroupChangeFailureReason failureReason) {
return new GroupChangeResult(failureReason);
}
public boolean isSuccess() {
return failureReason == null;
}
public @NonNull GroupChangeFailureReason getFailureReason() {
if (isSuccess()) {
throw new UnsupportedOperationException();
}
return failureReason;
}
}

View File

@ -14,6 +14,8 @@ public final class GroupErrors {
case NO_RIGHTS : return R.string.ManageGroupActivity_you_dont_have_the_rights_to_do_this; case NO_RIGHTS : return R.string.ManageGroupActivity_you_dont_have_the_rights_to_do_this;
case NOT_CAPABLE : return R.string.ManageGroupActivity_not_capable; case NOT_CAPABLE : return R.string.ManageGroupActivity_not_capable;
case NOT_A_MEMBER: return R.string.ManageGroupActivity_youre_not_a_member_of_the_group; case NOT_A_MEMBER: return R.string.ManageGroupActivity_youre_not_a_member_of_the_group;
case BUSY : return R.string.ManageGroupActivity_failed_to_update_the_group_please_retry_later;
case NETWORK : return R.string.ManageGroupActivity_failed_to_update_the_group_due_to_a_network_error_please_retry_later;
default : return R.string.ManageGroupActivity_failed_to_update_the_group; default : return R.string.ManageGroupActivity_failed_to_update_the_group;
} }
} }

View File

@ -12,14 +12,14 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.ui.chooseadmin.ChooseNewAdminActivity; import org.thoughtcrime.securesms.groups.ui.chooseadmin.ChooseNewAdminActivity;
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.util.concurrent.SimpleTask; import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -90,26 +90,32 @@ public final class LeaveGroupDialog {
.setIconAttribute(R.attr.dialog_info_icon) .setIconAttribute(R.attr.dialog_info_icon)
.setCancelable(true) .setCancelable(true)
.setMessage(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group) .setMessage(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group)
.setPositiveButton(R.string.yes, (dialog, which) -> SimpleTask.run(activity.getLifecycle(), this::leaveGroup, this::handleLeaveGroupResult)) .setPositiveButton(R.string.yes, (dialog, which) -> {
SimpleProgressDialog.DismissibleDialog progressDialog = SimpleProgressDialog.showDelayed(activity);
SimpleTask.run(activity.getLifecycle(), this::leaveGroup, result -> {
progressDialog.dismiss();
handleLeaveGroupResult(result);
});
})
.setNegativeButton(R.string.no, null) .setNegativeButton(R.string.no, null)
.show(); .show();
} }
private boolean leaveGroup() { private @NonNull GroupChangeResult leaveGroup() {
try { try {
GroupManager.leaveGroup(activity, groupId); GroupManager.leaveGroup(activity, groupId);
return true; return GroupChangeResult.SUCCESS;
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
return false; return GroupChangeResult.failure(GroupChangeFailureReason.fromException(e));
} }
} }
private void handleLeaveGroupResult(boolean success) { private void handleLeaveGroupResult(@NonNull GroupChangeResult result) {
if (success) { if (result.isSuccess()) {
if (onSuccess != null) onSuccess.run(); if (onSuccess != null) onSuccess.run();
} else { } else {
Toast.makeText(activity, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show(); Toast.makeText(activity, GroupErrors.getUserDisplayMessage(result.getFailureReason()), Toast.LENGTH_LONG).show();
} }
} }
} }

View File

@ -5,12 +5,9 @@ import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
import org.thoughtcrime.securesms.groups.MembershipNotSuitableForV2Exception; import org.thoughtcrime.securesms.groups.MembershipNotSuitableForV2Exception;
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;
@ -44,15 +41,9 @@ final class AddToGroupRepository {
GroupManager.addMembers(context, pushGroupId, Collections.singletonList(recipientId)); GroupManager.addMembers(context, pushGroupId, Collections.singletonList(recipientId));
success.run(); success.run();
} catch (GroupInsufficientRightsException | GroupNotAMemberException e) { } catch (GroupChangeException | MembershipNotSuitableForV2Exception | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NO_RIGHTS); error.onError(GroupChangeFailureReason.fromException(e));
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER);
} catch (MembershipNotSuitableForV2Exception e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NOT_CAPABLE);
} }
}); });
} }

View File

@ -20,10 +20,10 @@ import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.groups.BadGroupIdException; import org.thoughtcrime.securesms.groups.BadGroupIdException;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.ui.GroupChangeResult;
import org.thoughtcrime.securesms.groups.ui.GroupErrors; import org.thoughtcrime.securesms.groups.ui.GroupErrors;
import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry; import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry;
import org.thoughtcrime.securesms.groups.ui.GroupMemberListView; import org.thoughtcrime.securesms.groups.ui.GroupMemberListView;
import org.thoughtcrime.securesms.groups.ui.chooseadmin.ChooseNewAdminRepository.UpdateResult;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
@ -108,7 +108,7 @@ public final class ChooseNewAdminActivity extends PassphraseRequiredActivity {
viewModel.getSelection().observe(this, selection -> done.setVisibility(selection.isEmpty() ? View.GONE : View.VISIBLE)); viewModel.getSelection().observe(this, selection -> done.setVisibility(selection.isEmpty() ? View.GONE : View.VISIBLE));
} }
private void handleUpdateAndLeaveResult(@NonNull UpdateResult updateResult) { private void handleUpdateAndLeaveResult(@NonNull GroupChangeResult updateResult) {
if (updateResult.isSuccess()) { if (updateResult.isSuccess()) {
String title = Recipient.externalGroup(this, groupId).getDisplayName(this); String title = Recipient.externalGroup(this, groupId).getDisplayName(this);
Toast.makeText(this, getString(R.string.ChooseNewAdminActivity_you_left, title), Toast.LENGTH_LONG).show(); Toast.makeText(this, getString(R.string.ChooseNewAdminActivity_you_left, title), Toast.LENGTH_LONG).show();

View File

@ -3,60 +3,32 @@ package org.thoughtcrime.securesms.groups.ui.chooseadmin;
import android.app.Application; import android.app.Application;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import androidx.core.util.Consumer;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason; import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.groups.ui.GroupChangeResult;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
public final class ChooseNewAdminRepository { public final class ChooseNewAdminRepository {
private Application context; private final Application context;
ChooseNewAdminRepository(@NonNull Application context) { ChooseNewAdminRepository(@NonNull Application context) {
this.context = context; this.context = context;
} }
@WorkerThread @WorkerThread
@NonNull UpdateResult updateAdminsAndLeave(@NonNull GroupId.V2 groupId, @NonNull List<RecipientId> newAdminIds) { @NonNull GroupChangeResult updateAdminsAndLeave(@NonNull GroupId.V2 groupId, @NonNull List<RecipientId> newAdminIds) {
try { try {
GroupManager.addMemberAdminsAndLeaveGroup(context, groupId, newAdminIds); GroupManager.addMemberAdminsAndLeaveGroup(context, groupId, newAdminIds);
return new UpdateResult(); return GroupChangeResult.SUCCESS;
} catch (GroupInsufficientRightsException e) { } catch (GroupChangeException | IOException e) {
return new UpdateResult(GroupChangeFailureReason.NO_RIGHTS); return GroupChangeResult.failure(GroupChangeFailureReason.fromException(e));
} catch (GroupNotAMemberException e) {
return new UpdateResult(GroupChangeFailureReason.NOT_A_MEMBER);
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
return new UpdateResult(GroupChangeFailureReason.OTHER);
}
}
static final class UpdateResult {
final @Nullable GroupChangeFailureReason failureReason;
UpdateResult() {
this(null);
}
UpdateResult(@Nullable GroupChangeFailureReason failureReason) {
this.failureReason = failureReason;
}
boolean isSuccess() {
return failureReason == null;
}
@Nullable GroupChangeFailureReason getFailureReason() {
return failureReason;
} }
} }
} }

View File

@ -1,11 +1,9 @@
package org.thoughtcrime.securesms.groups.ui.chooseadmin; package org.thoughtcrime.securesms.groups.ui.chooseadmin;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.core.util.Consumer; import androidx.core.util.Consumer;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@ -14,13 +12,10 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.LiveGroup; import org.thoughtcrime.securesms.groups.LiveGroup;
import org.thoughtcrime.securesms.groups.ui.GroupErrors; import org.thoughtcrime.securesms.groups.ui.GroupChangeResult;
import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry; import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry;
import org.thoughtcrime.securesms.groups.ui.chooseadmin.ChooseNewAdminRepository.UpdateResult;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask; import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -53,7 +48,7 @@ final class ChooseNewAdminViewModel extends ViewModel {
this.selection.setValue(selection); this.selection.setValue(selection);
} }
void updateAdminsAndLeave(@NonNull Consumer<UpdateResult> consumer) { void updateAdminsAndLeave(@NonNull Consumer<GroupChangeResult> consumer) {
//noinspection ConstantConditions //noinspection ConstantConditions
List<RecipientId> recipientIds = Stream.of(selection.getValue()).map(entry -> entry.getMember().getId()).toList(); List<RecipientId> recipientIds = Stream.of(selection.getValue()).map(entry -> entry.getMember().getId()).toList();
SimpleTask.run(() -> repository.updateAdminsAndLeave(groupId, recipientIds), consumer::accept); SimpleTask.run(() -> repository.updateAdminsAndLeave(groupId, recipientIds), consumer::accept);

View File

@ -8,7 +8,6 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
@ -24,24 +23,14 @@ 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.util.FeatureFlags; import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.ProfileUtil;
import org.thoughtcrime.securesms.util.Stopwatch; import org.thoughtcrime.securesms.util.Stopwatch;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask; import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog; import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
import org.whispersystems.signalservice.internal.util.concurrent.ListenableFuture;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
public class CreateGroupActivity extends ContactSelectionActivity { public class CreateGroupActivity extends ContactSelectionActivity {
@ -133,15 +122,8 @@ public class CreateGroupActivity extends ContactSelectionActivity {
} }
private void handleNextPressed() { private void handleNextPressed() {
Stopwatch stopwatch = new Stopwatch("Recipient Refresh"); Stopwatch stopwatch = new Stopwatch("Recipient Refresh");
AtomicReference<AlertDialog> progressDialog = new AtomicReference<>(); SimpleProgressDialog.DismissibleDialog dismissibleDialog = SimpleProgressDialog.showDelayed(this);
Runnable showDialogRunnable = () -> {
Log.i(TAG, "Taking some time. Showing a progress dialog.");
progressDialog.set(SimpleProgressDialog.show(this));
};
next.postDelayed(showDialogRunnable, 300);
SimpleTask.run(getLifecycle(), () -> { SimpleTask.run(getLifecycle(), () -> {
RecipientId[] ids = Stream.of(contactsFragment.getSelectedContacts()) RecipientId[] ids = Stream.of(contactsFragment.getSelectedContacts())
@ -182,11 +164,8 @@ public class CreateGroupActivity extends ContactSelectionActivity {
return ids; return ids;
}, ids -> { }, ids -> {
if (progressDialog.get() != null) { dismissibleDialog.dismiss();
progressDialog.get().dismiss();
}
next.removeCallbacks(showDialogRunnable);
stopwatch.stop(TAG); stopwatch.stop(TAG);
startActivityForResult(AddGroupDetailsActivity.newIntent(this, ids), REQUEST_CODE_ADD_DETAILS); startActivityForResult(AddGroupDetailsActivity.newIntent(this, ids), REQUEST_CODE_ADD_DETAILS);

View File

@ -9,7 +9,7 @@ import androidx.core.util.Consumer;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry; import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
@ -57,7 +57,7 @@ final class AddGroupDetailsRepository {
resultConsumer.accept(GroupCreateResult.success(result)); resultConsumer.accept(GroupCreateResult.success(result));
} catch (GroupChangeBusyException e) { } catch (GroupChangeBusyException e) {
resultConsumer.accept(GroupCreateResult.error(GroupCreateResult.Error.Type.ERROR_BUSY)); resultConsumer.accept(GroupCreateResult.error(GroupCreateResult.Error.Type.ERROR_BUSY));
} catch (GroupChangeFailedException e) { } catch (GroupChangeException e) {
resultConsumer.accept(GroupCreateResult.error(GroupCreateResult.Error.Type.ERROR_FAILED)); resultConsumer.accept(GroupCreateResult.error(GroupCreateResult.Error.Type.ERROR_FAILED));
} catch (IOException e) { } catch (IOException e) {
resultConsumer.accept(GroupCreateResult.error(GroupCreateResult.Error.Type.ERROR_IO)); resultConsumer.accept(GroupCreateResult.error(GroupCreateResult.Error.Type.ERROR_IO));

View File

@ -14,12 +14,9 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.groups.GroupAccessControl; import org.thoughtcrime.securesms.groups.GroupAccessControl;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
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.AddMembersResultCallback;
@ -89,15 +86,9 @@ final class ManageGroupRepository {
SignalExecutors.UNBOUNDED.execute(() -> { SignalExecutors.UNBOUNDED.execute(() -> {
try { try {
GroupManager.updateGroupTimer(context, groupId.requirePush(), newExpirationTime); GroupManager.updateGroupTimer(context, groupId.requirePush(), newExpirationTime);
} catch (GroupInsufficientRightsException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NO_RIGHTS); error.onError(GroupChangeFailureReason.fromException(e));
} catch (GroupNotAMemberException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NOT_A_MEMBER);
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER);
} }
}); });
} }
@ -106,12 +97,9 @@ final class ManageGroupRepository {
SignalExecutors.UNBOUNDED.execute(() -> { SignalExecutors.UNBOUNDED.execute(() -> {
try { try {
GroupManager.applyMembershipAdditionRightsChange(context, groupId.requireV2(), newRights); GroupManager.applyMembershipAdditionRightsChange(context, groupId.requireV2(), newRights);
} catch (GroupInsufficientRightsException | GroupNotAMemberException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NO_RIGHTS); error.onError(GroupChangeFailureReason.fromException(e));
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER);
} }
}); });
} }
@ -120,12 +108,9 @@ final class ManageGroupRepository {
SignalExecutors.UNBOUNDED.execute(() -> { SignalExecutors.UNBOUNDED.execute(() -> {
try { try {
GroupManager.applyAttributesRightsChange(context, groupId.requireV2(), newRights); GroupManager.applyAttributesRightsChange(context, groupId.requireV2(), newRights);
} catch (GroupInsufficientRightsException | GroupNotAMemberException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NO_RIGHTS); error.onError(GroupChangeFailureReason.fromException(e));
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER);
} }
}); });
} }
@ -148,26 +133,21 @@ final class ManageGroupRepository {
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()); addMembersResultCallback.onMembersAdded(groupActionResult.getAddedMemberCount(), groupActionResult.getInvitedMembers());
} catch (GroupInsufficientRightsException | GroupNotAMemberException e) { } catch (GroupChangeException | MembershipNotSuitableForV2Exception | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NO_RIGHTS); error.onError(GroupChangeFailureReason.fromException(e));
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER);
} catch (MembershipNotSuitableForV2Exception e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NOT_CAPABLE);
} }
}); });
} }
void blockAndLeaveGroup(@NonNull GroupChangeErrorCallback error) { void blockAndLeaveGroup(@NonNull GroupChangeErrorCallback error, @NonNull Runnable onSuccess) {
SignalExecutors.UNBOUNDED.execute(() -> { SignalExecutors.UNBOUNDED.execute(() -> {
try { try {
RecipientUtil.block(context, Recipient.externalGroup(context, groupId)); RecipientUtil.block(context, Recipient.externalGroup(context, groupId));
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) { onSuccess.run();
} catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER); error.onError(GroupChangeFailureReason.fromException(e));
} }
}); });
} }

View File

@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.SingleLiveEvent; 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 java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -213,7 +214,7 @@ public class ManageGroupViewModel extends ViewModel {
manageGroupRepository.getRecipient(recipient -> BlockUnblockDialog.showBlockFor(activity, manageGroupRepository.getRecipient(recipient -> BlockUnblockDialog.showBlockFor(activity,
activity.getLifecycle(), activity.getLifecycle(),
recipient, recipient,
() -> manageGroupRepository.blockAndLeaveGroup(this::showErrorToast))); this::onBlockAndLeaveConfirmed));
} }
void unblock(@NonNull FragmentActivity activity) { void unblock(@NonNull FragmentActivity activity) {
@ -237,6 +238,16 @@ public class ManageGroupViewModel extends ViewModel {
memberListCollapseState.setValue(CollapseState.OPEN); memberListCollapseState.setValue(CollapseState.OPEN);
} }
private void onBlockAndLeaveConfirmed() {
SimpleProgressDialog.DismissibleDialog dismissibleDialog = SimpleProgressDialog.showDelayed(context);
manageGroupRepository.blockAndLeaveGroup(e -> {
dismissibleDialog.dismiss();
showErrorToast(e);
},
dismissibleDialog::dismiss);
}
private static @NonNull List<GroupMemberEntry.FullMember> filterMemberList(@NonNull List<GroupMemberEntry.FullMember> members, private static @NonNull List<GroupMemberEntry.FullMember> filterMemberList(@NonNull List<GroupMemberEntry.FullMember> members,
@NonNull CollapseState collapseState) @NonNull CollapseState collapseState)
{ {

View File

@ -16,12 +16,9 @@ import org.signal.zkgroup.groups.UuidCiphertext;
import org.signal.zkgroup.util.UUIDUtil; import org.signal.zkgroup.util.UUIDUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
import org.thoughtcrime.securesms.groups.GroupProtoUtil; import org.thoughtcrime.securesms.groups.GroupProtoUtil;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
@ -105,7 +102,7 @@ final class PendingMemberRepository {
try { try {
GroupManager.cancelInvites(context, groupId, uuidCipherTexts); GroupManager.cancelInvites(context, groupId, uuidCipherTexts);
return true; return true;
} catch (GroupChangeFailedException | GroupInsufficientRightsException | IOException | GroupNotAMemberException | GroupChangeBusyException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
return false; return false;
} }

View File

@ -12,11 +12,8 @@ import org.thoughtcrime.securesms.database.MessagingDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
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.jobs.MultiDeviceMessageRequestResponseJob; import org.thoughtcrime.securesms.jobs.MultiDeviceMessageRequestResponseJob;
@ -101,12 +98,9 @@ final class MessageRequestRepository {
recipientDatabase.setProfileSharing(liveRecipient.getId(), true); recipientDatabase.setProfileSharing(liveRecipient.getId(), true);
onMessageRequestAccepted.run(); onMessageRequestAccepted.run();
} catch (GroupInsufficientRightsException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NO_RIGHTS); error.onError(GroupChangeFailureReason.fromException(e));
} catch (GroupChangeBusyException | GroupChangeFailedException | GroupNotAMemberException | IOException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER);
} }
} else { } else {
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context); RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
@ -139,9 +133,9 @@ final class MessageRequestRepository {
if (resolved.isGroup() && resolved.requireGroupId().isPush()) { if (resolved.isGroup() && resolved.requireGroupId().isPush()) {
try { try {
GroupManager.leaveGroupFromBlockOrMessageRequest(context, resolved.requireGroupId().requirePush()); GroupManager.leaveGroupFromBlockOrMessageRequest(context, resolved.requireGroupId().requirePush());
} catch (GroupChangeBusyException | GroupChangeFailedException | IOException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER); error.onError(GroupChangeFailureReason.fromException(e));
return; return;
} }
} }
@ -165,8 +159,9 @@ final class MessageRequestRepository {
Recipient recipient = liveRecipient.resolve(); Recipient recipient = liveRecipient.resolve();
try { try {
RecipientUtil.block(context, recipient); RecipientUtil.block(context, recipient);
} catch (GroupChangeBusyException | GroupChangeFailedException | IOException e) { } catch (GroupChangeException | IOException e) {
error.onError(GroupChangeFailureReason.OTHER); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.fromException(e));
return; return;
} }
liveRecipient.refresh(); liveRecipient.refresh();
@ -188,8 +183,9 @@ final class MessageRequestRepository {
Recipient recipient = liveRecipient.resolve(); Recipient recipient = liveRecipient.resolve();
try{ try{
RecipientUtil.block(context, recipient); RecipientUtil.block(context, recipient);
} catch (GroupChangeBusyException | GroupChangeFailedException | IOException e) { } catch (GroupChangeException | IOException e) {
error.onError(GroupChangeFailureReason.OTHER); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.fromException(e));
return; return;
} }
liveRecipient.refresh(); liveRecipient.refresh();

View File

@ -8,12 +8,9 @@ import androidx.annotation.WorkerThread;
import androidx.core.util.Consumer; import androidx.core.util.Consumer;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.profiles.AvatarHelper; import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.profiles.ProfileName; import org.thoughtcrime.securesms.profiles.ProfileName;
@ -83,7 +80,7 @@ class EditPushGroupProfileRepository implements EditProfileRepository {
GroupManager.updateGroupDetails(context, groupId, avatar, avatarChanged, displayName, displayNameChanged); GroupManager.updateGroupDetails(context, groupId, avatar, avatarChanged, displayName, displayNameChanged);
return UploadResult.SUCCESS; return UploadResult.SUCCESS;
} catch (GroupChangeFailedException | GroupInsufficientRightsException | IOException | GroupNotAMemberException | GroupChangeBusyException e) { } catch (GroupChangeException | IOException e) {
return UploadResult.ERROR_IO; return UploadResult.ERROR_IO;
} }

View File

@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException; import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
@ -77,7 +78,7 @@ public class RecipientUtil {
try { try {
block(context, recipient); block(context, recipient);
} catch (GroupChangeBusyException | IOException | GroupChangeFailedException e) { } catch (GroupChangeException | IOException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }

View File

@ -10,12 +10,9 @@ import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase; import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.GroupInsufficientRightsException;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.groups.GroupNotAMemberException;
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;
@ -89,12 +86,9 @@ final class RecipientDialogRepository {
try { try {
GroupManager.ejectFromGroup(context, Objects.requireNonNull(groupId).requireV2(), Recipient.resolved(recipientId)); GroupManager.ejectFromGroup(context, Objects.requireNonNull(groupId).requireV2(), Recipient.resolved(recipientId));
return true; return true;
} catch (GroupInsufficientRightsException | GroupNotAMemberException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NO_RIGHTS); error.onError(GroupChangeFailureReason.fromException(e));
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER);
} }
return false; return false;
}, },
@ -107,12 +101,9 @@ final class RecipientDialogRepository {
try { try {
GroupManager.setMemberAdmin(context, Objects.requireNonNull(groupId).requireV2(), recipientId, admin); GroupManager.setMemberAdmin(context, Objects.requireNonNull(groupId).requireV2(), recipientId, admin);
return true; return true;
} catch (GroupInsufficientRightsException | GroupNotAMemberException e) { } catch (GroupChangeException | IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
error.onError(GroupChangeFailureReason.NO_RIGHTS); error.onError(GroupChangeFailureReason.fromException(e));
} catch (GroupChangeFailedException | GroupChangeBusyException | IOException e) {
Log.w(TAG, e);
error.onError(GroupChangeFailureReason.OTHER);
} }
return false; return false;
}, },

View File

@ -2,18 +2,27 @@ package org.thoughtcrime.securesms.util.views;
import android.content.Context; import android.content.Context;
import androidx.annotation.AnyThread;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.Util;
import java.util.concurrent.atomic.AtomicReference;
/** /**
* Helper class to show a fullscreen blocking indeterminate progress dialog. * Helper class to show a fullscreen blocking indeterminate progress dialog.
*/ */
public final class SimpleProgressDialog { public final class SimpleProgressDialog {
private static final String TAG = Log.tag(SimpleProgressDialog.class);
private SimpleProgressDialog() {} private SimpleProgressDialog() {}
@MainThread
public static @NonNull AlertDialog show(@NonNull Context context) { public static @NonNull AlertDialog show(@NonNull Context context) {
AlertDialog dialog = new AlertDialog.Builder(context) AlertDialog dialog = new AlertDialog.Builder(context)
.setView(R.layout.progress_dialog) .setView(R.layout.progress_dialog)
@ -25,4 +34,44 @@ public final class SimpleProgressDialog {
return dialog; return dialog;
} }
@AnyThread
public static @NonNull DismissibleDialog showDelayed(@NonNull Context context) {
return showDelayed(context, 300);
}
/**
* Shows the dialog after {@param delayMs} ms.
* <p>
* To dismiss, call {@link DismissibleDialog#dismiss()} on the result. If dismiss is called before
* the delay has elapsed, the dialog will not show at all.
* <p>
* Dismiss can be called on any thread.
*/
@AnyThread
public static @NonNull DismissibleDialog showDelayed(@NonNull Context context, int delayMs) {
AtomicReference<AlertDialog> dialogAtomicReference = new AtomicReference<>();
Runnable showRunnable = () -> {
Log.i(TAG, "Taking some time. Showing a progress dialog.");
dialogAtomicReference.set(show(context));
};
Util.runOnMainDelayed(showRunnable, delayMs);
return () -> {
Util.cancelRunnableOnMain(showRunnable);
Util.runOnMain(() -> {
AlertDialog alertDialog = dialogAtomicReference.getAndSet(null);
if (alertDialog != null) {
alertDialog.dismiss();
}
});
};
}
public interface DismissibleDialog {
@AnyThread
void dismiss();
}
} }

View File

@ -234,7 +234,6 @@
<string name="ConversationActivity_transport_insecure_mms">Insecure MMS</string> <string name="ConversationActivity_transport_insecure_mms">Insecure MMS</string>
<string name="ConversationActivity_transport_signal">Signal</string> <string name="ConversationActivity_transport_signal">Signal</string>
<string name="ConversationActivity_lets_switch_to_signal">Let\'s switch to Signal %1$s</string> <string name="ConversationActivity_lets_switch_to_signal">Let\'s switch to Signal %1$s</string>
<string name="ConversationActivity_error_leaving_group">Error leaving group</string>
<string name="ConversationActivity_specify_recipient">Please choose a contact</string> <string name="ConversationActivity_specify_recipient">Please choose a contact</string>
<string name="ConversationActivity_unblock_this_contact_question">Unblock this contact?</string> <string name="ConversationActivity_unblock_this_contact_question">Unblock this contact?</string>
<string name="ConversationActivity_unblock_this_group_question">Unblock this group?</string> <string name="ConversationActivity_unblock_this_group_question">Unblock this group?</string>
@ -554,6 +553,8 @@
<string name="ManageGroupActivity_not_capable">Someone you added does not support new groups and needs to update Signal</string> <string name="ManageGroupActivity_not_capable">Someone you added does not support new groups and needs to update Signal</string>
<string name="ManageGroupActivity_failed_to_update_the_group">Failed to update the group</string> <string name="ManageGroupActivity_failed_to_update_the_group">Failed to update the group</string>
<string name="ManageGroupActivity_youre_not_a_member_of_the_group">You\'re not a member of the group</string> <string name="ManageGroupActivity_youre_not_a_member_of_the_group">You\'re not a member of the group</string>
<string name="ManageGroupActivity_failed_to_update_the_group_please_retry_later">Failed to update the group please retry later</string>
<string name="ManageGroupActivity_failed_to_update_the_group_due_to_a_network_error_please_retry_later">Failed to update the group due to a network error, please retry later</string>
<string name="ManageGroupActivity_edit_name_and_picture">Edit name and picture</string> <string name="ManageGroupActivity_edit_name_and_picture">Edit name and picture</string>