Add feature flag driven group recommended size and hard size limits.

This commit is contained in:
Alan Evans
2020-10-22 14:52:05 -03:00
committed by Cody Henthorne
parent 5eace49739
commit b4b1e5b605
12 changed files with 246 additions and 54 deletions

View File

@@ -0,0 +1,65 @@
package org.thoughtcrime.securesms.groups;
import android.os.Parcel;
import android.os.Parcelable;
public final class SelectionLimits implements Parcelable {
public static final int NO_LIMIT = Integer.MAX_VALUE;
public static final SelectionLimits NO_LIMITS = new SelectionLimits(NO_LIMIT, NO_LIMIT);
private final int recommendedLimit;
private final int hardLimit;
public SelectionLimits(int recommendedLimit, int hardLimit) {
this.recommendedLimit = recommendedLimit;
this.hardLimit = hardLimit;
}
public int getRecommendedLimit() {
return recommendedLimit;
}
public int getHardLimit() {
return hardLimit;
}
public boolean hasRecommendedLimit() {
return recommendedLimit != NO_LIMIT;
}
public boolean hasHardLimit() {
return hardLimit != NO_LIMIT;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(recommendedLimit);
dest.writeInt(hardLimit);
}
public static final Creator<SelectionLimits> CREATOR = new Creator<SelectionLimits>() {
@Override
public SelectionLimits createFromParcel(Parcel in) {
return new SelectionLimits(in.readInt(), in.readInt());
}
@Override
public SelectionLimits[] newArray(int size) {
return new SelectionLimits[size];
}
};
public SelectionLimits excludingSelf() {
return excluding(1);
}
public SelectionLimits excluding(int count) {
return new SelectionLimits(recommendedLimit - count, hardLimit - count);
}
}

View File

@@ -0,0 +1,28 @@
package org.thoughtcrime.securesms.groups.ui;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.FeatureFlags;
public final class GroupLimitDialog {
public static void showHardLimitMessage(@NonNull Context context) {
new AlertDialog.Builder(context)
.setTitle(R.string.ContactSelectionListFragment_maximum_group_size_reached)
.setMessage(context.getString(R.string.ContactSelectionListFragment_signal_groups_can_have_a_maximum_of_d_members, FeatureFlags.groupLimits().getHardLimit()))
.setPositiveButton(android.R.string.ok, null)
.show();
}
public static void showRecommendedLimitMessage(@NonNull Context context) {
new AlertDialog.Builder(context)
.setTitle(R.string.ContactSelectionListFragment_recommended_member_limit_reached)
.setMessage(context.getString(R.string.ContactSelectionListFragment_signal_groups_perform_best_with_d_members_or_fewer, FeatureFlags.groupLimits().getRecommendedLimit()))
.setPositiveButton(android.R.string.ok, null)
.show();
}
}

View File

@@ -51,7 +51,6 @@ public final class AddToGroupsActivity extends ContactSelectionActivity {
intent.putExtra(EXTRA_RECIPIENT_ID, recipientId);
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, ContactsCursorLoader.DisplayMode.FLAG_ACTIVE_GROUPS);
intent.putExtra(ContactSelectionListFragment.SELECTION_LIMIT, ContactSelectionListFragment.NO_LIMIT);
intent.putParcelableArrayListExtra(ContactSelectionListFragment.CURRENT_SELECTION, new ArrayList<>(currentGroupsMemberOf));

View File

@@ -56,8 +56,7 @@ public class CreateGroupActivity extends ContactSelectionActivity {
: ContactsCursorLoader.DisplayMode.FLAG_PUSH;
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, displayMode);
intent.putExtra(ContactSelectionListFragment.SELECTION_LIMIT, SignalStore.internalValues().gv2DoNotCreateGv2Groups() ? ContactSelectionListFragment.NO_LIMIT
: FeatureFlags.gv2GroupCapacity() - 1);
intent.putExtra(ContactSelectionListFragment.SELECTION_LIMITS, FeatureFlags.groupLimits().excludingSelf());
return intent;
}

View File

@@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.groups.GroupProtoUtil;
import org.thoughtcrime.securesms.groups.MembershipNotSuitableForV2Exception;
import org.thoughtcrime.securesms.groups.ui.GroupChangeErrorCallback;
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.groups.SelectionLimits;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
@@ -44,8 +45,8 @@ final class ManageGroupRepository {
private final GroupId groupId;
ManageGroupRepository(@NonNull Context context, @NonNull GroupId groupId) {
this.context = context;
this.groupId = groupId;
this.context = context;
this.groupId = groupId;
}
public GroupId getGroupId() {
@@ -68,9 +69,9 @@ final class ManageGroupRepository {
members.addAll(pendingMembers);
return new GroupCapacityResult(members, FeatureFlags.gv2GroupCapacity());
return new GroupCapacityResult(members, FeatureFlags.groupLimits());
} else {
return new GroupCapacityResult(groupRecord.getMembers(), ContactSelectionListFragment.NO_LIMIT);
return new GroupCapacityResult(groupRecord.getMembers(), FeatureFlags.groupLimits());
}
}, onGroupCapacityLoaded::accept);
}
@@ -186,33 +187,39 @@ final class ManageGroupRepository {
static final class GroupCapacityResult {
private final List<RecipientId> members;
private final int totalCapacity;
private final SelectionLimits selectionLimits;
GroupCapacityResult(@NonNull List<RecipientId> members, int totalCapacity) {
this.members = members;
this.totalCapacity = totalCapacity;
GroupCapacityResult(@NonNull List<RecipientId> members, @NonNull SelectionLimits selectionLimits) {
this.members = members;
this.selectionLimits = selectionLimits;
}
public @NonNull List<RecipientId> getMembers() {
return members;
}
public int getTotalCapacity() {
return totalCapacity;
}
public int getSelectionLimit() {
if (totalCapacity == ContactSelectionListFragment.NO_LIMIT) {
return totalCapacity;
if (!selectionLimits.hasHardLimit()) {
return ContactSelectionListFragment.NO_LIMIT;
}
boolean containsSelf = members.indexOf(Recipient.self().getId()) != -1;
return totalCapacity - (containsSelf ? 1 : 0);
return selectionLimits.getHardLimit() - (containsSelf ? 1 : 0);
}
public int getSelectionWarning() {
if (!selectionLimits.hasRecommendedLimit()) {
return ContactSelectionListFragment.NO_LIMIT;
}
boolean containsSelf = members.indexOf(Recipient.self().getId()) != -1;
return selectionLimits.getRecommendedLimit() - (containsSelf ? 1 : 0);
}
public int getRemainingCapacity() {
return totalCapacity - members.size();
return selectionLimits.getHardLimit() - members.size();
}
public @NonNull ArrayList<RecipientId> getMembersWithoutSelf() {

View File

@@ -27,9 +27,11 @@ import org.thoughtcrime.securesms.database.loaders.MediaLoader;
import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
import org.thoughtcrime.securesms.groups.GroupAccessControl;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.SelectionLimits;
import org.thoughtcrime.securesms.groups.LiveGroup;
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
import org.thoughtcrime.securesms.groups.ui.GroupErrors;
import org.thoughtcrime.securesms.groups.ui.GroupLimitDialog;
import org.thoughtcrime.securesms.groups.ui.GroupMemberEntry;
import org.thoughtcrime.securesms.groups.ui.addmembers.AddMembersActivity;
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupMentionSettingDialog;
@@ -306,12 +308,12 @@ public class ManageGroupViewModel extends ViewModel {
manageGroupRepository.getGroupCapacity(capacity -> {
int remainingCapacity = capacity.getRemainingCapacity();
if (remainingCapacity <= 0) {
Toast.makeText(fragment.requireContext(), R.string.ContactSelectionListFragment_the_group_is_full, Toast.LENGTH_SHORT).show();
GroupLimitDialog.showHardLimitMessage(fragment.requireContext());
} else {
Intent intent = new Intent(fragment.requireActivity(), AddMembersActivity.class);
intent.putExtra(AddMembersActivity.GROUP_ID, manageGroupRepository.getGroupId().toString());
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, ContactsCursorLoader.DisplayMode.FLAG_PUSH);
intent.putExtra(ContactSelectionListFragment.SELECTION_LIMIT, capacity.getSelectionLimit());
intent.putExtra(ContactSelectionListFragment.SELECTION_LIMITS, new SelectionLimits(capacity.getSelectionWarning(), capacity.getSelectionLimit()));
intent.putParcelableArrayListExtra(ContactSelectionListFragment.CURRENT_SELECTION, capacity.getMembersWithoutSelf());
fragment.startActivityForResult(intent, resultCode);
}