1package eu.siacs.conversations.ui;
2
3import android.content.Context;
4import android.content.Intent;
5import android.os.Bundle;
6import android.text.Editable;
7import android.text.TextUtils;
8import android.text.TextWatcher;
9import android.view.Menu;
10import android.view.MenuItem;
11import android.view.View;
12import android.view.inputmethod.InputMethodManager;
13import android.widget.EditText;
14import android.widget.Toast;
15
16import androidx.annotation.NonNull;
17import androidx.databinding.DataBindingUtil;
18
19import com.google.common.collect.Collections2;
20import com.google.common.collect.Lists;
21import com.google.common.collect.Ordering;
22
23import java.util.ArrayList;
24import java.util.Collections;
25import java.util.Locale;
26
27import eu.siacs.conversations.R;
28import eu.siacs.conversations.databinding.ActivityMucUsersBinding;
29import eu.siacs.conversations.entities.Contact;
30import eu.siacs.conversations.entities.Conversation;
31import eu.siacs.conversations.entities.MucOptions;
32import eu.siacs.conversations.services.XmppConnectionService;
33import eu.siacs.conversations.ui.adapter.UserAdapter;
34import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper;
35import eu.siacs.conversations.xmpp.Jid;
36import im.conversations.android.xmpp.model.muc.Affiliation;
37
38public class MucUsersActivity extends XmppActivity implements XmppConnectionService.OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, MenuItem.OnActionExpandListener, TextWatcher {
39
40 private UserAdapter userAdapter;
41
42 private Conversation mConversation = null;
43
44 private EditText mSearchEditText;
45
46 private ArrayList<MucOptions.User> allUsers = new ArrayList<>();
47
48 @Override
49 protected void refreshUiReal() {
50 }
51
52 @Override
53 protected void onBackendConnected() {
54 final Intent intent = getIntent();
55 final String uuid = intent == null ? null : intent.getStringExtra("uuid");
56 if (uuid != null) {
57 mConversation = xmppConnectionService.findConversationByUuid(uuid);
58 }
59 loadAndSubmitUsers();
60 }
61
62 private void loadAndSubmitUsers() {
63 if (mConversation != null) {
64 allUsers = mConversation.getMucOptions().getUsers(true, mConversation.getMucOptions().getSelf().ranks(Affiliation.ADMIN));
65 submitFilteredList(mSearchEditText != null ? mSearchEditText.getText().toString() : null);
66 }
67 }
68
69 private void submitFilteredList(final String search) {
70 if (TextUtils.isEmpty(search)) {
71 userAdapter.submitList(Ordering.natural().immutableSortedCopy(allUsers));
72 } else {
73 final String needle = search.toLowerCase(Locale.getDefault());
74 userAdapter.submitList(
75 Ordering.natural()
76 .immutableSortedCopy(
77 Collections2.filter(
78 this.allUsers,
79 user -> {
80 final String name = user.getName();
81 final Contact contact = user.getContact();
82 return name != null
83 && name.toLowerCase(
84 Locale.getDefault())
85 .contains(needle)
86 || contact != null
87 && contact.getDisplayName()
88 .toLowerCase(
89 Locale.getDefault())
90 .contains(needle);
91 })));
92 }
93 }
94
95 @Override
96 public boolean onContextItemSelected(@NonNull MenuItem item) {
97 if (!MucDetailsContextMenuHelper.onContextItemSelected(item, userAdapter.getSelectedUser(), this)) {
98 return super.onContextItemSelected(item);
99 }
100 return true;
101 }
102
103 @Override
104 protected void onCreate(final Bundle savedInstanceState) {
105 super.onCreate(savedInstanceState);
106 final ActivityMucUsersBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_muc_users);
107 setSupportActionBar(binding.toolbar);
108 Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
109 configureActionBar(getSupportActionBar(), true);
110 this.userAdapter = new UserAdapter(getPreferences().getBoolean("advanced_muc_mode", false));
111 binding.list.setAdapter(this.userAdapter);
112 }
113
114
115 @Override
116 public void onMucRosterUpdate() {
117 loadAndSubmitUsers();
118 }
119
120 private void displayToast(final String msg) {
121 runOnUiThread(() -> Toast.makeText(this, msg, Toast.LENGTH_SHORT).show());
122 }
123
124 @Override
125 public void onAffiliationChangedSuccessful(Jid jid) {
126
127 }
128
129 @Override
130 public void onAffiliationChangeFailed(Jid jid, int resId) {
131 displayToast(getString(resId, jid.asBareJid().toString()));
132 }
133
134 @Override
135 public boolean onCreateOptionsMenu(final Menu menu) {
136 getMenuInflater().inflate(R.menu.muc_users_activity, menu);
137 final MenuItem menuSearchView = menu.findItem(R.id.action_search);
138 final View mSearchView = menuSearchView.getActionView();
139 mSearchEditText = mSearchView.findViewById(R.id.search_field);
140 mSearchEditText.addTextChangedListener(this);
141 mSearchEditText.setHint(R.string.search_participants);
142 menuSearchView.setOnActionExpandListener(this);
143 return true;
144 }
145
146 @Override
147 public boolean onMenuItemActionExpand(MenuItem item) {
148 mSearchEditText.post(() -> {
149 mSearchEditText.requestFocus();
150 final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
151 imm.showSoftInput(mSearchEditText, InputMethodManager.SHOW_IMPLICIT);
152 });
153 return true;
154 }
155
156 @Override
157 public boolean onMenuItemActionCollapse(MenuItem item) {
158 final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
159 imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
160 mSearchEditText.setText("");
161 submitFilteredList("");
162 return true;
163 }
164
165 @Override
166 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
167
168 }
169
170 @Override
171 public void onTextChanged(CharSequence s, int start, int before, int count) {
172
173 }
174
175 @Override
176 public void afterTextChanged(Editable s) {
177 submitFilteredList(s.toString());
178 }
179}