Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-selection: Selection mode #5623

Open
wants to merge 13 commits into
base: feature/ondrej/tab-multi-selection-menu
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,18 @@ import android.os.Bundle
import androidx.recyclerview.widget.DiffUtil
import com.duckduckgo.app.tabs.model.TabEntity

class TabEntityDiffCallback(old: List<TabEntity>, new: List<TabEntity>) : DiffUtil.Callback() {
class TabEntityDiffCallback(
old: List<TabEntity>,
new: List<TabEntity>,
oldSelectedIds: List<String>? = null,
newSelectedIds: List<String>? = null,
) : DiffUtil.Callback() {

// keep a local copy of the lists to avoid any changes to the lists during the diffing process
private val oldList = old.toList()
private val newList = new.toList()
private val oldSelectedTabIds = oldSelectedIds?.toList()
private val newSelectedIds = newSelectedIds?.toList()

private fun areItemsTheSame(
oldItem: TabEntity,
Expand All @@ -40,7 +47,8 @@ class TabEntityDiffCallback(old: List<TabEntity>, new: List<TabEntity>) : DiffUt
return oldItem.tabPreviewFile == newItem.tabPreviewFile &&
oldItem.viewed == newItem.viewed &&
oldItem.title == newItem.title &&
oldItem.url == newItem.url
oldItem.url == newItem.url &&
oldSelectedTabIds?.contains(oldItem.tabId) == newSelectedIds?.contains(newItem.tabId)
}

private fun getChangePayload(
Expand All @@ -65,6 +73,10 @@ class TabEntityDiffCallback(old: List<TabEntity>, new: List<TabEntity>) : DiffUt
diffBundle.putString(DIFF_KEY_PREVIEW, newItem.tabPreviewFile)
}

if (oldSelectedTabIds?.contains(oldItem.tabId) != newSelectedIds?.contains(newItem.tabId)) {
diffBundle.putString(DIFF_KEY_SELECTION, newItem.tabId)
}

return diffBundle
}

Expand Down Expand Up @@ -105,5 +117,6 @@ class TabEntityDiffCallback(old: List<TabEntity>, new: List<TabEntity>) : DiffUt
const val DIFF_KEY_URL = "url"
const val DIFF_KEY_PREVIEW = "previewImage"
const val DIFF_KEY_VIEWED = "viewed"
const val DIFF_KEY_SELECTION = "selection"
}
}
58 changes: 42 additions & 16 deletions app/src/main/java/com/duckduckgo/app/tabs/ui/TabItemDecorator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,52 +23,77 @@ import android.graphics.RectF
import android.util.TypedValue
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.SelectionViewState.Mode
import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.SelectionViewState.Mode.Normal
import com.duckduckgo.common.ui.view.toPx
import com.duckduckgo.mobile.android.R as CommonR

class TabItemDecorator(
context: Context,
var selectedTabId: String?,
val selectedTabId: String?,
private var mode: Mode = Normal,
) : RecyclerView.ItemDecoration() {

private val borderStroke: Paint = Paint().apply {
var highlightedTabId: String? = selectedTabId
private set

private val activeTabBorderStroke: Paint = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
strokeWidth = BORDER_WIDTH
strokeWidth = ACTIVE_TAB_BORDER_WIDTH

val typedValue = TypedValue()
context.theme.resolveAttribute(CommonR.attr.daxColorBackgroundInverted, typedValue, true)
color = ContextCompat.getColor(context, typedValue.resourceId)
}

private val selectionBorderStroke: Paint = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
strokeWidth = SELECTION_BORDER_WIDTH

val typedValue = TypedValue()
context.theme.resolveAttribute(CommonR.attr.daxColorAccentBlue, typedValue, true)
color = ContextCompat.getColor(context, typedValue.resourceId)
}

override fun onDrawOver(
canvas: Canvas,
recyclerView: RecyclerView,
state: RecyclerView.State,
) {
val adapter = recyclerView.adapter as TabSwitcherAdapter? ?: return

for (i in 0 until recyclerView.childCount) {
val child = recyclerView.getChildAt(i)

recyclerView.children.forEach { child ->
val positionInAdapter = recyclerView.getChildAdapterPosition(child)
adapter.getTab(positionInAdapter)?.let { tab ->
if (tab.tabId == selectedTabId) {
drawSelectedTabDecoration(child, canvas)
when (mode) {
is Normal -> {
if (tab.tabId == highlightedTabId) {
drawTabDecoration(child, canvas, activeTabBorderStroke)
}
}
is Mode.Selection -> {
if (tab.tabId in (mode as Mode.Selection).selectedTabs) {
drawTabDecoration(child, canvas, selectionBorderStroke)
}
}
}
}
}

super.onDrawOver(canvas, recyclerView, state)
}

private fun drawSelectedTabDecoration(
child: View,
c: Canvas,
) {
borderStroke.alpha = (child.alpha * 255).toInt()
c.drawRoundRect(child.getBounds(), BORDER_RADIUS, BORDER_RADIUS, borderStroke)
fun updateParameters(selectedTabId: String?, mode: Mode = Normal) {
this.highlightedTabId = selectedTabId
this.mode = mode
}

private fun drawTabDecoration(child: View, c: Canvas, paint: Paint) {
selectionBorderStroke.alpha = (child.alpha * 255).toInt()
c.drawRoundRect(child.getBounds(), BORDER_RADIUS, BORDER_RADIUS, paint)
}

private fun View.getBounds(): RectF {
Expand All @@ -83,7 +108,8 @@ class TabItemDecorator(

companion object {
private val BORDER_RADIUS = 12.toPx().toFloat()
private val BORDER_WIDTH = 2.toPx().toFloat()
private val ACTIVE_TAB_BORDER_WIDTH = 2.toPx().toFloat()
private val SELECTION_BORDER_WIDTH = 4.toPx().toFloat()
private val BORDER_PADDING = 3.toPx().toFloat()
}
}
Loading
Loading