aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2018-02-03 23:41:07 +0100
committerChristian Schneppe <christian@pix-art.de>2018-02-04 00:02:27 +0100
commitbc4d112060cbe822bef0dda8d5104db725deeb1b (patch)
treef719786139b729892cf67d103b1922ea48cad279 /src/main/java
parent282612a0612fac5eb9ced648b3d8969bff85c90c (diff)
implemented message search
fixes #110
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationActivity.java12
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationFragment.java161
2 files changed, 171 insertions, 2 deletions
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationActivity.java b/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
index 274b51d8a..36940359d 100644
--- a/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
@@ -59,7 +59,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import de.pixart.messenger.BuildConfig;
import de.pixart.messenger.Config;
import de.pixart.messenger.R;
import de.pixart.messenger.crypto.axolotl.AxolotlService;
@@ -168,6 +167,7 @@ public class ConversationActivity extends XmppActivity
public void showConversationsOverview() {
if (mConversationFragment != null) {
mConversationFragment.stopScrolling();
+ mConversationFragment.hideSearchField();
}
if (mContentView instanceof SlidingPaneLayout) {
SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
@@ -291,6 +291,7 @@ public class ConversationActivity extends XmppActivity
xmppConnectionService.getNotificationService().setOpenConversation(null);
}
closeContextMenu();
+ mConversationFragment.hideSearchField();
}
@Override
@@ -475,6 +476,7 @@ public class ConversationActivity extends XmppActivity
final MenuItem menuInviteContact = menu.findItem(R.id.action_invite);
final MenuItem menuUpdater = menu.findItem(R.id.action_check_updates);
final MenuItem menuInviteUser = menu.findItem(R.id.action_invite_user);
+ final MenuItem menuSearchHistory = menu.findItem(R.id.action_search_history);
if (isConversationsOverviewVisable() && isConversationsOverviewHideable()) {
menuArchiveChat.setVisible(false);
@@ -483,6 +485,7 @@ public class ConversationActivity extends XmppActivity
menuInviteContact.setVisible(false);
menuAttach.setVisible(false);
menuClearHistory.setVisible(false);
+ menuSearchHistory.setVisible(false);
if (xmppConnectionService.installedFromFDroid()) {
menuUpdater.setVisible(false);
} else {
@@ -835,6 +838,9 @@ public class ConversationActivity extends XmppActivity
case R.id.action_unblock:
BlockContactDialog.show(this, getSelectedConversation());
break;
+ case R.id.action_search_history:
+ mConversationFragment.showSearchField();
+ break;
default:
break;
}
@@ -1067,7 +1073,9 @@ public class ConversationActivity extends XmppActivity
@Override
public void onBackPressed() {
- if (!isConversationsOverviewVisable()) {
+ if (!isConversationsOverviewVisable() && mConversationFragment.isSearchFieldVisible()) {
+ mConversationFragment.hideSearchField();
+ } else if (!isConversationsOverviewVisable()) {
showConversationsOverview();
} else {
super.onBackPressed();
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
index d62192170..b97dda837 100644
--- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
+++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
@@ -16,6 +16,7 @@ import android.support.v13.view.inputmethod.InputConnectionCompat;
import android.support.v13.view.inputmethod.InputContentInfoCompat;
import android.text.Editable;
import android.text.InputType;
+import android.text.TextWatcher;
import android.util.Log;
import android.util.Pair;
import android.view.ContextMenu;
@@ -34,6 +35,7 @@ import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.PopupMenu;
@@ -93,11 +95,17 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
protected Conversation conversation;
protected ListView messagesView;
protected MessageAdapter messageListAdapter;
+ protected Message lastHistoryMessage = null;
private EditMessage mEditMessage;
private ImageButton mSendButton;
private RelativeLayout snackbar;
private RelativeLayout messagehint;
private TextView messagehint_message;
+ private RelativeLayout textsend;
+ private RelativeLayout searchfield;
+ private EditText searchfield_input;
+ private ImageButton searchUp;
+ private ImageButton searchDown;
private TextView snackbarMessage;
private TextView snackbarAction;
private Toast messageLoaderToast;
@@ -596,6 +604,13 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
messagehint = view.findViewById(R.id.messagehint);
messagehint_message = view.findViewById(R.id.messagehint_message);
+ textsend = view.findViewById(R.id.textsend);
+
+ searchfield = view.findViewById(R.id.searchfield);
+ searchfield_input = view.findViewById(R.id.searchfield_input);
+ searchUp = view.findViewById(R.id.search_up);
+ searchDown = view.findViewById(R.id.search_down);
+
messagesView = view.findViewById(R.id.messages_view);
messagesView.setOnScrollListener(mOnScrollListener);
messagesView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
@@ -1531,6 +1546,79 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
messagehint.setVisibility(View.GONE);
}
+ protected void showSearchField() {
+ textsend.setVisibility(View.GONE);
+ searchfield.setVisibility(View.VISIBLE);
+ searchfield_input.addTextChangedListener(mSearchTextWatcher);
+ searchfield_input.requestFocus();
+ final InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ imm.showSoftInput(searchfield_input, InputMethodManager.SHOW_IMPLICIT);
+ }
+ }
+
+ protected void hideSearchField() {
+ textsend.setVisibility(View.VISIBLE);
+ searchfield.setVisibility(View.GONE);
+ if (activity != null) {
+ final InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ imm.hideSoftInputFromWindow(searchfield_input.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
+ }
+ }
+ searchfield_input.setText("");
+ }
+
+ protected boolean isSearchFieldVisible() {
+ return searchfield.getVisibility() == View.VISIBLE;
+ }
+
+ private TextWatcher mSearchTextWatcher = new TextWatcher() {
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String query = editable.toString().trim();
+
+ if ((!query.isEmpty() || !query.contains("")) && query.length() >= 3) {
+ searchUp.setVisibility(View.VISIBLE);
+ searchDown.setVisibility(View.VISIBLE);
+ Message found = searchHistory(query);
+ if (found != null) {
+ searchUp.setVisibility(View.VISIBLE);
+ searchDown.setVisibility(View.VISIBLE);
+ } else {
+ searchUp.setVisibility(View.GONE);
+ searchDown.setVisibility(View.GONE);
+ }
+ searchUp.setEnabled(found != null);
+ searchDown.setEnabled(found != null);
+ View.OnClickListener upDownListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String searchQuery = searchfield_input.getText().toString().trim();
+ if (!searchQuery.isEmpty() || !searchQuery.contains("")) {
+ searchHistory(searchQuery, view.getId() == R.id.search_up);
+ }
+
+ }
+ };
+ searchUp.setOnClickListener(upDownListener);
+ searchDown.setOnClickListener(upDownListener);
+ } else {
+ searchUp.setVisibility(View.GONE);
+ searchDown.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ };
+
protected void sendPlainTextMessage(Message message) {
ConversationActivity activity = (ConversationActivity) getActivity();
activity.xmppConnectionService.sendMessage(message);
@@ -1788,6 +1876,79 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
}
+ public Message searchHistory(String query) {
+ return searchHistory(query, null);
+ }
+
+ public Message searchHistory(String query, Boolean ascendingSearch) {
+ return searchHistory(query, lastHistoryMessage, ascendingSearch);
+ }
+
+ /**
+ * Search through history from message basis either ascending or descending
+ *
+ * @param query search term
+ * @param basis message to start from. If null, start from last recent message
+ * @param ascendingSearch do we want to ascend or descend in our search?
+ * If this is null, ascend to first match and return.
+ * @return match or null
+ */
+ public Message searchHistory(String query, Message basis, Boolean ascendingSearch) {
+ int entryIndex;
+ Message message;
+ lastHistoryMessage = basis;
+ if (messageList.size() == 0) {
+ return null;
+ }
+ if (basis == null) {
+ entryIndex = messageList.size() - 1;
+ } else {
+ int in = getIndexOf(basis.getUuid(), messageList);
+ entryIndex = (in != -1 ? in : messageList.size() - 1);
+ }
+
+ int firstMatchIndex = entryIndex;
+ boolean entryIndexWasMatch = true;
+ do {
+ message = messageList.get(firstMatchIndex);
+ if (message.getType() == Message.TYPE_TEXT && messageContainsQuery(message, query)) {
+ lastHistoryMessage = message;
+ break;
+ }
+ entryIndexWasMatch = false;
+ firstMatchIndex = (messageList.size() + firstMatchIndex - 1) % messageList.size();
+ } while (entryIndex != firstMatchIndex);
+
+ if (!entryIndexWasMatch && entryIndex == firstMatchIndex) {
+ //No matches
+ return null;
+ }
+
+ if (ascendingSearch != null) {
+ int direction = ascendingSearch ? -1 : 1;
+ int nextMatchIndex = firstMatchIndex;
+ do {
+ nextMatchIndex = (messageList.size() + nextMatchIndex + direction) % messageList.size();
+ message = messageList.get(nextMatchIndex);
+ if (message.getType() == Message.TYPE_TEXT && messageContainsQuery(message, query)) {
+ lastHistoryMessage = message;
+ break;
+ }
+ } while (nextMatchIndex != entryIndex);
+ }
+
+ if (lastHistoryMessage != null) {
+ int pos = getIndexOf(lastHistoryMessage.getUuid(), messageList);
+ setScrollPosition(new Pair<>(pos, pos));
+ messagesView.setSelection(pos);
+ }
+ return lastHistoryMessage;
+ }
+
+ private boolean messageContainsQuery(Message m, String q) {
+ return m != null && m.getMergedBody().toString().toLowerCase().contains(q.toLowerCase());
+ }
+
enum SendButtonAction {
TEXT, TAKE_FROM_CAMERA, SEND_LOCATION, RECORD_VOICE, CANCEL, CHOOSE_PICTURE;