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 allUsers.add(mConversation.getMucOptions().getSelf());
66 submitFilteredList(mSearchEditText != null ? mSearchEditText.getText().toString() : null);
67 }
68 }
69
70 private void submitFilteredList(final String search) {
71 if (TextUtils.isEmpty(search)) {
72 userAdapter.submitList(Ordering.natural().immutableSortedCopy(allUsers));
73 } else {
74 final String needle = search.toLowerCase(Locale.getDefault());
75 userAdapter.submitList(
76 Ordering.natural()
77 .immutableSortedCopy(
78 Collections2.filter(
79 this.allUsers,
80 user -> {
81 final String name = user.getName();
82 final Contact contact = user.getContact();
83 return name != null
84 && name.toLowerCase(
85 Locale.getDefault())
86 .contains(needle)
87 || contact != null
88 && contact.getDisplayName()
89 .toLowerCase(
90 Locale.getDefault())
91 .contains(needle);
92 })));
93 }
94 }
95
96 @Override
97 public boolean onContextItemSelected(@NonNull MenuItem item) {
98 if (!MucDetailsContextMenuHelper.onContextItemSelected(item, userAdapter.getSelectedUser(), this)) {
99 return super.onContextItemSelected(item);
100 }
101 return true;
102 }
103
104 @Override
105 protected void onCreate(final Bundle savedInstanceState) {
106 super.onCreate(savedInstanceState);
107 final ActivityMucUsersBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_muc_users);
108 setSupportActionBar(binding.toolbar);
109 Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
110 configureActionBar(getSupportActionBar(), true);
111 this.userAdapter = new UserAdapter(getPreferences().getBoolean("advanced_muc_mode", false));
112 binding.list.setAdapter(this.userAdapter);
113 }
114
115
116 @Override
117 public void onMucRosterUpdate() {
118 loadAndSubmitUsers();
119 }
120
121 private void displayToast(final String msg) {
122 runOnUiThread(() -> Toast.makeText(this, msg, Toast.LENGTH_SHORT).show());
123 }
124
125 @Override
126 public void onAffiliationChangedSuccessful(Jid jid) {
127
128 }
129
130 @Override
131 public void onAffiliationChangeFailed(Jid jid, int resId) {
132 displayToast(getString(resId, jid.asBareJid().toString()));
133 }
134
135 @Override
136 public boolean onCreateOptionsMenu(final Menu menu) {
137 getMenuInflater().inflate(R.menu.muc_users_activity, menu);
138 final MenuItem menuSearchView = menu.findItem(R.id.action_search);
139 final View mSearchView = menuSearchView.getActionView();
140 mSearchEditText = mSearchView.findViewById(R.id.search_field);
141 mSearchEditText.addTextChangedListener(this);
142 mSearchEditText.setHint(R.string.search_participants);
143 menuSearchView.setOnActionExpandListener(this);
144 return true;
145 }
146
147 @Override
148 public boolean onMenuItemActionExpand(MenuItem item) {
149 mSearchEditText.post(() -> {
150 mSearchEditText.requestFocus();
151 final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
152 imm.showSoftInput(mSearchEditText, InputMethodManager.SHOW_IMPLICIT);
153 });
154 return true;
155 }
156
157 @Override
158 public boolean onMenuItemActionCollapse(MenuItem item) {
159 final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
160 imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
161 mSearchEditText.setText("");
162 submitFilteredList("");
163 return true;
164 }
165
166 @Override
167 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
168
169 }
170
171 @Override
172 public void onTextChanged(CharSequence s, int start, int before, int count) {
173
174 }
175
176 @Override
177 public void afterTextChanged(Editable s) {
178 submitFilteredList(s.toString());
179 }
180}