diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index 74bea9cd936c..62ba290ef757 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -110,6 +110,7 @@ import com.duckduckgo.app.browser.api.WebViewCapabilityChecker.WebViewCapability import com.duckduckgo.app.browser.applinks.AppLinksLauncher import com.duckduckgo.app.browser.applinks.AppLinksSnackBarConfigurator import com.duckduckgo.app.browser.autocomplete.BrowserAutoCompleteSuggestionsAdapter +import com.duckduckgo.app.browser.autocomplete.SuggestionItemDecoration import com.duckduckgo.app.browser.commands.Command import com.duckduckgo.app.browser.commands.Command.ShowBackNavigationHistory import com.duckduckgo.app.browser.commands.NavigationCommand @@ -2329,6 +2330,9 @@ class BrowserTabFragment : omnibarPosition = settingsDataStore.omnibarPosition, ) binding.autoCompleteSuggestionsList.adapter = autoCompleteSuggestionsAdapter + binding.autoCompleteSuggestionsList.addItemDecoration( + SuggestionItemDecoration(ContextCompat.getDrawable(context, R.drawable.suggestions_divider)!!), + ) } private fun configureNewTab() { diff --git a/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionItemDecoration.kt b/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionItemDecoration.kt new file mode 100644 index 000000000000..486aaf58b469 --- /dev/null +++ b/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionItemDecoration.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.duckduckgo.app.browser.autocomplete + +import android.graphics.Canvas +import android.graphics.drawable.Drawable +import android.view.ViewGroup.MarginLayoutParams +import androidx.recyclerview.widget.RecyclerView + +class SuggestionItemDecoration(private val divider: Drawable) : RecyclerView.ItemDecoration() { + + override fun onDrawOver( + canvas: Canvas, + parent: RecyclerView, + state: RecyclerView.State, + ) { + canvas.save() + + val childCount = parent.childCount + val parentRight = parent.width - parent.paddingRight + + for (i in 0 until childCount) { + val child = parent.getChildAt(i) + val params = child.layoutParams as MarginLayoutParams + val currentViewType = child.tag + val nextViewType = if (i + 1 < childCount) parent.getChildAt(i + 1).tag else UNKNOWN + + if (nextViewType == UNKNOWN) { + continue + } + + if (currentViewType == SEARCH_ITEM && nextViewType == OTHER_ITEM) { + drawDivider(canvas, child, params, parentRight) + } + + if (currentViewType == OTHER_ITEM && nextViewType == SEARCH_ITEM) { + drawDivider(canvas, child, params, parentRight) + } + } + + canvas.restore() + } + + private fun drawDivider( + canvas: Canvas, + child: android.view.View, + params: MarginLayoutParams, + parentRight: Int, + ) { + val horizontalSize = parentRight + val verticalSize = child.bottom + params.bottomMargin + divider.setBounds(0, verticalSize, horizontalSize, verticalSize + divider.intrinsicHeight) + divider.draw(canvas) + } + + companion object { + internal const val SEARCH_ITEM = "SEARCH_ITEM" + internal const val OTHER_ITEM = "OTHER_ITEM" + internal const val UNKNOWN = "UNKNOWN" + } +} diff --git a/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionViewHolderFactory.kt b/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionViewHolderFactory.kt index 8c5846037b1a..57d563cdcd82 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionViewHolderFactory.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionViewHolderFactory.kt @@ -29,6 +29,8 @@ import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.A import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteUrlSuggestion.AutoCompleteSwitchToTabSuggestion import com.duckduckgo.app.browser.R import com.duckduckgo.app.browser.autocomplete.AutoCompleteViewHolder.InAppMessageViewHolder +import com.duckduckgo.app.browser.autocomplete.SuggestionItemDecoration.Companion.OTHER_ITEM +import com.duckduckgo.app.browser.autocomplete.SuggestionItemDecoration.Companion.SEARCH_ITEM import com.duckduckgo.app.browser.databinding.ItemAutocompleteBookmarkSuggestionBinding import com.duckduckgo.app.browser.databinding.ItemAutocompleteDefaultBinding import com.duckduckgo.app.browser.databinding.ItemAutocompleteHistorySuggestionBinding @@ -269,6 +271,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it if (omnibarPosition == OmnibarPosition.BOTTOM) { editQueryImage.setImageResource(R.drawable.ic_autocomplete_down_20dp) } + + root.tag = SEARCH_ITEM } } @@ -294,6 +298,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it if (omnibarPosition == OmnibarPosition.BOTTOM) { editQueryImage.setImageResource(R.drawable.ic_autocomplete_down_20dp) } + + root.tag = OTHER_ITEM } } @@ -307,6 +313,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it bookmarkIndicator.setImageResource(if (item.isFavorite) R.drawable.ic_bookmark_favorite_20 else R.drawable.ic_bookmark_20) root.setOnClickListener { immediateSearchListener(item) } + + root.tag = OTHER_ITEM } } @@ -324,6 +332,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it longPressClickListener(item) true } + + root.tag = OTHER_ITEM } } @@ -336,6 +346,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it url.text = root.context.getString(R.string.autocompleteSwitchToTab, item.phrase.formatIfUrl()) root.setOnClickListener { immediateSearchListener(item) } + + root.tag = OTHER_ITEM } } @@ -353,6 +365,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it if (omnibarPosition == OmnibarPosition.BOTTOM) { binding.editQueryImage.setImageResource(R.drawable.ic_autocomplete_down_20dp) } + + binding.root.tag = OTHER_ITEM } } @@ -371,6 +385,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it ) binding.messageCta.onCloseButtonClicked { deleteClickListener(item) } binding.messageCta.onPrimaryActionClicked { openSettingsClickListener() } + + binding.root.tag = OTHER_ITEM } } diff --git a/app/src/main/res/drawable/ic_switch_to_tab_20.xml b/app/src/main/res/drawable/ic_switch_to_tab_20.xml index 052c8511bd82..8860a3f5d23e 100644 --- a/app/src/main/res/drawable/ic_switch_to_tab_20.xml +++ b/app/src/main/res/drawable/ic_switch_to_tab_20.xml @@ -5,6 +5,6 @@ android:viewportHeight="20"> diff --git a/app/src/main/res/drawable/suggestions_divider.xml b/app/src/main/res/drawable/suggestions_divider.xml new file mode 100644 index 000000000000..c111e7320c8f --- /dev/null +++ b/app/src/main/res/drawable/suggestions_divider.xml @@ -0,0 +1,26 @@ + + + + + + + + + \ No newline at end of file