aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/pixart/messenger/ui
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2019-04-26 23:12:05 +0200
committerChristian Schneppe <christian@pix-art.de>2019-04-26 23:12:22 +0200
commitf9f07063876ec5f3917ce72385b015e1b5f31d7e (patch)
tree093f9ded3021800b20e1e8dcb22d4d8ac17dc7db /src/main/java/de/pixart/messenger/ui
parent35276c6519afa1da6042dd485ddae09b06c68aeb (diff)
implement channel discovery
refactor muc search to use http cache channel search results
Diffstat (limited to 'src/main/java/de/pixart/messenger/ui')
-rw-r--r--src/main/java/de/pixart/messenger/ui/ChannelDiscoveryActivity.java196
-rw-r--r--src/main/java/de/pixart/messenger/ui/StartConversationActivity.java6
-rw-r--r--src/main/java/de/pixart/messenger/ui/adapter/ChannelSearchResultAdapter.java78
3 files changed, 279 insertions, 1 deletions
diff --git a/src/main/java/de/pixart/messenger/ui/ChannelDiscoveryActivity.java b/src/main/java/de/pixart/messenger/ui/ChannelDiscoveryActivity.java
new file mode 100644
index 000000000..e0b70b6ac
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/ChannelDiscoveryActivity.java
@@ -0,0 +1,196 @@
+package de.pixart.messenger.ui;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.databinding.DataBindingUtil;
+import android.os.Bundle;
+import android.support.v7.widget.Toolbar;
+import android.text.Html;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import de.pixart.messenger.R;
+import de.pixart.messenger.databinding.ActivityChannelDiscoveryBinding;
+import de.pixart.messenger.entities.Account;
+import de.pixart.messenger.entities.Conversation;
+import de.pixart.messenger.http.services.MuclumbusService;
+import de.pixart.messenger.services.ChannelDiscoveryService;
+import de.pixart.messenger.ui.adapter.ChannelSearchResultAdapter;
+import de.pixart.messenger.ui.util.PendingItem;
+import de.pixart.messenger.ui.util.SoftKeyboardUtils;
+import de.pixart.messenger.utils.AccountUtils;
+import rocks.xmpp.addr.Jid;
+
+public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.OnActionExpandListener, TextView.OnEditorActionListener, ChannelDiscoveryService.OnChannelSearchResultsFound, ChannelSearchResultAdapter.OnChannelSearchResultSelected {
+ private static final String CHANNEL_DISCOVERY_OPT_IN = "channel_discovery_opt_in";
+ private final ChannelSearchResultAdapter adapter = new ChannelSearchResultAdapter();
+ private ActivityChannelDiscoveryBinding binding;
+ private final PendingItem<String> mInitialSearchValue = new PendingItem<>();
+ private MenuItem mMenuSearchView;
+ private EditText mSearchEditText;
+ private boolean optedIn = false;
+
+ @Override
+ protected void refreshUiReal() {
+
+ }
+
+ @Override
+ void onBackendConnected() {
+ if (optedIn) {
+ String query;
+ if (mMenuSearchView != null && mMenuSearchView.isActionViewExpanded()) {
+ query = mSearchEditText.getText().toString();
+ } else {
+ query = mInitialSearchValue.peek();
+ }
+ xmppConnectionService.discoverChannels(query, this);
+ }
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = DataBindingUtil.setContentView(this, R.layout.activity_channel_discovery);
+ setSupportActionBar((Toolbar) binding.toolbar);
+ configureActionBar(getSupportActionBar(), true);
+ binding.list.setAdapter(this.adapter);
+ this.adapter.setOnChannelSearchResultSelectedListener(this);
+ optedIn = getPreferences().getBoolean(CHANNEL_DISCOVERY_OPT_IN, false);
+
+ final String search = savedInstanceState == null ? null : savedInstanceState.getString("search");
+ if (search != null) {
+ mInitialSearchValue.push(search);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ getMenuInflater().inflate(R.menu.muc_users_activity, menu);
+ mMenuSearchView = menu.findItem(R.id.action_search);
+ final View mSearchView = mMenuSearchView.getActionView();
+ mSearchEditText = mSearchView.findViewById(R.id.search_field);
+ mSearchEditText.setHint(R.string.search_channels);
+ String initialSearchValue = mInitialSearchValue.pop();
+ if (initialSearchValue != null) {
+ mMenuSearchView.expandActionView();
+ mSearchEditText.append(initialSearchValue);
+ mSearchEditText.requestFocus();
+ if (optedIn) {
+ xmppConnectionService.discoverChannels(initialSearchValue, this);
+ }
+ }
+ mSearchEditText.setOnEditorActionListener(this);
+ mMenuSearchView.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("");
+ toggleLoadingScreen();
+ if (optedIn) {
+ xmppConnectionService.discoverChannels(null, this);
+ }
+ return true;
+ }
+
+ private void toggleLoadingScreen() {
+ adapter.submitList(Collections.emptyList());
+ binding.progressBar.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (!optedIn) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.channel_discovery_opt_in_title);
+ builder.setMessage(Html.fromHtml(getString(R.string.channel_discover_opt_in_message)));
+ builder.setNegativeButton(R.string.cancel, (dialog, which) -> finish());
+ builder.setPositiveButton(R.string.confirm, (dialog, which) -> optIn());
+ builder.setOnCancelListener(dialog -> finish());
+ final AlertDialog dialog = builder.create();
+ dialog.setCanceledOnTouchOutside(false);
+ dialog.show();
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ if (mMenuSearchView != null && mMenuSearchView.isActionViewExpanded()) {
+ savedInstanceState.putString("search", mSearchEditText != null ? mSearchEditText.getText().toString() : null);
+ }
+ super.onSaveInstanceState(savedInstanceState);
+ }
+
+ private void optIn() {
+ SharedPreferences preferences = getPreferences();
+ preferences.edit().putBoolean(CHANNEL_DISCOVERY_OPT_IN, true).apply();
+ optedIn = true;
+ xmppConnectionService.discoverChannels(null, this);
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (optedIn) {
+ xmppConnectionService.discoverChannels(v.getText().toString(), this);
+ }
+ toggleLoadingScreen();
+ SoftKeyboardUtils.hideSoftKeyboard(this);
+ return true;
+ }
+
+ @Override
+ public void onChannelSearchResultsFound(List<MuclumbusService.Room> results) {
+ runOnUiThread(() -> {
+ adapter.submitList(results);
+ binding.list.setVisibility(View.VISIBLE);
+ binding.progressBar.setVisibility(View.GONE);
+ });
+ }
+
+ @Override
+ public void onChannelSearchResult(final MuclumbusService.Room result) {
+ List<String> accounts = AccountUtils.getEnabledAccounts(xmppConnectionService);
+ if (accounts.size() == 1) {
+ joinChannelSearchResult(accounts.get(0), result);
+ } else if (accounts.size() > 0) {
+ final AtomicReference<String> account = new AtomicReference<>(accounts.get(0));
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.choose_account);
+ builder.setSingleChoiceItems(accounts.toArray(new CharSequence[0]), 0, (dialog, which) -> account.set(accounts.get(which)));
+ builder.setPositiveButton(R.string.join, (dialog, which) -> joinChannelSearchResult(account.get(), result));
+ builder.setNegativeButton(R.string.cancel, null);
+ builder.create().show();
+ }
+ }
+
+ public void joinChannelSearchResult(String accountJid, MuclumbusService.Room result) {
+ Account account = xmppConnectionService.findAccountByJid(Jid.of(accountJid));
+ final Conversation conversation = xmppConnectionService.findOrCreateConversation(account, result.getRoom(), true, true, true);
+ switchToConversation(conversation);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
index 6706d004c..75e7c2f52 100644
--- a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
@@ -70,6 +70,7 @@ import de.pixart.messenger.ui.interfaces.OnBackendConnected;
import de.pixart.messenger.ui.util.JidDialog;
import de.pixart.messenger.ui.util.PendingItem;
import de.pixart.messenger.ui.util.SoftKeyboardUtils;
+import de.pixart.messenger.utils.AccountUtils;
import de.pixart.messenger.utils.MenuDoubleTabUtil;
import de.pixart.messenger.utils.XmppUri;
import de.pixart.messenger.xmpp.OnUpdateBlocklist;
@@ -307,6 +308,9 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
prefilled = null;
}
switch (actionItem.getId()) {
+ case R.id.discover_public_channels:
+ startActivity(new Intent(this, ChannelDiscoveryActivity.class));
+ break;
case R.id.join_public_channel:
showJoinConferenceDialog(prefilled);
break;
@@ -763,7 +767,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second);
this.mPostponedActivityResult = null;
}
- this.mActivatedAccounts.clear();
+ this.mActivatedAccounts.addAll(AccountUtils.getEnabledAccounts(xmppConnectionService));
for (Account account : xmppConnectionService.getAccounts()) {
if (account.getStatus() != Account.State.DISABLED) {
if (Config.DOMAIN_LOCK != null) {
diff --git a/src/main/java/de/pixart/messenger/ui/adapter/ChannelSearchResultAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/ChannelSearchResultAdapter.java
new file mode 100644
index 000000000..d137e3a6f
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/adapter/ChannelSearchResultAdapter.java
@@ -0,0 +1,78 @@
+package de.pixart.messenger.ui.adapter;
+
+import android.databinding.DataBindingUtil;
+import android.support.annotation.NonNull;
+import android.support.v7.recyclerview.extensions.ListAdapter;
+import android.support.v7.util.DiffUtil;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import de.pixart.messenger.R;
+import de.pixart.messenger.databinding.SearchResultItemBinding;
+import de.pixart.messenger.http.services.MuclumbusService;
+import de.pixart.messenger.ui.util.AvatarWorkerTask;
+
+
+public class ChannelSearchResultAdapter extends ListAdapter<MuclumbusService.Room, ChannelSearchResultAdapter.ViewHolder> {
+
+ private OnChannelSearchResultSelected listener;
+
+ private static final DiffUtil.ItemCallback<MuclumbusService.Room> DIFF = new DiffUtil.ItemCallback<MuclumbusService.Room>() {
+ @Override
+ public boolean areItemsTheSame(@NonNull MuclumbusService.Room a, @NonNull MuclumbusService.Room b) {
+ return a.address != null && a.address.equals(b.address);
+ }
+
+ @Override
+ public boolean areContentsTheSame(@NonNull MuclumbusService.Room a, @NonNull MuclumbusService.Room b) {
+ return a.equals(b);
+ }
+ };
+
+ public ChannelSearchResultAdapter() {
+ super(DIFF);
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
+ return new ViewHolder(DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()), R.layout.search_result_item, viewGroup, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
+ final MuclumbusService.Room searchResult = getItem(position);
+ viewHolder.binding.name.setText(searchResult.getName());
+ final String description = searchResult.getDescription();
+ if (TextUtils.isEmpty(description)) {
+ viewHolder.binding.description.setVisibility(View.GONE);
+ } else {
+ viewHolder.binding.description.setText(description);
+ viewHolder.binding.description.setVisibility(View.VISIBLE);
+ }
+ viewHolder.binding.room.setText(searchResult.getRoom().asBareJid().toString());
+ AvatarWorkerTask.loadAvatar(searchResult, viewHolder.binding.avatar, R.dimen.avatar);
+ viewHolder.binding.getRoot().setOnClickListener(v -> listener.onChannelSearchResult(searchResult));
+ }
+
+ public void setOnChannelSearchResultSelectedListener(OnChannelSearchResultSelected listener) {
+ this.listener = listener;
+ }
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+
+ private final SearchResultItemBinding binding;
+
+ private ViewHolder(SearchResultItemBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
+ }
+
+ public interface OnChannelSearchResultSelected {
+ void onChannelSearchResult(MuclumbusService.Room result);
+ }
+} \ No newline at end of file