Skip to content

Commit

Permalink
Issue mozilla-mobile#2783: Add snackbar to collection deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
rocketsroger authored and pkirakosyan committed Aug 23, 2021
1 parent e337353 commit e40ef99
Show file tree
Hide file tree
Showing 17 changed files with 41 additions and 106 deletions.
2 changes: 1 addition & 1 deletion app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -981,10 +981,10 @@ class SmokeTest {
}.expandCollection(collectionName) {
clickCollectionThreeDotButton()
selectDeleteCollection()
confirmDeleteCollection()
}

homeScreen {
verifySnackBarText("Collection deleted")
verifyNoCollectionsText()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ class CollectionRobot {

fun selectDeleteCollection() {
onView(withText("Delete collection")).click()
mDevice.waitNotNull(Until.findObject(By.res("android:id/message")), waitingTime)
}

fun confirmDeleteCollection() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.browser.state.state.createTab
import mozilla.components.feature.tab.collections.Tab
import mozilla.components.feature.tab.collections.TabCollection
import mozilla.components.feature.tab.collections.TabCollectionStorage
Expand Down Expand Up @@ -68,6 +69,15 @@ class TabCollectionStorage(
}
}

suspend fun createCollection(tabCollection: TabCollection): Long? {
return withContext(ioScope.coroutineContext) {
val sessions = tabCollection.tabs.map { createTab(url = it.url, title = it.title) }
val id = collectionStorage.createCollection(tabCollection.title, sessions)
notifyObservers { onCollectionCreated(tabCollection.title, sessions, id) }
id
}
}

suspend fun addTabsToCollection(tabCollection: TabCollection, sessions: List<TabSessionState>): Long? {
return withContext(ioScope.coroutineContext) {
val id = collectionStorage.addTabsToCollection(tabCollection, sessions)
Expand Down
54 changes: 23 additions & 31 deletions app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package org.mozilla.fenix.home

import android.animation.Animator
import android.content.Context
import android.content.DialogInterface
import android.content.res.Configuration
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.ColorDrawable
Expand All @@ -22,7 +21,6 @@ import android.widget.Button
import android.widget.LinearLayout
import android.widget.PopupWindow
import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
Expand Down Expand Up @@ -301,7 +299,7 @@ class HomeFragment : Fragment() {
viewLifecycleScope = viewLifecycleOwner.lifecycleScope,
hideOnboarding = ::hideOnboardingAndOpenSearch,
registerCollectionStorageObserver = ::registerCollectionStorageObserver,
showDeleteCollectionPrompt = ::showDeleteCollectionPrompt,
removeCollectionWithUndo = ::removeCollectionWithUndo,
showTabTray = ::openTabsTray,
handleSwipedItemDeletionCancel = ::handleSwipedItemDeletionCancel
),
Expand Down Expand Up @@ -703,34 +701,25 @@ class HomeFragment : Fragment() {
}
}

private fun showDeleteCollectionPrompt(
tabCollection: TabCollection,
title: String?,
message: String,
wasSwiped: Boolean,
handleSwipedItemDeletionCancel: () -> Unit
) {
val context = context ?: return
AlertDialog.Builder(context).apply {
setTitle(title)
setMessage(message)
setNegativeButton(R.string.tab_collection_dialog_negative) { dialog: DialogInterface, _ ->
if (wasSwiped) {
handleSwipedItemDeletionCancel()
}
dialog.cancel()
}
setPositiveButton(R.string.tab_collection_dialog_positive) { dialog: DialogInterface, _ ->
// Use fragment's lifecycle; the view may be gone by the time dialog is interacted with.
lifecycleScope.launch(IO) {
context.components.core.tabCollectionStorage.removeCollection(tabCollection)
context.components.analytics.metrics.track(Event.CollectionRemoved)
}.invokeOnCompletion {
dialog.dismiss()
}
}
create()
}.show()
@VisibleForTesting
internal fun removeCollectionWithUndo(tabCollection: TabCollection) {
val snackbarMessage = getString(R.string.snackbar_collection_deleted)

lifecycleScope.allowUndo(
requireView(),
snackbarMessage,
getString(R.string.snackbar_deleted_undo),
{
requireComponents.core.tabCollectionStorage.createCollection(tabCollection)
},
operation = { },
elevation = TOAST_ELEVATION,
anchorView = null
)

lifecycleScope.launch(IO) {
requireComponents.core.tabCollectionStorage.removeCollection(tabCollection)
}
}

override fun onResume() {
Expand Down Expand Up @@ -1146,5 +1135,8 @@ class HomeFragment : Fragment() {
private const val FADE_ANIM_DURATION = 150L
private const val CFR_WIDTH_DIVIDER = 1.7
private const val CFR_Y_OFFSET = -20

// Elevation for undo toasts
internal const val TOAST_ELEVATION = 80f
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,7 @@ class DefaultSessionControlController(
private val viewLifecycleScope: CoroutineScope,
private val hideOnboarding: () -> Unit,
private val registerCollectionStorageObserver: () -> Unit,
private val showDeleteCollectionPrompt: (
tabCollection: TabCollection,
title: String?,
message: String,
wasSwiped: Boolean,
handleSwipedItemDeletionCancel: () -> Unit
) -> Unit,
private val removeCollectionWithUndo: (tabCollection: TabCollection) -> Unit,
private val showTabTray: () -> Unit,
private val handleSwipedItemDeletionCancel: () -> Unit
) : SessionControlController {
Expand Down Expand Up @@ -266,19 +260,7 @@ class DefaultSessionControlController(
metrics.track(Event.CollectionTabRemoved)

if (collection.tabs.size == 1) {
val title = activity.resources.getString(
R.string.delete_tab_and_collection_dialog_title,
collection.title
)
val message =
activity.resources.getString(R.string.delete_tab_and_collection_dialog_message)
showDeleteCollectionPrompt(
collection,
title,
message,
wasSwiped,
handleSwipedItemDeletionCancel
)
removeCollectionWithUndo(collection)
} else {
viewLifecycleScope.launch {
tabCollectionStorage.removeTabFromCollection(collection, tab)
Expand All @@ -296,9 +278,7 @@ class DefaultSessionControlController(
}

override fun handleDeleteCollectionTapped(collection: TabCollection) {
val message =
activity.resources.getString(R.string.tab_collection_dialog_message, collection.title)
showDeleteCollectionPrompt(collection, null, message, false, handleSwipedItemDeletionCancel)
removeCollectionWithUndo(collection)
}

override fun handleOpenInPrivateTabClicked(topSite: TopSite) {
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1147,8 +1147,6 @@
<string name="delete_tab_and_collection_dialog_title">%1$s löschen?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Löschen</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Abbrechen</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Vollbildmodus wird gestartet</string>

Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-es-rAR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1125,8 +1125,6 @@
<string name="delete_tab_and_collection_dialog_title">¿Eliminar %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Eliminar</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Cancelar</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Acceder a pantalla completa</string>
<!-- Message for copying the URL via long press on the toolbar -->
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-es-rCL/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1123,8 +1123,6 @@
<string name="delete_tab_and_collection_dialog_title">¿Eliminar %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Eliminar</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Cancelar</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Pasando a modo de pantalla completa</string>
<!-- Message for copying the URL via long press on the toolbar -->
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-es-rES/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1134,8 +1134,6 @@
<string name="delete_tab_and_collection_dialog_title">¿Eliminar %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Eliminar</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Cancelar</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Accediendo a pantalla completa</string>

Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-es-rMX/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1099,8 +1099,6 @@
<string name="delete_tab_and_collection_dialog_title">¿Eliminar %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Eliminar</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Cancelar</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Accediendo a pantalla completa</string>
<!-- Message for copying the URL via long press on the toolbar -->
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1135,8 +1135,6 @@
<string name="delete_tab_and_collection_dialog_title">¿Eliminar %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Eliminar</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Cancelar</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Accediendo al modo de pantalla completa</string>

Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1133,8 +1133,6 @@
<string name="delete_tab_and_collection_dialog_title">Supprimer %1$s ?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Supprimer</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Annuler</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Mode plein écran activé</string>

Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-it/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1137,8 +1137,6 @@
<string name="delete_tab_and_collection_dialog_title">Eliminare %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Elimina</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Annulla</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Passa a schermo intero</string>

Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-pt-rBR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1104,8 +1104,6 @@
<string name="delete_tab_and_collection_dialog_title">Excluir %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Excluir</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Cancelar</string>

<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Entrando no modo de tela inteira</string>
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values-pt-rPT/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1107,8 +1107,6 @@
<string name="delete_tab_and_collection_dialog_title">Eliminar %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Eliminar</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Cancelar</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">A entrar no modo de ecrã completo</string>
<!-- Message for copying the URL via long press on the toolbar -->
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1102,8 +1102,6 @@
<string name="delete_tab_and_collection_dialog_title">Delete %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Delete</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
<string name="tab_collection_dialog_negative">Cancel</string>
<!-- Text displayed in a notification when the user enters full screen mode -->
<string name="full_screen_notification">Entering full screen mode</string>
<!-- Message for copying the URL via long press on the toolbar -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,25 +263,16 @@ class DefaultSessionControlControllerTest {
} returns "Deleting this tab will delete everything."

var actualCollection: TabCollection? = null
var actualTitle: String? = null
var actualMessage: String? = null
var actualWasSwipe: Boolean? = null

createController(
showDeleteCollectionPrompt = { collection, title, message, wasSwipe, _ ->
removeCollectionWithUndo = { collection ->
actualCollection = collection
actualTitle = title
actualMessage = message
actualWasSwipe = wasSwipe
}
).handleCollectionRemoveTab(expectedCollection, tab, false)

verify { metrics.track(Event.CollectionTabRemoved) }

assertEquals(expectedCollection, actualCollection)
assertEquals("Delete Collection?", actualTitle)
assertEquals("Deleting this tab will delete everything.", actualMessage)
assertEquals(false, actualWasSwipe)
}

@Test
Expand Down Expand Up @@ -319,23 +310,14 @@ class DefaultSessionControlControllerTest {
} returns "Are you sure you want to delete Collection?"

var actualCollection: TabCollection? = null
var actualTitle: String? = null
var actualMessage: String? = null
var actualWasSwipe: Boolean? = null

createController(
showDeleteCollectionPrompt = { collection, title, message, wasSwipe, _ ->
removeCollectionWithUndo = { collection ->
actualCollection = collection
actualTitle = title
actualMessage = message
actualWasSwipe = wasSwipe
}
).handleDeleteCollectionTapped(expectedCollection)

assertEquals(expectedCollection, actualCollection)
assertEquals(null, actualTitle)
assertEquals("Are you sure you want to delete Collection?", actualMessage)
assertEquals(false, actualWasSwipe)
}

@Test
Expand Down Expand Up @@ -744,13 +726,7 @@ class DefaultSessionControlControllerTest {
registerCollectionStorageObserver: () -> Unit = { },
showTabTray: () -> Unit = { },
handleSwipedItemDeletionCancel: () -> Unit = { },
showDeleteCollectionPrompt: (
tabCollection: TabCollection,
title: String?,
message: String,
wasSwiped: Boolean,
handleSwipedItemDeletionCancel: () -> Unit
) -> Unit = { _, _, _, _, _ -> }
removeCollectionWithUndo: (tabCollection: TabCollection) -> Unit = { }
): DefaultSessionControlController {
return DefaultSessionControlController(
activity = activity,
Expand All @@ -768,7 +744,7 @@ class DefaultSessionControlControllerTest {
viewLifecycleScope = scope,
hideOnboarding = hideOnboarding,
registerCollectionStorageObserver = registerCollectionStorageObserver,
showDeleteCollectionPrompt = showDeleteCollectionPrompt,
removeCollectionWithUndo = removeCollectionWithUndo,
showTabTray = showTabTray,
handleSwipedItemDeletionCancel = handleSwipedItemDeletionCancel
)
Expand Down

0 comments on commit e40ef99

Please sign in to comment.