allow filtering in participant view. fixes #3371

Daniel Gultsch created

Change summary

src/conversations/res/menu/muc_users_activity.xml                | 11 
src/main/java/eu/siacs/conversations/ui/MucUsersActivity.java    | 85 +
src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java |  5 
src/main/res/values/strings.xml                                  |  1 
4 files changed, 95 insertions(+), 7 deletions(-)

Detailed changes

src/conversations/res/menu/muc_users_activity.xml 🔗

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+      xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <item
+        android:id="@+id/action_search"
+        app:actionLayout="@layout/actionview_search"
+        android:icon="?attr/icon_search"
+        app:showAsAction="collapseActionView|always"
+        android:title="@string/search"/>
+</menu>

src/main/java/eu/siacs/conversations/ui/MucUsersActivity.java 🔗

@@ -1,18 +1,27 @@
 package eu.siacs.conversations.ui;
 
+import android.content.Context;
 import android.content.Intent;
 import android.databinding.DataBindingUtil;
 import android.os.Bundle;
 import android.support.v7.widget.Toolbar;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.view.Menu;
 import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
 import android.widget.Toast;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Locale;
 
-import eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.databinding.ActivityMucUsersBinding;
+import eu.siacs.conversations.entities.Contact;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.entities.MucOptions;
 import eu.siacs.conversations.services.XmppConnectionService;
@@ -20,12 +29,16 @@ import eu.siacs.conversations.ui.adapter.UserAdapter;
 import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper;
 import rocks.xmpp.addr.Jid;
 
-public class MucUsersActivity extends XmppActivity implements XmppConnectionService.OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged {
+public class MucUsersActivity extends XmppActivity implements XmppConnectionService.OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, MenuItem.OnActionExpandListener, TextWatcher {
 
     private UserAdapter userAdapter;
 
     private Conversation mConversation = null;
 
+    private EditText mSearchEditText;
+
+    private ArrayList<MucOptions.User> allUsers = new ArrayList<>();
+
     @Override
     protected void refreshUiReal() {
     }
@@ -42,9 +55,26 @@ public class MucUsersActivity extends XmppActivity implements XmppConnectionServ
 
     private void loadAndSubmitUsers() {
         if (mConversation != null) {
-            ArrayList<MucOptions.User> users = mConversation.getMucOptions().getUsers();
-            Collections.sort(users);
-            userAdapter.submitList(users);
+            allUsers = mConversation.getMucOptions().getUsers();
+            Collections.sort(allUsers);
+            submitFilteredList(mSearchEditText != null ? mSearchEditText.getText().toString() : null);
+        }
+    }
+
+    private void submitFilteredList(String search) {
+        if (TextUtils.isEmpty(search)) {
+            userAdapter.submitList(allUsers);
+        } else {
+            final String needle = search.toLowerCase(Locale.getDefault());
+            ArrayList<MucOptions.User> filtered = new ArrayList<>();
+            for(MucOptions.User user : allUsers) {
+                final String name = user.getName();
+                final Contact contact = user.getContact();
+                if (name != null && name.toLowerCase(Locale.getDefault()).contains(needle) || contact != null && contact.getDisplayName().toLowerCase(Locale.getDefault()).contains(needle)) {
+                    filtered.add(user);
+                }
+            }
+            userAdapter.submitList(filtered);
         }
     }
 
@@ -86,4 +116,49 @@ public class MucUsersActivity extends XmppActivity implements XmppConnectionServ
         displayToast(getString(resId, jid.asBareJid().toString()));
     }
 
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        getMenuInflater().inflate(R.menu.muc_users_activity, menu);
+        final MenuItem menuSearchView = menu.findItem(R.id.action_search);
+        final View mSearchView = menuSearchView.getActionView();
+        mSearchEditText = mSearchView.findViewById(R.id.search_field);
+        mSearchEditText.addTextChangedListener(this);
+        mSearchEditText.setHint(R.string.search_participants);
+        menuSearchView.setOnActionExpandListener(this);
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemActionExpand(MenuItem item) {
+        mSearchEditText.post(() -> {
+            mSearchEditText.requestFocus();
+            final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+            imm.showSoftInput(mSearchEditText, InputMethodManager.SHOW_IMPLICIT);
+        });
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemActionCollapse(MenuItem item) {
+        final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
+        mSearchEditText.setText("");
+        submitFilteredList("");
+        return true;
+    }
+
+    @Override
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+    }
+
+    @Override
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+    }
+
+    @Override
+    public void afterTextChanged(Editable s) {
+        submitFilteredList(s.toString());
+    }
 }

src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java 🔗

@@ -82,8 +82,9 @@ public class UserAdapter extends ListAdapter<MucOptions.User, UserAdapter.ViewHo
         final String name = user.getName();
         final Contact contact = user.getContact();
         if (contact != null) {
-            viewHolder.binding.contactDisplayName.setText(contact.getDisplayName());
-            if (name != null) {
+            final String displayName = contact.getDisplayName();
+            viewHolder.binding.contactDisplayName.setText(displayName);
+            if (name != null && !name.equals(displayName)) {
                 viewHolder.binding.contactJid.setText(String.format("%s \u2022 %s", name, ConferenceDetailsActivity.getStatus(viewHolder.binding.getRoot().getContext(), user, advancedMode)));
             } else {
                 viewHolder.binding.contactJid.setText(ConferenceDetailsActivity.getStatus(viewHolder.binding.getRoot().getContext(), user, advancedMode));

src/main/res/values/strings.xml 🔗

@@ -854,4 +854,5 @@
     <string name="no_users_hint_channel">This public channel has no participants. Invite your contacts or use the share button to distribute its XMPP address.</string>
     <string name="no_users_hint_group_chat">This private group chat has no participants.</string>
     <string name="manage_permission">Manage privileges</string>
+    <string name="search_participants">Search participants</string>
 </resources>