diff --git a/CHANGELOG.md b/CHANGELOG.md index b89e96a7b..49aee32d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,9 @@ * Fix: Refresh chat list when returning from conversation if selected profile changed * Fix: Update menu when using "select all" in contact selection * Fix: Avoid empty profiles after using "add as second device" from welcome screen +* Fix: Remove from group deselected members in the contact selection list * Fix multi-device seen messages synchronization when using multiple relays +* Fix layout problems inside in-chat apps * Avoid crash when the app is minimized with profile switcher or reactions dialogs open * Update to core 2.39.0 diff --git a/src/main/java/org/thoughtcrime/securesms/ContactMultiSelectionActivity.java b/src/main/java/org/thoughtcrime/securesms/ContactMultiSelectionActivity.java index 9654c0249..8767ea736 100644 --- a/src/main/java/org/thoughtcrime/securesms/ContactMultiSelectionActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/ContactMultiSelectionActivity.java @@ -34,6 +34,7 @@ import java.util.List; public class ContactMultiSelectionActivity extends ContactSelectionActivity { public static final String CONTACTS_EXTRA = "contacts_extra"; + public static final String DESELECTED_CONTACTS_EXTRA = "deselected_contacts_extra"; @Override protected void onCreate(Bundle icicle, boolean ready) { @@ -71,7 +72,9 @@ public class ContactMultiSelectionActivity extends ContactSelectionActivity { private void saveSelection() { Intent resultIntent = getIntent(); List selectedContacts = contactsFragment.getSelectedContacts(); + List deselectedContacts = contactsFragment.getDeselectedContacts(); resultIntent.putIntegerArrayListExtra(CONTACTS_EXTRA, new ArrayList<>(selectedContacts)); + resultIntent.putIntegerArrayListExtra(DESELECTED_CONTACTS_EXTRA, new ArrayList<>(deselectedContacts)); setResult(RESULT_OK, resultIntent); } } diff --git a/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java b/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java index 4c6f11bb0..bf4cf95ca 100644 --- a/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java @@ -58,6 +58,7 @@ import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import java.util.ArrayList; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -83,6 +84,7 @@ public class ContactSelectionListFragment extends Fragment private DcContext dcContext; private Set selectedContacts; + private Set deselectedContacts; private OnContactSelectedListener onContactSelectedListener; private String cursorFilter; private RecyclerView recyclerView; @@ -226,6 +228,15 @@ public class ContactSelectionListFragment extends Fragment return selected; } + public @NonNull List getDeselectedContacts() { + List deselected = new LinkedList<>(); + if (deselectedContacts != null) { + deselected.addAll(deselectedContacts); + } + + return deselected; + } + private boolean isMulti() { return getActivity().getIntent().getBooleanExtra(MULTI_SELECT, false); } @@ -241,6 +252,7 @@ public class ContactSelectionListFragment extends Fragment isMulti(), true); selectedContacts = adapter.getSelectedContacts(); + deselectedContacts = new HashSet<>(); ArrayList preselectedContacts = getActivity().getIntent().getIntegerArrayListExtra(PRESELECTED_CONTACTS); if(preselectedContacts!=null) { selectedContacts.addAll(preselectedContacts); @@ -309,12 +321,14 @@ public class ContactSelectionListFragment extends Fragment } selectedContacts.add(contactId); + deselectedContacts.remove(contactId); contact.setChecked(true); if (onContactSelectedListener != null) { onContactSelectedListener.onContactSelected(contactId); } } else { selectedContacts.remove(contactId); + deselectedContacts.add(contactId); contact.setChecked(false); if (onContactSelectedListener != null) { onContactSelectedListener.onContactDeselected(contactId); @@ -355,6 +369,7 @@ public class ContactSelectionListFragment extends Fragment int contactId = data.getIntExtra(NewContactActivity.CONTACT_ID_EXTRA, 0); if (contactId != 0) { selectedContacts.add(contactId); + deselectedContacts.remove(contactId); } getLoaderManager().restartLoader(0, null, ContactSelectionListFragment.this); } diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileFragment.java b/src/main/java/org/thoughtcrime/securesms/ProfileFragment.java index e9c9a19c5..6c9e38f6b 100644 --- a/src/main/java/org/thoughtcrime/securesms/ProfileFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/ProfileFragment.java @@ -310,11 +310,27 @@ public class ProfileFragment extends Fragment super.onActivityResult(requestCode, resultCode, data); if (requestCode==REQUEST_CODE_PICK_CONTACT && resultCode==Activity.RESULT_OK && data!=null) { List selected = data.getIntegerArrayListExtra(ContactMultiSelectionActivity.CONTACTS_EXTRA); - if(selected == null) return; + List deselected = data.getIntegerArrayListExtra(ContactMultiSelectionActivity.DESELECTED_CONTACTS_EXTRA); Util.runOnAnyBackgroundThread(() -> { - for (Integer contactId : selected) { - if (contactId!=null) { - dcContext.addContactToChat(chatId, contactId); + if (deselected != null) { + // Remove members that were deselected + int[] members = dcContext.getChatContacts(chatId); + for (int contactId : deselected) { + for (int memberId : members) { + if (memberId == contactId) { + dcContext.removeContactFromChat(chatId, memberId); + break; + } + } + } + } + + if (selected != null) { + // Add new members + for (Integer contactId : selected) { + if (contactId != null) { + dcContext.addContactToChat(chatId, contactId); + } } } }); diff --git a/src/main/java/org/thoughtcrime/securesms/WebViewActivity.java b/src/main/java/org/thoughtcrime/securesms/WebViewActivity.java index 42d1fc410..87094a35d 100644 --- a/src/main/java/org/thoughtcrime/securesms/WebViewActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/WebViewActivity.java @@ -77,7 +77,7 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity findViewById(R.id.status_bar_background).setBackgroundResource(R.drawable.search_toolbar_shadow); } else { // add padding to avoid content hidden behind system bars - ViewUtil.applyWindowInsets(findViewById(R.id.content_container)); + ViewUtil.applyWindowInsets(findViewById(R.id.content_container), true, true, true, true, true); } webView.setWebViewClient(new WebViewClient() { diff --git a/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java b/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java index 122cd38e0..91c4d3a6b 100644 --- a/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java +++ b/src/main/java/org/thoughtcrime/securesms/util/ViewUtil.java @@ -390,11 +390,27 @@ public class ViewUtil { /** * Apply window insets to a view by adding padding to avoid drawing elements behind system bars. * Convenience method that applies insets to all sides. + * IME insets are propagated to child views. * * @param view The view to apply insets to */ public static void applyWindowInsets(@NonNull View view) { - applyWindowInsets(view, true, true, true, true); + applyWindowInsets(view, true, true, true, true, false); + } + + /** + * Apply window insets to a view by adding padding to avoid drawing elements behind system bars. + * + * IME insets are propagated to child views. + * + * @param view The view to apply insets to + * @param left Whether to apply left inset + * @param top Whether to apply top inset + * @param right Whether to apply right inset + * @param bottom Whether to apply bottom inset + */ + public static void applyWindowInsets(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) { + applyWindowInsets(view, left, top, right, bottom, false); } /** @@ -408,8 +424,9 @@ public class ViewUtil { * @param top Whether to apply top inset * @param right Whether to apply right inset * @param bottom Whether to apply bottom inset + * @param consumeImeInsets Whether to consume IME insets so they don't propagate to child views */ - public static void applyWindowInsets(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) { + public static void applyWindowInsets(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom, boolean consumeImeInsets) { // Only enable on API 30+ where WindowInsets APIs work correctly if (!isEdgeToEdgeSupported()) return; @@ -442,6 +459,11 @@ public class ViewUtil { bottom ? basePaddingBottom + insets.bottom : basePaddingBottom ); + if (consumeImeInsets) { + windowInsets = new WindowInsetsCompat.Builder(windowInsets) + .setInsets(WindowInsetsCompat.Type.ime(), Insets.NONE) + .build(); + } return windowInsets; }); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 2f31a6eaa..d611028b6 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -1088,8 +1088,8 @@ Name Select Group Image Export Backup - sent - received + Sent + Received Open the Log Folder Open Current Logfile Tray icon cannot be disabled as Delta Chat was started with the --minimized option.