mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Fix race condition by tracking removed contacts explicitly
Instead of comparing current members at result time (which can change), ContactMultiSelectionActivity now tracks preselected contacts and explicitly returns which ones were removed. This eliminates the race condition where member list changes could cause accidental removals. Changes: - ContactMultiSelectionActivity: Store preselected contacts, calculate and return removed contacts - ProfileFragment: Use explicitly removed contacts instead of calculating from current member list Co-authored-by: adbenitez <24558636+adbenitez@users.noreply.github.com>
This commit is contained in:
@@ -23,7 +23,9 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Activity container for selecting a list of contacts.
|
||||
@@ -34,6 +36,9 @@ import java.util.List;
|
||||
public class ContactMultiSelectionActivity extends ContactSelectionActivity {
|
||||
|
||||
public static final String CONTACTS_EXTRA = "contacts_extra";
|
||||
public static final String REMOVED_CONTACTS_EXTRA = "removed_contacts_extra";
|
||||
|
||||
private ArrayList<Integer> preselectedContacts;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle, boolean ready) {
|
||||
@@ -44,6 +49,9 @@ public class ContactMultiSelectionActivity extends ContactSelectionActivity {
|
||||
// it's a bit confusing having one "X" button on the left and one on the right -
|
||||
// and the "clear search" button is not that important.
|
||||
getToolbar().setUseClearButton(false);
|
||||
|
||||
// Store preselected contacts to track which ones were removed
|
||||
preselectedContacts = getIntent().getIntegerArrayListExtra(ContactSelectionListFragment.PRESELECTED_CONTACTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,6 +80,19 @@ public class ContactMultiSelectionActivity extends ContactSelectionActivity {
|
||||
Intent resultIntent = getIntent();
|
||||
List<Integer> selectedContacts = contactsFragment.getSelectedContacts();
|
||||
resultIntent.putIntegerArrayListExtra(CONTACTS_EXTRA, new ArrayList<>(selectedContacts));
|
||||
|
||||
// Calculate which contacts were removed (preselected but not in final selection)
|
||||
if (preselectedContacts != null) {
|
||||
Set<Integer> selectedSet = new HashSet<>(selectedContacts);
|
||||
ArrayList<Integer> removedContacts = new ArrayList<>();
|
||||
for (Integer preselectedId : preselectedContacts) {
|
||||
if (!selectedSet.contains(preselectedId)) {
|
||||
removedContacts.add(preselectedId);
|
||||
}
|
||||
}
|
||||
resultIntent.putIntegerArrayListExtra(REMOVED_CONTACTS_EXTRA, removedContacts);
|
||||
}
|
||||
|
||||
setResult(RESULT_OK, resultIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ProfileFragment extends Fragment
|
||||
implements ProfileAdapter.ItemClickListener, DcEventCenter.DcEventDelegate {
|
||||
@@ -312,11 +310,9 @@ public class ProfileFragment extends Fragment
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode==REQUEST_CODE_PICK_CONTACT && resultCode==Activity.RESULT_OK && data!=null) {
|
||||
List<Integer> selected = data.getIntegerArrayListExtra(ContactMultiSelectionActivity.CONTACTS_EXTRA);
|
||||
List<Integer> removed = data.getIntegerArrayListExtra(ContactMultiSelectionActivity.REMOVED_CONTACTS_EXTRA);
|
||||
if(selected == null) return;
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
// Get current members
|
||||
int[] currentMembers = dcContext.getChatContacts(chatId);
|
||||
|
||||
// Add new members
|
||||
for (Integer contactId : selected) {
|
||||
if (contactId != null) {
|
||||
@@ -324,12 +320,12 @@ public class ProfileFragment extends Fragment
|
||||
}
|
||||
}
|
||||
|
||||
// Remove members that were unchecked
|
||||
// Use HashSet for O(1) lookup performance
|
||||
Set<Integer> selectedSet = new HashSet<>(selected);
|
||||
for (int currentMemberId : currentMembers) {
|
||||
if (!selectedSet.contains(currentMemberId)) {
|
||||
dcContext.removeContactFromChat(chatId, currentMemberId);
|
||||
// Remove members that were explicitly unchecked
|
||||
if (removed != null) {
|
||||
for (Integer contactId : removed) {
|
||||
if (contactId != null) {
|
||||
dcContext.removeContactFromChat(chatId, contactId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user