You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SwipeToDeleteCallback.kt

136 lines
5.2 KiB
Kotlin

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.home.sessioncontrol
import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import androidx.appcompat.content.res.AppCompatResources
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.support.ktx.android.content.getColorFromAttr
import org.mozilla.fenix.R
import org.mozilla.fenix.home.sessioncontrol.viewholders.TabInCollectionViewHolder
class SwipeToDeleteCallback(
For #5574 - Migrate SessionControl to LibState (#6651) * For #5574 - Part 1: Port TabAction.SaveTabGroup to TabSessionInteractor and SessionControlController. (#6651) - Introduces the TabSessionInteractor, SessionControlInteractor and SessionControlController classes. - Removes the TabAction.SaveTabGroup. * For #5574 - Part 2: Port TabAction.PrivateBrowsingLearnMore to TabSessionInteractor and SessionControlController (#6651) * For #5574 - Part 3: Port TabAction.ShareTabs to TabSessionInteractor and SessionControlController (#6651) * For #5574 - Part 4: Remove unused TabAction.Share and TabItemMenu (#6651) In #2205, the tab overflow button was removed which would have shown the TabItemMenu when clicked. So, we can remove TabItemMenu since it is not used and as a result, we can also remove TabAction.Share since there are no consumers. * For #5574 - Part 5: Port TabAction.PlayMedia and TabAction.PauseMedia to TabSessionInteractor and SessionControlController (#6651) * For #5574 - Part 6: Port TabAction.Select to TabSessionInteractor and SessionControlController (#6651) * For #5574 - Part 7: Port Onboarding.Finish to OnboardingInteractor and SessionControlController (#6651) * For #5574 - Part 8: Port TabAction.Close and TabAction.CloseAll to TabSessionInteractor and SessionControlController (#6651) - Removes TabAction * For #5574 - Part 9: Port CollectionAction.Delete to CollectionInteractor and SessionControlController (#6651) * For #5574 - Part 10: Port CollectionAction.ShareTabs to CollectionInteractor and SessionControlController (#6651) * For #5574 - Part 11: Port CollectionAction.AddTab and CollectionAction.Rename to CollectionInteractor and SessionControlController (#6651) * For #5574 - Part 12: Port CollectionAction.RemoveTab to CollectionInteractor and SessionControlController (#6651) * For #5574 - Part 13: Port CollectionAction.OpenTab to CollectionInteractor and SessionControlController (#6651) * For #5574 - Part 14: Port CollectionAction.CloseTabs to CollectionInteractor and SessionControlController (#6651) * For #5574 - Part 15: Introduce a HomeFragmentStore (#6651) - We will hook up the HomeFragmentStore in later parts. - Removes List<Tab>.toSessionBundle(context: Context) since it is unused. * For #5574 - Part 16: Port CollectionAction.Collapse and CollectionAction.Expand to CollectionInteractor and SessionControlController (#6651) - We assume the store is hooked up to the SessionControlController in this part, but this work will be done in a later part. - Removes CollectionAction. * For #5574 - Part 20: Remove the architecture module. (#6651) * For #5574 - Part 17: Remove duplicate subscribeToTabCollections in BrowserFragment.kt (#6651) There is a duplicate call of subscribeToTabCollections() in both HomeFragment and BrowserFragment. In this patch, we remove the call in BrowserFragment to avoid passing the HomeFragmentStore to BrowserFragment in order to dispatch the CollectionsChange event. * For #5574 - Part 18: Delete SessionControlComponent and fix TabCollection and Tab imports (#6651) * For #5574 - Part 19: Use the new HomeFragmentStore in the HomeFragment (#6651) - Renames SessionControlUIView to SessionControlView * For #5574 - Part 21: Fix white screen on home fragment (#6651) * For #5574 - Part 22: Fix formatting in SessionControlInteractor and replace See with @see in SessionControlController (#6651) * For #5574 - Part 23: Move to metrics.track call to the beginning of handleCollectionRemoveTab (#6651) This ensures that the metrics.track will be called immediately before the tab is removed from the collection. * For #5574 - Part 24: Use the sessionManager getter in SessionControlController (#6651) * For #5574 - Part 25: Use mapNotNull in List<Tab>.toSessionBundle (#6651) * For #5574 - Part 26: Simplify closeTab and closeAllTabs functions by assigning a deletionJob constant (#6651) * For #5574 - Part 27: Replace listOf() with emptyList() in removeAllTabsWithUndo (#6651) * For #5574 - Part 28: Replace the Context parameter with the HomeActivity in SessionControlController (#6651) * For #5574 - Part 29: Add test for HomeFragmentStore, DefaultSessionControlController and SessionControlInteractor (#6651) * For #5574 - Removes running CI against the architecture debug build varient
5 years ago
val interactor: SessionControlInteractor
) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
// We don't support drag and drop so this method will never be called
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
when (viewHolder) {
is TabInCollectionViewHolder -> {
interactor.onCollectionRemoveTab(viewHolder.collection, viewHolder.tab, wasSwiped = true)
}
}
}
override fun onChildDraw(
c: Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float,
dY: Float,
actionState: Int,
isCurrentlyActive: Boolean
) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
For #23350 - Revert changes from removing duplicate icons that already exists in ui-icons (#23527) * Revert "For #23121 - Override @color/mozac_ui_icons_fill with ?primaryText attribute" This reverts commit 12347c99999c340e7f7072ab2749cb13c5fd86c9. * Revert "For #23121 - Replace @drawble/ic_share with @drawable/mozac_ic_share" This reverts commit bbf6ce3f0c52e58493423ce2e2c62e3fb08f21b2. * Revert "For #23121 - Replace @drawble/ic_storage_enabled with @drawable/mozac_ic_storage" This reverts commit 930c7bf3b3076cf6b56be85fd733dd9f5cf2d1bb. * Revert "For #23121 - Replace @drawble/ic_notifications_enabled with @drawable/mozac_ic_notification" This reverts commit 9069b57c2440b517357a180e7c74b70ab86501a8. * Revert "For #23121 - Replace @drawble/ic_microphone_enabled with @drawable/mozac_ic_microphone" This reverts commit 53216f3f4a1fc6982aee8ab111cb6e92ef54f92a. * Revert "For #23121 - Replace @drawble/ic_location_enabled with @drawable/mozac_ic_location" This reverts commit 9ee9aafd879a884814f1d4b826db75f24ebdacec. * Revert "For #23121 - Replace @drawble/ic_autoplay_disabled with @drawable/mozac_ic_autoplay_blocked" This reverts commit b045a5e20317516bac422ed44549d5871a2cb96a. * Revert "For #23121 - Replace @drawble/ic_camera_enabled with @drawable/mozac_ic_video" This reverts commit 62842db131fee3aa0646c586f075f85105d32cb7. * Revert "For #23121 - Replace @drawble/mozac_ic_extensions_black with @drawable/mozac_ic_extensions" This reverts commit c020a9da10e6a49ce097b48fe2d40b7b21c578fe. * Revert "For #23121 - Replace @drawble/ic_top_sites with @drawable/mozac_ic_pin" This reverts commit ca67b0a752f9582a85ef5d22ff9cfba5f95fd1a0. * Revert "For #23121 - Replace @drawble/ic_search with @drawable/mozac_ic_search" This reverts commit 02d9197945ca9305cf3d2017954a48dd762a8a09. * Revert "For #23121 - Replace @drawble/ic_readermode with @drawable/mozac_ic_reader_mode" This reverts commit cf8592c709d26cf34a187175a2a0b4275a53a576. * Revert "For #23121 - Replace @drawble/ic_menu with @drawable/mozac_ic_menu" This reverts commit a1ac0190242ae416472442e3838318d210a6e419. * Revert "For #23121 - Replace @drawble/ic_login with @drawable/mozac_ic_login" This reverts commit 541c56b5894436c4384c7fdcb6ad3a57a566833a. * Revert "For #23121 - Replace @drawble/ic_internet with @drawable/mozac_ic_globe" This reverts commit 4d8adce85e07edce1969bd188698963c7452cac7. * Revert "For #23121 - Replace @drawble/ic_download with @drawable/mozac_ic_download" This reverts commit ef026d3ec290614053001a0709b800480ac59bf5. * Revert "For #23121 - Replace @drawble/ic_lock with @drawable/mozac_ic_lock" This reverts commit 18591d5dd848af6a11f1ebf4d37efc602a0f36e7. * Revert "For #23121 - Replace @drawble/ic_desktop with @drawable/mozac_ic_device_desktop" This reverts commit ad33e3c1e148bf20264a4cc08c524814da15409a. * Revert "For #23121 - Replace @drawble/ic_close with @drawable/mozac_ic_close" This reverts commit a9f0fefac21e63260a7e8547431a9a5af780faf1. * Revert "For #23121 - Replace @drawble/ic_delete with @drawable/mozac_ic_delete" This reverts commit 33dc752ef2864e8662eebe63756ea37360c4cf61. * Revert "For #23121 - Replace @drawble/ic_chevron_up with @drawable/mozac_ic_arrowhead_up" This reverts commit 5bf937cfd37e2fec2258d8e03e3f31d35952d9cc. * Revert "For #23121 - Replace @drawble/ic_chevron_down with @drawable/mozac_ic_arrowhead_down" This reverts commit 0fadd68112fc313f20be14c13ee75bb9ce67c472. * Revert "For #23121 - Replace @drawble/ic_back_button with @drawable/mozac_ic_back" This reverts commit bea766e7858e6a0bf38a8d1a74d79c8da68d204a. * Revert "For #23121 - Replace @drawable/ic_arrowhead_right with @drawable/mozac_ic_arrowhead_right" This reverts commit 5a6f349ea857cd2a5fdeb3b6001dcf52e8463025. * Revert "For #23121 - Replace @drawable/ic_new with @drawable/mozac_ic_new" This reverts commit ae38410106d7ed0eb65f3eda43ef45ecb7fecc73. * Revert "For #23121 - Replace @drawable/ic_addons_extensions with @drawable/mozac_ic_extensions" This reverts commit 9352946afce4d7be135bfe9b1ffc83895eb20b40.
2 years ago
val icon = AppCompatResources.getDrawable(recyclerView.context, R.drawable.ic_delete)
icon?.setTint(recyclerView.context.getColorFromAttr(R.attr.textWarning))
val backgroundDrawable = when {
viewHolder is TabInCollectionViewHolder && viewHolder.isLastItem -> {
R.drawable.tab_in_collection_last_swipe_background
}
viewHolder is TabInCollectionViewHolder -> {
R.drawable.tab_in_collection_swipe_background
}
else -> R.drawable.session_background
}
val background = AppCompatResources.getDrawable(recyclerView.context, backgroundDrawable)
background?.let {
icon?.let {
val itemView = viewHolder.itemView
val iconLeft: Int
val iconRight: Int
val margin = convertDpToPixel(MARGIN.toFloat())
val iconWidth = icon.intrinsicWidth
val iconHeight = icon.intrinsicHeight
val cellHeight = itemView.bottom - itemView.top
val iconTop = itemView.top + (cellHeight - iconHeight) / 2
val iconBottom = iconTop + iconHeight
when {
dX > 0 -> { // Swiping to the right
iconLeft = itemView.left + margin
iconRight = itemView.left + margin + iconWidth
background.setBounds(
itemView.left, itemView.top,
(itemView.left + dX).toInt() + BACKGROUND_CORNER_OFFSET,
itemView.bottom
)
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
draw(background, icon, c)
}
dX < 0 -> { // Swiping to the left
iconLeft = itemView.right - margin - iconWidth
iconRight = itemView.right - margin
background.setBounds(
(itemView.right + dX).toInt() - BACKGROUND_CORNER_OFFSET,
itemView.top, itemView.right, itemView.bottom
)
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
draw(background, icon, c)
}
else -> { // View not swiped
background.setBounds(0, 0, 0, 0)
icon.setBounds(0, 0, 0, 0)
}
}
}
}
}
override fun getSwipeDirs(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
return if (recyclerView.hasWindowFocus() &&
viewHolder is TabInCollectionViewHolder
) {
super.getSwipeDirs(recyclerView, viewHolder)
} else 0
}
companion object {
const val BACKGROUND_CORNER_OFFSET = 40
const val MARGIN = 32
private const val DENSITY_CONVERSION = 160f
private fun draw(
background: Drawable,
icon: Drawable,
c: Canvas
) {
background.draw(c)
icon.draw(c)
}
private fun convertDpToPixel(dp: Float): Int {
val metrics = Resources.getSystem().displayMetrics
val px = dp * (metrics.densityDpi / DENSITY_CONVERSION)
return Math.round(px)
}
}
}