mock (non functional) search activity

Daniel Gultsch created

Change summary

art/ic_search_black.svg                                                    |  54 
art/ic_search_white.svg                                                    |  54 
art/render.rb                                                              |   2 
src/main/AndroidManifest.xml                                               |   3 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java          |   9 
src/main/java/eu/siacs/conversations/ui/ConversationsOverviewFragment.java |  31 
src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java           |   3 
src/main/java/eu/siacs/conversations/ui/SearchActivity.java                | 114 
src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java     |   7 
src/main/java/eu/siacs/conversations/ui/XmppActivity.java                  |   7 
src/main/java/eu/siacs/conversations/ui/util/SoftKeyboardUtils.java        |  61 
src/main/res/drawable-hdpi/ic_search_background_black.png                  |   0 
src/main/res/drawable-hdpi/ic_search_background_white.png                  |   0 
src/main/res/drawable-mdpi/ic_search_background_black.png                  |   0 
src/main/res/drawable-mdpi/ic_search_background_white.png                  |   0 
src/main/res/drawable-xhdpi/ic_search_background_black.png                 |   0 
src/main/res/drawable-xhdpi/ic_search_background_white.png                 |   0 
src/main/res/drawable-xxhdpi/ic_search_background_black.png                |   0 
src/main/res/drawable-xxhdpi/ic_search_background_white.png                |   0 
src/main/res/drawable-xxxhdpi/ic_search_background_black.png               |   0 
src/main/res/drawable-xxxhdpi/ic_search_background_white.png               |   0 
src/main/res/drawable/search_background_dark.xml                           |  41 
src/main/res/drawable/search_background_light.xml                          |  41 
src/main/res/drawable/white_cursor.xml                                     |  33 
src/main/res/layout/activity_search.xml                                    |   2 
src/main/res/menu/activity_conversations.xml                               |   1 
src/main/res/menu/activity_search.xml                                      |  40 
src/main/res/menu/fragment_conversations_overview.xml                      |  37 
src/main/res/values/attrs.xml                                              |   2 
src/main/res/values/colors.xml                                             |   1 
src/main/res/values/strings.xml                                            |   2 
src/main/res/values/styles.xml                                             |   1 
src/main/res/values/themes.xml                                             |   3 
33 files changed, 528 insertions(+), 21 deletions(-)

Detailed changes

art/ic_search_black.svg πŸ”—

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48"
+   height="48"
+   viewBox="0 0 48 48"
+   version="1.1"
+   id="svg4"
+   sodipodi:docname="ic_search_black.svg"
+   inkscape:version="0.92.2 2405546, 2018-03-11">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs8" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="956"
+     inkscape:window-height="567"
+     id="namedview6"
+     showgrid="false"
+     inkscape:zoom="4.9166667"
+     inkscape:cx="-13.118644"
+     inkscape:cy="24"
+     inkscape:window-x="2880"
+     inkscape:window-y="609"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg4" />
+  <path
+     d="M31 28h-1.59l-.55-.55C30.82 25.18 32 22.23 32 19c0-7.18-5.82-13-13-13S6 11.82 6 19s5.82 13 13 13c3.23 0 6.18-1.18 8.45-3.13l.55.55V31l10 9.98L40.98 38 31 28zm-12 0c-4.97 0-9-4.03-9-9s4.03-9 9-9 9 4.03 9 9-4.03 9-9 9z"
+     id="path2"
+     style="fill:#000000;fill-opacity:1" />
+</svg>

art/ic_search_white.svg πŸ”—

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48"
+   height="48"
+   viewBox="0 0 48 48"
+   version="1.1"
+   id="svg4"
+   sodipodi:docname="ic_search_white.svg"
+   inkscape:version="0.92.2 2405546, 2018-03-11">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs8" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1200"
+     id="namedview6"
+     showgrid="false"
+     inkscape:zoom="4.9166667"
+     inkscape:cx="-10.474576"
+     inkscape:cy="22.169492"
+     inkscape:window-x="1920"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg4" />
+  <path
+     d="M31 28h-1.59l-.55-.55C30.82 25.18 32 22.23 32 19c0-7.18-5.82-13-13-13S6 11.82 6 19s5.82 13 13 13c3.23 0 6.18-1.18 8.45-3.13l.55.55V31l10 9.98L40.98 38 31 28zm-12 0c-4.97 0-9-4.03-9-9s4.03-9 9-9 9 4.03 9 9-4.03 9-9 9z"
+     id="path2"
+     style="fill:#ffffff;fill-opacity:0.99570817" />
+</svg>

art/render.rb πŸ”—

@@ -14,6 +14,8 @@ images = {
 	'ic_launcher.svg' => ['ic_launcher', 48],
 	'main_logo.svg' => ['main_logo', 200],
     'main_logo.svg' => ['splash_logo', 144],
+    'ic_search_black.svg' => ['ic_search_background_black', 144],
+    'ic_search_white.svg' => ['ic_search_background_white', 144],
 	'play_video.svg' => ['play_video', 128],
 	'play_gif.svg' => ['play_gif', 128],
 	'conversations_mono.svg' => ['ic_notification', 24],

src/main/AndroidManifest.xml πŸ”—

@@ -60,6 +60,9 @@
         <activity
             android:name=".ui.ShareLocationActivity"
             android:label="@string/title_activity_share_location"/>
+        <activity
+            android:name=".ui.SearchActivity"
+            android:label="@string/title_activity_search"/>
         <activity
             android:name=".ui.RecordingActivity"
             android:theme="@style/ConversationsTheme.Dialog"

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java πŸ”—

@@ -105,6 +105,7 @@ import rocks.xmpp.addr.Jid;
 
 import static eu.siacs.conversations.ui.XmppActivity.EXTRA_ACCOUNT;
 import static eu.siacs.conversations.ui.XmppActivity.REQUEST_INVITE_TO_CONVERSATION;
+import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.hideSoftKeyboard;
 
 
 public class ConversationFragment extends XmppFragment implements EditMessage.KeyboardListener {
@@ -502,14 +503,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 		return null;
 	}
 
-	private static void hideSoftKeyboard(final Activity activity) {
-		InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
-		View view = activity.getCurrentFocus();
-		if (view != null && imm != null) {
-			imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
-		}
-	}
-
 	private static boolean scrolledToBottom(AbsListView listView) {
 		final int count = listView.getCount();
 		if (count == 0) {

src/main/java/eu/siacs/conversations/ui/ConversationsOverviewFragment.java πŸ”—

@@ -31,6 +31,7 @@ package eu.siacs.conversations.ui;
 
 import android.app.Activity;
 import android.app.Fragment;
+import android.content.Intent;
 import android.databinding.DataBindingUtil;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -41,6 +42,9 @@ import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.helper.ItemTouchHelper;
 import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -55,6 +59,7 @@ import eu.siacs.conversations.ui.adapter.ConversationAdapter;
 import eu.siacs.conversations.ui.interfaces.OnConversationArchived;
 import eu.siacs.conversations.ui.interfaces.OnConversationSelected;
 import eu.siacs.conversations.ui.util.Color;
+import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
 import eu.siacs.conversations.ui.util.PendingActionHelper;
 import eu.siacs.conversations.ui.util.PendingItem;
 import eu.siacs.conversations.ui.util.ScrollState;
@@ -235,11 +240,15 @@ public class ConversationsOverviewFragment extends XmppFragment {
 		this.activity = null;
 	}
 
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setHasOptionsMenu(true);
+	}
+
 	@Override
 	public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-		Log.d(Config.LOGTAG, "onCreateView");
 		this.mSwipeEscapeVelocity = getResources().getDimension(R.dimen.swipe_escape_velocity);
-		Log.d(Config.LOGTAG,"swipe escape velocity: "+this.mSwipeEscapeVelocity);
 		this.binding = DataBindingUtil.inflate(inflater, R.layout.fragment_conversations_overview, container, false);
 		this.binding.fab.setOnClickListener((view) -> StartConversationActivity.launch(getActivity()));
 
@@ -257,6 +266,11 @@ public class ConversationsOverviewFragment extends XmppFragment {
 		return binding.getRoot();
 	}
 
+	@Override
+	public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
+		menuInflater.inflate(R.menu.fragment_conversations_overview, menu);
+	}
+
 	@Override
 	public void onBackendConnected() {
 		refresh();
@@ -300,6 +314,19 @@ public class ConversationsOverviewFragment extends XmppFragment {
 		Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onResume()");
 	}
 
+	@Override
+	public boolean onOptionsItemSelected(final MenuItem item) {
+		if (MenuDoubleTabUtil.shouldIgnoreTap()) {
+			return false;
+		}
+		switch (item.getItemId()) {
+			case R.id.action_search:
+				startActivity(new Intent(getActivity(), SearchActivity.class));
+				return true;
+		}
+		return super.onOptionsItemSelected(item);
+	}
+
 	@Override
 	void refresh() {
 		if (this.binding == null || this.activity == null) {

src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java πŸ”—

@@ -64,6 +64,7 @@ import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
 import eu.siacs.conversations.ui.adapter.PresenceTemplateAdapter;
 import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
 import eu.siacs.conversations.ui.util.PendingItem;
+import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
 import eu.siacs.conversations.utils.CryptoHelper;
 import eu.siacs.conversations.utils.UIHelper;
 import eu.siacs.conversations.utils.XmppUri;
@@ -389,7 +390,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
 
 	protected void finishInitialSetup(final Avatar avatar) {
 		runOnUiThread(() -> {
-			hideKeyboard();
+			SoftKeyboardUtils.hideSoftKeyboard(EditAccountActivity.this);
 			final Intent intent;
 			final XmppConnection connection = mAccount.getXmppConnection();
 			final boolean wasFirstAccount = xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1;

src/main/java/eu/siacs/conversations/ui/SearchActivity.java πŸ”—

@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package eu.siacs.conversations.ui;
+
+import android.databinding.DataBindingUtil;
+import android.os.Bundle;
+import android.support.v7.widget.Toolbar;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.EditText;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.databinding.ActivitySearchBinding;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.ui.adapter.MessageAdapter;
+
+import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.hideSoftKeyboard;
+import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.showKeyboard;
+
+public class SearchActivity extends XmppActivity implements TextWatcher {
+
+	private ActivitySearchBinding binding;
+	private MessageAdapter messageListAdapter;
+	private final List<Message> messages = new ArrayList<>();
+
+	@Override
+	public void onCreate(final Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		this.binding = DataBindingUtil.setContentView(this, R.layout.activity_search);
+		setSupportActionBar((Toolbar) this.binding.toolbar);
+		configureActionBar(getSupportActionBar());
+		this.messageListAdapter = new MessageAdapter(this, this.messages);
+		this.binding.searchResults.setAdapter(messageListAdapter);
+	}
+
+	@Override
+	public boolean onCreateOptionsMenu(final Menu menu) {
+		getMenuInflater().inflate(R.menu.activity_search, menu);
+		MenuItem searchActionMenuItem = menu.findItem(R.id.action_search);
+		EditText searchField = searchActionMenuItem.getActionView().findViewById(R.id.search_field);
+		searchField.addTextChangedListener(this);
+		searchField.setHint(R.string.search_messages);
+		showKeyboard(searchField);
+		return super.onCreateOptionsMenu(menu);
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		if (item.getItemId() == android.R.id.home) {
+			hideSoftKeyboard(this);
+		}
+		return super.onOptionsItemSelected(item);
+	}
+
+	@Override
+	protected void refreshUiReal() {
+
+	}
+
+	@Override
+	void onBackendConnected() {
+
+	}
+
+	@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) {
+		Log.d(Config.LOGTAG,"searching for "+s);
+	}
+
+}

src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java πŸ”—

@@ -72,6 +72,7 @@ import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
 import eu.siacs.conversations.ui.service.EmojiService;
 import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
 import eu.siacs.conversations.ui.util.PendingItem;
+import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
 import eu.siacs.conversations.utils.XmppUri;
 import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
 import eu.siacs.conversations.xmpp.XmppConnection;
@@ -116,7 +117,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
 
 		@Override
 		public boolean onMenuItemActionCollapse(MenuItem item) {
-			hideKeyboard();
+			SoftKeyboardUtils.hideSoftKeyboard(StartConversationActivity.this);
 			mSearchEditText.setText("");
 			filter(null);
 			return true;
@@ -186,7 +187,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
 					return true;
 				}
 			}
-			hideKeyboard();
+			SoftKeyboardUtils.hideSoftKeyboard(StartConversationActivity.this);
 			mListPagerAdapter.requestFocus(pos);
 			return true;
 		}
@@ -343,6 +344,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
 
 	protected void openConversationForContact(Contact contact) {
 		Conversation conversation = xmppConnectionService.findOrCreateConversation(contact.getAccount(), contact.getJid(), false, true);
+		SoftKeyboardUtils.hideSoftKeyboard(this);
 		switchToConversation(conversation);
 	}
 
@@ -384,6 +386,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
 			bookmark.setAutojoin(true);
 			xmppConnectionService.pushBookmarks(bookmark.getAccount());
 		}
+		SoftKeyboardUtils.hideSoftKeyboard(this);
 		switchToConversation(conversation);
 	}
 

src/main/java/eu/siacs/conversations/ui/XmppActivity.java πŸ”—

@@ -248,13 +248,6 @@ public abstract class XmppActivity extends ActionBarActivity {
 		}
 	}
 
-	protected void hideKeyboard() {
-		final InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
-		View focus = getCurrentFocus();
-		if (focus != null && inputManager != null) {
-			inputManager.hideSoftInputFromWindow(focus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
-		}
-	}
 
 	public boolean hasPgp() {
 		return xmppConnectionService.getPgpEngine() != null;

src/main/java/eu/siacs/conversations/ui/util/SoftKeyboardUtils.java πŸ”—

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package eu.siacs.conversations.ui.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+
+
+
+public class SoftKeyboardUtils {
+
+	public static void hideSoftKeyboard(final Activity activity) {
+		InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
+		if (imm == null) {
+			return;
+		}
+		View view = activity.getCurrentFocus();
+		if (view == null) {
+			view = new View(activity);
+		}
+		imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+	}
+
+	public static void showKeyboard(EditText editText) {
+		editText.requestFocus();
+		InputMethodManager inputMethodManager = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+		if (inputMethodManager != null) {
+			inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
+		}
+	}
+}

src/main/res/drawable/search_background_dark.xml πŸ”—

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (c) 2018, Daniel Gultsch All rights reserved.
+  ~
+  ~ Redistribution and use in source and binary forms, with or without modification,
+  ~ are permitted provided that the following conditions are met:
+  ~
+  ~ 1. Redistributions of source code must retain the above copyright notice, this
+  ~ list of conditions and the following disclaimer.
+  ~
+  ~ 2. Redistributions in binary form must reproduce the above copyright notice,
+  ~ this list of conditions and the following disclaimer in the documentation and/or
+  ~ other materials provided with the distribution.
+  ~
+  ~ 3. Neither the name of the copyright holder nor the names of its contributors
+  ~ may be used to endorse or promote products derived from this software without
+  ~ specific prior written permission.
+  ~
+  ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+  ~ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  ~ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  ~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+  ~ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  ~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ~ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+  ~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  ~ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  ~ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@color/grey800"/>
+
+    <item>
+        <bitmap
+            android:alpha="0.12"
+            android:gravity="center"
+            android:src="@drawable/ic_search_background_white"/>
+    </item>
+</layer-list>

src/main/res/drawable/search_background_light.xml πŸ”—

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (c) 2018, Daniel Gultsch All rights reserved.
+  ~
+  ~ Redistribution and use in source and binary forms, with or without modification,
+  ~ are permitted provided that the following conditions are met:
+  ~
+  ~ 1. Redistributions of source code must retain the above copyright notice, this
+  ~ list of conditions and the following disclaimer.
+  ~
+  ~ 2. Redistributions in binary form must reproduce the above copyright notice,
+  ~ this list of conditions and the following disclaimer in the documentation and/or
+  ~ other materials provided with the distribution.
+  ~
+  ~ 3. Neither the name of the copyright holder nor the names of its contributors
+  ~ may be used to endorse or promote products derived from this software without
+  ~ specific prior written permission.
+  ~
+  ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+  ~ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  ~ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  ~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+  ~ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  ~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ~ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+  ~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  ~ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  ~ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@color/grey50"/>
+
+    <item>
+        <bitmap
+            android:alpha="0.12"
+            android:gravity="center"
+            android:src="@drawable/ic_search_background_black"/>
+    </item>
+</layer-list>

src/main/res/drawable/white_cursor.xml πŸ”—

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (c) 2018, Daniel Gultsch All rights reserved.
+  ~
+  ~ Redistribution and use in source and binary forms, with or without modification,
+  ~ are permitted provided that the following conditions are met:
+  ~
+  ~ 1. Redistributions of source code must retain the above copyright notice, this
+  ~ list of conditions and the following disclaimer.
+  ~
+  ~ 2. Redistributions in binary form must reproduce the above copyright notice,
+  ~ this list of conditions and the following disclaimer in the documentation and/or
+  ~ other materials provided with the distribution.
+  ~
+  ~ 3. Neither the name of the copyright holder nor the names of its contributors
+  ~ may be used to endorse or promote products derived from this software without
+  ~ specific prior written permission.
+  ~
+  ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+  ~ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  ~ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  ~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+  ~ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  ~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ~ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+  ~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  ~ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  ~ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+    <size android:width="1.75dp"/>
+    <solid android:color="@color/white87"  />
+</shape>

src/main/res/layout/activity_search.xml πŸ”—

@@ -44,7 +44,7 @@
             android:id="@+id/search_results"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:background="?attr/color_background_secondary"
+            android:background="?attr/activity_background_search"
             android:divider="@android:color/transparent"
             android:dividerHeight="0dp"/>
     </LinearLayout>

src/main/res/menu/activity_conversations.xml πŸ”—

@@ -4,6 +4,7 @@
         android:id="@+id/action_scan_qr_code"
         android:title="@string/scan_qr_code"
         app:showAsAction="always"
+        android:orderInCategory="10"
         android:visible="@bool/show_qr_code_scan"
         android:icon="?attr/icon_scan_qr_code"/>
     <item

src/main/res/menu/activity_search.xml πŸ”—

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (c) 2018, Daniel Gultsch All rights reserved.
+  ~
+  ~ Redistribution and use in source and binary forms, with or without modification,
+  ~ are permitted provided that the following conditions are met:
+  ~
+  ~ 1. Redistributions of source code must retain the above copyright notice, this
+  ~ list of conditions and the following disclaimer.
+  ~
+  ~ 2. Redistributions in binary form must reproduce the above copyright notice,
+  ~ this list of conditions and the following disclaimer in the documentation and/or
+  ~ other materials provided with the distribution.
+  ~
+  ~ 3. Neither the name of the copyright holder nor the names of its contributors
+  ~ may be used to endorse or promote products derived from this software without
+  ~ specific prior written permission.
+  ~
+  ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+  ~ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  ~ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  ~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+  ~ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  ~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ~ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+  ~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  ~ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  ~ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  -->
+
+<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"
+        android:icon="?attr/icon_search"
+        android:title="@string/search"
+        app:actionLayout="@layout/actionview_search"
+        app:showAsAction="always"/>
+</menu>

src/main/res/menu/fragment_conversations_overview.xml πŸ”—

@@ -0,0 +1,37 @@
+<!--
+  ~ Copyright (c) 2018, Daniel Gultsch All rights reserved.
+  ~
+  ~ Redistribution and use in source and binary forms, with or without modification,
+  ~ are permitted provided that the following conditions are met:
+  ~
+  ~ 1. Redistributions of source code must retain the above copyright notice, this
+  ~ list of conditions and the following disclaimer.
+  ~
+  ~ 2. Redistributions in binary form must reproduce the above copyright notice,
+  ~ this list of conditions and the following disclaimer in the documentation and/or
+  ~ other materials provided with the distribution.
+  ~
+  ~ 3. Neither the name of the copyright holder nor the names of its contributors
+  ~ may be used to endorse or promote products derived from this software without
+  ~ specific prior written permission.
+  ~
+  ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+  ~ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  ~ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  ~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+  ~ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  ~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ~ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+  ~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  ~ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  ~ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  -->
+
+<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"
+        android:title="@string/title_activity_search"
+        android:orderInCategory="50"
+        app:showAsAction="never"/>
+</menu>

src/main/res/values/attrs.xml πŸ”—

@@ -17,6 +17,8 @@
     <attr name="color_warning" format="reference|color"/>
     <attr name="EmojiColor" format="reference|color"/>
 
+    <attr name="activity_background_search" format="reference"/>
+
     <attr name="ic_send_cancel_offline" format="reference"/>
     <attr name="ic_send_location_offline" format="reference"/>
     <attr name="ic_send_photo_offline" format="reference"/>

src/main/res/values/colors.xml πŸ”—

@@ -11,6 +11,7 @@
 	<color name="black26">#42000000</color>
 	<color name="black12">#1f000000</color>
 	<color name="white">#ffffffff</color>
+	<color name="white87">#deffffff</color>
 	<color name="white70">#b2ffffff</color>
 	<color name="white12">#1fffffff</color>
 	<color name="grey50">#fffafafa</color>

src/main/res/values/strings.xml πŸ”—

@@ -703,4 +703,6 @@
     <string name="unable_to_start_recording">Unable to start recording</string>
     <string name="please_wait">Please wait…</string>
     <string name="no_microphone_permission">Conversations needs access to the microphone</string>
+    <string name="title_activity_search">Search</string>
+    <string name="search_messages">Search messages</string>
 </resources>

src/main/res/values/styles.xml πŸ”—

@@ -36,6 +36,7 @@
         <item name="android:textColorHint">@color/white70</item>
         <item name="android:background">@android:color/transparent</item>
         <item name="android:textSize">18sp</item>
+        <item name="android:textCursorDrawable">@drawable/white_cursor</item>
     </style>
 
     <style name="Widget.Conversations.CheckBox" parent="Widget.AppCompat.CompoundButton.CheckBox">

src/main/res/values/themes.xml πŸ”—

@@ -11,6 +11,8 @@
         <item name="color_background_secondary">@color/grey200</item>
         <item name="color_warning">@color/red_a700</item>
 
+        <item name="activity_background_search">@drawable/search_background_light</item>
+
         <item name="EmojiColor">@color/black</item>
 
         <item name="windowActionModeOverlay">true</item>
@@ -99,6 +101,7 @@
 
         <item name="color_background_primary">@color/grey800</item>
         <item name="color_background_secondary">@color/grey900</item>
+        <item name="activity_background_search">@drawable/search_background_dark</item>
         <item name="color_warning">@color/red_a100</item>
 
         <item name="EmojiColor">@color/white</item>