From a32250fe3443cbf67f0fae5d8bd2f644572270c9 Mon Sep 17 00:00:00 2001 From: "MINIPC\\frivaong" Date: Sat, 26 Sep 2026 05:36:08 +0900 Subject: [PATCH] Messaging: Looply search hub with frequent contacts and nav inset Redesign Search around frequent contacts, category counts, and recent chips, and keep the Messages/Automation pill on the left guideline without moving compose. Co-authored-by: Cursor --- .../ConversationListFragment.java | 19 + .../messaging/ui/home/HomeSearchActivity.java | 303 ++++++++++++- .../ui/home/HomeSearchHistoryStore.java | 69 +++ .../messaging/ui/home/HomeSubHeader.java | 11 + .../ui/home/StarredMessagesStore.java | 4 + .../main/res/drawable/home_bg_search_card.xml | 10 + .../res/layout/conversation_list_fragment.xml | 9 + .../main/res/layout/home_search_activity.xml | 418 ++++++++++++------ .../res/layout/home_search_filter_item.xml | 21 +- .../res/layout/home_search_frequent_item.xml | 32 ++ app/src/main/res/layout/home_sub_header.xml | 14 + app/src/main/res/values/looply_dimens.xml | 5 +- app/src/main/res/values/looply_strings.xml | 10 +- 13 files changed, 762 insertions(+), 163 deletions(-) create mode 100644 app/src/main/java/com/android/messaging/ui/home/HomeSearchHistoryStore.java create mode 100644 app/src/main/res/drawable/home_bg_search_card.xml create mode 100644 app/src/main/res/layout/home_search_frequent_item.xml diff --git a/app/src/main/java/com/android/messaging/ui/conversationlist/ConversationListFragment.java b/app/src/main/java/com/android/messaging/ui/conversationlist/ConversationListFragment.java index e00ca00..ed921a8 100644 --- a/app/src/main/java/com/android/messaging/ui/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/com/android/messaging/ui/conversationlist/ConversationListFragment.java @@ -138,6 +138,7 @@ public class ConversationListFragment extends Fragment implements ConversationLi private TextView mHomeEditButton; private ImageButton mHomePinnedDoneButton; private boolean mHomePinnedEditMode; + private View mHomeNavDock; private View mHomeNavMessages; private View mHomeNavAutomate; private View mHomeNavTabGap; @@ -389,6 +390,7 @@ public class ConversationListFragment extends Fragment implements ConversationLi mHomeMessagesTop = rootView.findViewById(R.id.home_messages_top); mHomeTitle = rootView.findViewById(R.id.home_title); mHomeAutomationPane = rootView.findViewById(R.id.home_automation_pane); + mHomeNavDock = rootView.findViewById(R.id.home_nav_dock); mHomeNavMessages = rootView.findViewById(R.id.home_nav_messages); bindHomeNavTab(mHomeNavMessages, R.drawable.ic_home_nav_messages, R.string.home_nav_messages); @@ -453,6 +455,23 @@ public class ConversationListFragment extends Fragment implements ConversationLi } applyHomeNavTabActiveSize(mHomeNavMessages, mHomeNavMessagesNaturalWidth); applyHomeNavTabActiveSize(mHomeNavAutomate, mHomeNavAutomateNaturalWidth); + if (mHomeNavDock != null) { + mHomeNavDock.post(this::alignHomeNavDockToGuideline); + } + } + + /** Slide only the Messages/Automation pill to the 20dp screen guideline; compose stays put. */ + private void alignHomeNavDockToGuideline() { + if (mHomeNavDock == null || mRootView == null || mHomeNavDock.getWidth() <= 0) { + return; + } + final int guideline = getResources().getDimensionPixelSize(R.dimen.looply_screen_padding); + mHomeNavDock.setTranslationX(0f); + final int[] dockLoc = new int[2]; + final int[] rootLoc = new int[2]; + mHomeNavDock.getLocationOnScreen(dockLoc); + mRootView.getLocationOnScreen(rootLoc); + mHomeNavDock.setTranslationX(guideline - (dockLoc[0] - rootLoc[0])); } private void applyHomeNavTabActiveSize(final View tab, final int natural) { diff --git a/app/src/main/java/com/android/messaging/ui/home/HomeSearchActivity.java b/app/src/main/java/com/android/messaging/ui/home/HomeSearchActivity.java index e2d55af..f853eb4 100644 --- a/app/src/main/java/com/android/messaging/ui/home/HomeSearchActivity.java +++ b/app/src/main/java/com/android/messaging/ui/home/HomeSearchActivity.java @@ -16,29 +16,58 @@ package com.android.messaging.ui.home; +import android.content.Intent; +import android.content.res.ColorStateList; +import android.database.Cursor; +import android.net.Uri; import android.os.Bundle; +import android.speech.RecognizerIntent; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; +import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.DrawableRes; import androidx.annotation.IdRes; +import androidx.annotation.Nullable; import androidx.annotation.StringRes; +import androidx.core.content.ContextCompat; import com.android.messaging.R; +import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns; +import com.android.messaging.datamodel.MessagingContentProvider; +import com.android.messaging.datamodel.data.ConversationListItemData; import com.android.messaging.ui.BugleActionBarActivity; +import com.android.messaging.ui.ContactIconView; +import com.android.messaging.ui.UIIntents; +import com.android.messaging.util.AvatarUriUtil; import com.android.messaging.util.ImeUtil; +import com.android.messaging.util.UriUtil; +import com.google.android.material.chip.Chip; +import com.google.android.material.chip.ChipGroup; -/** Home-style message search entry point with quick filter tiles. */ +import java.util.ArrayList; +import java.util.List; + +/** Home-style message search hub with frequent contacts, categories, and recent queries. */ public class HomeSearchActivity extends BugleActionBarActivity { + private static final int FREQUENT_LIMIT = 4; + private static final int VOICE_SEARCH_REQUEST = 71; + private EditText mSearchField; private ImageButton mClearButton; + private ImageButton mVoiceButton; + private LinearLayout mFrequentSection; + private LinearLayout mFrequentRow; + private View mRecentSection; + private ChipGroup mRecentGroup; @Override protected void onCreate(final Bundle savedInstanceState) { @@ -49,12 +78,40 @@ public class HomeSearchActivity extends BugleActionBarActivity { } HomeSubHeader.bind(this, R.string.home_search_title, v -> finish()); + HomeSubHeader.bindAction(this, R.string.home_search_reset, v -> resetSearch()); mSearchField = findViewById(R.id.home_search_field); mClearButton = findViewById(R.id.home_search_clear); + mVoiceButton = findViewById(R.id.home_search_voice); + mFrequentSection = findViewById(R.id.home_search_frequent_section); + mFrequentRow = findViewById(R.id.home_search_frequent_row); + mRecentSection = findViewById(R.id.home_search_recent_section); + mRecentGroup = findViewById(R.id.home_search_recent_group); + if (mClearButton != null) { mClearButton.setOnClickListener(v -> mSearchField.setText("")); } + if (mVoiceButton != null) { + mVoiceButton.setOnClickListener(v -> startVoiceSearch()); + } + final View seeAll = findViewById(R.id.home_search_frequent_see_all); + if (seeAll != null) { + seeAll.setOnClickListener(v -> HomeToast.show(this, + getString(R.string.home_search_coming_soon, + getString(R.string.home_search_frequent_title)))); + } + final View clearHistory = findViewById(R.id.home_search_clear_history); + if (clearHistory != null) { + clearHistory.setOnClickListener(v -> { + HomeSearchHistoryStore.clear(this); + bindRecentSearches(); + }); + } + final TextView categoryCount = findViewById(R.id.home_search_categories_count); + if (categoryCount != null) { + categoryCount.setText(getString(R.string.home_search_categories_count, 8)); + } + if (mSearchField != null) { mSearchField.addTextChangedListener(new TextWatcher() { @Override @@ -69,7 +126,7 @@ public class HomeSearchActivity extends BugleActionBarActivity { @Override public void afterTextChanged(final Editable s) { - updateClearButton(); + updateFieldActions(); } }); mSearchField.setOnEditorActionListener((v, actionId, event) -> { @@ -79,28 +136,31 @@ public class HomeSearchActivity extends BugleActionBarActivity { mSearchField.requestFocus(); mSearchField.post(() -> ImeUtil.get().showImeKeyboard(this, mSearchField)); } - updateClearButton(); + updateFieldActions(); bindFilter(R.id.home_search_filter_unread, R.drawable.ic_home_menu_unread, - R.string.home_search_filter_unread); + R.string.home_search_filter_unread, 0); bindFilter(R.id.home_search_filter_saved, R.drawable.ic_home_menu_person, - R.string.home_search_filter_saved); + R.string.home_search_filter_saved, 0); bindFilter(R.id.home_search_filter_unknown, R.drawable.ic_home_menu_spam, - R.string.home_search_filter_unknown); + R.string.home_search_filter_unknown, 0); bindFilter(R.id.home_search_filter_starred, R.drawable.ic_home_star_line, - R.string.home_search_filter_starred); + R.string.home_search_filter_starred, StarredMessagesStore.count(this)); bindFilter(R.id.home_search_filter_images, R.drawable.ic_home_image_line, - R.string.home_search_filter_images); + R.string.home_search_filter_images, 0); bindFilter(R.id.home_search_filter_videos, R.drawable.ic_home_video_line, - R.string.home_search_filter_videos); + R.string.home_search_filter_videos, 0); bindFilter(R.id.home_search_filter_places, R.drawable.ic_home_place_line, - R.string.home_search_filter_places); + R.string.home_search_filter_places, 0); bindFilter(R.id.home_search_filter_links, R.drawable.ic_home_link_line, - R.string.home_search_filter_links); + R.string.home_search_filter_links, 0); + + bindRecentSearches(); + loadConversationStats(); } private void bindFilter(@IdRes final int tileId, @DrawableRes final int iconRes, - @StringRes final int labelRes) { + @StringRes final int labelRes, final int count) { final View tile = findViewById(tileId); if (tile == null) { return; @@ -113,25 +173,232 @@ public class HomeSearchActivity extends BugleActionBarActivity { if (label != null) { label.setText(labelRes); } + setFilterCount(tile, count); tile.setOnClickListener(v -> HomeToast.show(this, getString(R.string.home_search_coming_soon, getString(labelRes)))); } - private void updateClearButton() { - if (mClearButton == null || mSearchField == null) { + private void setFilterCount(final View tile, final int count) { + final TextView countView = tile.findViewById(R.id.home_search_filter_count); + if (countView == null) { return; } - mClearButton.setVisibility( - TextUtils.isEmpty(mSearchField.getText()) ? View.GONE : View.VISIBLE); + countView.setText(String.valueOf(Math.max(0, count))); + countView.setTextColor(ContextCompat.getColor(this, + count > 0 ? R.color.home_accent : R.color.home_text_secondary)); + } + + private void loadConversationStats() { + new Thread(() -> { + int unread = 0; + int saved = 0; + int unknown = 0; + final List frequent = new ArrayList<>(); + Cursor cursor = null; + try { + cursor = getContentResolver().query( + MessagingContentProvider.CONVERSATIONS_URI, null, null, null, + ConversationColumns.SORT_TIMESTAMP + " DESC"); + if (cursor != null) { + while (cursor.moveToNext()) { + final ConversationListItemData item = new ConversationListItemData(); + item.bind(cursor); + if (item.getIsArchived()) { + continue; + } + if (!item.getIsRead()) { + unread++; + } + if (!item.getIsGroup()) { + if (item.getParticipantContactId() > 0) { + saved++; + } else { + unknown++; + } + } + if (frequent.size() < FREQUENT_LIMIT) { + frequent.add(item); + } + } + } + } catch (final Exception ignored) { + } finally { + if (cursor != null) { + cursor.close(); + } + } + final int unreadCount = unread; + final int savedCount = saved; + final int unknownCount = unknown; + runOnUiThread(() -> { + if (isFinishing()) { + return; + } + applyFilterCount(R.id.home_search_filter_unread, unreadCount); + applyFilterCount(R.id.home_search_filter_saved, savedCount); + applyFilterCount(R.id.home_search_filter_unknown, unknownCount); + bindFrequentContacts(frequent); + }); + }, "home-search-stats").start(); + } + + private void applyFilterCount(@IdRes final int tileId, final int count) { + final View tile = findViewById(tileId); + if (tile != null) { + setFilterCount(tile, count); + } + } + + private void bindFrequentContacts(final List items) { + if (mFrequentSection == null || mFrequentRow == null) { + return; + } + mFrequentRow.removeAllViews(); + if (items == null || items.isEmpty()) { + mFrequentSection.setVisibility(View.GONE); + return; + } + mFrequentSection.setVisibility(View.VISIBLE); + final LayoutInflater inflater = getLayoutInflater(); + for (final ConversationListItemData item : items) { + final View cell = inflater.inflate(R.layout.home_search_frequent_item, mFrequentRow, + false); + final ContactIconView avatar = cell.findViewById(R.id.home_search_frequent_avatar); + final TextView name = cell.findViewById(R.id.home_search_frequent_name); + if (avatar != null) { + avatar.setImageResourceUri(frequentAvatarUri(item), + item.getParticipantContactId(), + item.getParticipantLookupKey(), + item.getOtherParticipantNormalizedDestination()); + avatar.setImageClickHandlerDisabled(true); + } + if (name != null) { + name.setText(item.getName()); + } + cell.setOnClickListener(v -> UIIntents.get().launchConversationActivity( + this, item.getConversationId(), null)); + mFrequentRow.addView(cell); + } + } + + private void bindRecentSearches() { + if (mRecentSection == null || mRecentGroup == null) { + return; + } + mRecentGroup.removeAllViews(); + final List items = HomeSearchHistoryStore.list(this); + if (items.isEmpty()) { + mRecentSection.setVisibility(View.GONE); + return; + } + mRecentSection.setVisibility(View.VISIBLE); + final int bg = ContextCompat.getColor(this, R.color.home_row_bg); + final int stroke = ContextCompat.getColor(this, R.color.home_divider); + final int text = ContextCompat.getColor(this, R.color.home_text_primary); + final int close = ContextCompat.getColor(this, R.color.home_text_secondary); + for (final String query : items) { + final Chip chip = new Chip(this, null, com.google.android.material.R.attr.chipStyle); + chip.setText(query); + chip.setCheckable(false); + chip.setClickable(true); + chip.setCloseIconVisible(true); + chip.setChipBackgroundColor(ColorStateList.valueOf(bg)); + chip.setChipStrokeColor(ColorStateList.valueOf(stroke)); + chip.setChipStrokeWidth(getResources().getDisplayMetrics().density); + chip.setChipCornerRadius(999f); + chip.setTextColor(text); + chip.setCloseIconTint(ColorStateList.valueOf(close)); + chip.setEnsureMinTouchTargetSize(false); + chip.setOnClickListener(v -> { + mSearchField.setText(query); + mSearchField.setSelection(query.length()); + submitSearch(); + }); + chip.setOnCloseIconClickListener(v -> { + HomeSearchHistoryStore.remove(this, query); + bindRecentSearches(); + }); + mRecentGroup.addView(chip); + } + } + + private static Uri frequentAvatarUri(final ConversationListItemData item) { + Uri stored = null; + if (!TextUtils.isEmpty(item.getIcon())) { + try { + stored = Uri.parse(item.getIcon()); + } catch (final RuntimeException ignored) { + stored = null; + } + } + if (stored != null && AvatarUriUtil.isAvatarUri(stored)) { + return stored; + } + final Uri photo = (stored != null && UriUtil.isLocalResourceUri(stored)) ? stored : null; + return AvatarUriUtil.createAvatarUri(photo, item.getName(), + item.getOtherParticipantNormalizedDestination(), + item.getParticipantLookupKey()); + } + + private void updateFieldActions() { + final boolean empty = mSearchField == null || TextUtils.isEmpty(mSearchField.getText()); + if (mClearButton != null) { + mClearButton.setVisibility(empty ? View.GONE : View.VISIBLE); + } + if (mVoiceButton != null) { + mVoiceButton.setVisibility(empty ? View.VISIBLE : View.GONE); + } } private void submitSearch() { if (mSearchField == null || TextUtils.isEmpty(mSearchField.getText())) { return; } + final String query = mSearchField.getText().toString().trim(); + HomeSearchHistoryStore.add(this, query); + bindRecentSearches(); ImeUtil.get().hideImeKeyboard(this, mSearchField); - HomeToast.show(this, getString(R.string.home_search_coming_soon, - mSearchField.getText().toString())); + HomeToast.show(this, getString(R.string.home_search_coming_soon, query)); + } + + private void resetSearch() { + if (mSearchField != null) { + mSearchField.setText(""); + } + HomeSearchHistoryStore.clear(this); + bindRecentSearches(); + updateFieldActions(); + } + + private void startVoiceSearch() { + final Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); + intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.home_search_field_hint)); + try { + startActivityForResult(intent, VOICE_SEARCH_REQUEST); + } catch (final Exception ignored) { + HomeToast.show(this, getString(R.string.home_search_coming_soon, + getString(R.string.home_search_voice))); + } + } + + @Override + protected void onActivityResult(final int requestCode, final int resultCode, + @Nullable final Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode != VOICE_SEARCH_REQUEST || resultCode != RESULT_OK || data == null + || mSearchField == null) { + return; + } + final ArrayList results = + data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); + if (results == null || results.isEmpty()) { + return; + } + mSearchField.setText(results.get(0)); + mSearchField.setSelection(mSearchField.getText().length()); + submitSearch(); } @Override diff --git a/app/src/main/java/com/android/messaging/ui/home/HomeSearchHistoryStore.java b/app/src/main/java/com/android/messaging/ui/home/HomeSearchHistoryStore.java new file mode 100644 index 0000000..374ae74 --- /dev/null +++ b/app/src/main/java/com/android/messaging/ui/home/HomeSearchHistoryStore.java @@ -0,0 +1,69 @@ +package com.android.messaging.ui.home; + +import android.content.Context; +import android.content.SharedPreferences; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** Recent search queries for the home search hub. */ +public final class HomeSearchHistoryStore { + + private static final String PREFS_NAME = "home_search_history"; + private static final String KEY_QUERIES = "queries"; + private static final String SEPARATOR = "\n"; + private static final int MAX_ITEMS = 10; + + private HomeSearchHistoryStore() { + } + + public static List list(final Context context) { + final String raw = prefs(context).getString(KEY_QUERIES, ""); + if (TextUtils.isEmpty(raw)) { + return Collections.emptyList(); + } + final List items = new ArrayList<>(); + for (final String part : raw.split(SEPARATOR, -1)) { + if (!TextUtils.isEmpty(part)) { + items.add(part); + } + } + return items; + } + + public static void add(final Context context, final String query) { + final String trimmed = query == null ? "" : query.trim(); + if (TextUtils.isEmpty(trimmed)) { + return; + } + final List items = new ArrayList<>(list(context)); + items.remove(trimmed); + items.add(0, trimmed); + while (items.size() > MAX_ITEMS) { + items.remove(items.size() - 1); + } + save(context, items); + } + + public static void remove(final Context context, final String query) { + final List items = new ArrayList<>(list(context)); + if (items.remove(query)) { + save(context, items); + } + } + + public static void clear(final Context context) { + prefs(context).edit().remove(KEY_QUERIES).apply(); + } + + private static void save(final Context context, final List items) { + prefs(context).edit().putString(KEY_QUERIES, TextUtils.join(SEPARATOR, items)).apply(); + } + + private static SharedPreferences prefs(final Context context) { + return context.getApplicationContext().getSharedPreferences(PREFS_NAME, + Context.MODE_PRIVATE); + } +} diff --git a/app/src/main/java/com/android/messaging/ui/home/HomeSubHeader.java b/app/src/main/java/com/android/messaging/ui/home/HomeSubHeader.java index 3c04bb7..202d1c3 100644 --- a/app/src/main/java/com/android/messaging/ui/home/HomeSubHeader.java +++ b/app/src/main/java/com/android/messaging/ui/home/HomeSubHeader.java @@ -48,6 +48,17 @@ public final class HomeSubHeader { } } + public static void bindAction(final Activity activity, @StringRes final int actionResId, + final View.OnClickListener onAction) { + final TextView action = activity.findViewById(R.id.home_sub_header_action); + if (action == null) { + return; + } + action.setText(actionResId); + action.setVisibility(View.VISIBLE); + action.setOnClickListener(onAction); + } + public static void bindBackOnly(final Activity activity, final View.OnClickListener onBack) { final ImageButton back = activity.findViewById(R.id.home_sub_header_back); diff --git a/app/src/main/java/com/android/messaging/ui/home/StarredMessagesStore.java b/app/src/main/java/com/android/messaging/ui/home/StarredMessagesStore.java index ddfa76d..1b14d01 100644 --- a/app/src/main/java/com/android/messaging/ui/home/StarredMessagesStore.java +++ b/app/src/main/java/com/android/messaging/ui/home/StarredMessagesStore.java @@ -32,6 +32,10 @@ public final class StarredMessagesStore { private StarredMessagesStore() { } + public static int count(final Context context) { + return ids(context).size(); + } + public static boolean isStarred(final Context context, final String messageId) { if (TextUtils.isEmpty(messageId)) { return false; diff --git a/app/src/main/res/drawable/home_bg_search_card.xml b/app/src/main/res/drawable/home_bg_search_card.xml new file mode 100644 index 0000000..d8fd2f3 --- /dev/null +++ b/app/src/main/res/drawable/home_bg_search_card.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/conversation_list_fragment.xml b/app/src/main/res/layout/conversation_list_fragment.xml index 4dd357c..81ffb9a 100644 --- a/app/src/main/res/layout/conversation_list_fragment.xml +++ b/app/src/main/res/layout/conversation_list_fragment.xml @@ -277,6 +277,15 @@ android:text="@string/home_search_field_hint" android:textColor="@color/home_search_hint" android:textSize="16sp" /> + + diff --git a/app/src/main/res/layout/home_search_activity.xml b/app/src/main/res/layout/home_search_activity.xml index 1870ccf..7152bc6 100644 --- a/app/src/main/res/layout/home_search_activity.xml +++ b/app/src/main/res/layout/home_search_activity.xml @@ -9,150 +9,292 @@ - - - - - - - - - - + android:layout_height="0dp" + android:layout_weight="1" + android:clipToPadding="false" + android:overScrollMode="ifContentScrolls" + android:scrollbars="none"> + android:orientation="vertical" + android:paddingStart="@dimen/looply_screen_padding" + android:paddingTop="@dimen/looply_space_sm" + android:paddingEnd="@dimen/looply_screen_padding" + android:paddingBottom="@dimen/looply_space_xxl"> - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + diff --git a/app/src/main/res/layout/home_search_filter_item.xml b/app/src/main/res/layout/home_search_filter_item.xml index 2671b46..df86361 100644 --- a/app/src/main/res/layout/home_search_filter_item.xml +++ b/app/src/main/res/layout/home_search_filter_item.xml @@ -1,20 +1,23 @@ - + android:paddingTop="@dimen/looply_space_md" + android:paddingEnd="@dimen/looply_space_lg" + android:paddingBottom="@dimen/looply_space_md"> @@ -27,7 +30,17 @@ android:layout_weight="1" android:ellipsize="end" android:includeFontPadding="false" - android:maxLines="1" + android:maxLines="2" android:textColor="@color/home_text_primary" android:textSize="15sp" /> + + diff --git a/app/src/main/res/layout/home_search_frequent_item.xml b/app/src/main/res/layout/home_search_frequent_item.xml new file mode 100644 index 0000000..2bb6412 --- /dev/null +++ b/app/src/main/res/layout/home_search_frequent_item.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/app/src/main/res/layout/home_sub_header.xml b/app/src/main/res/layout/home_sub_header.xml index 5a3abec..a0bec72 100644 --- a/app/src/main/res/layout/home_sub_header.xml +++ b/app/src/main/res/layout/home_sub_header.xml @@ -41,4 +41,18 @@ android:visibility="gone" app:srcCompat="@drawable/ic_looply_more" app:tint="@color/home_text_primary" /> + + diff --git a/app/src/main/res/values/looply_dimens.xml b/app/src/main/res/values/looply_dimens.xml index 100ac6b..8ae5132 100644 --- a/app/src/main/res/values/looply_dimens.xml +++ b/app/src/main/res/values/looply_dimens.xml @@ -106,9 +106,10 @@ 8dp 14dp 28dp - 56dp + 88dp 22dp - 52dp + 48dp + 48dp 52dp 52dp 55dp diff --git a/app/src/main/res/values/looply_strings.xml b/app/src/main/res/values/looply_strings.xml index d5c59db..15bd0d2 100644 --- a/app/src/main/res/values/looply_strings.xml +++ b/app/src/main/res/values/looply_strings.xml @@ -155,8 +155,16 @@ Search - Search messages + Search messages or contacts Clear + Reset + Voice search + Frequent contacts + See all + Categories + %1$d items + Recent searches + Clear history Unread Saved contacts Unknown contacts