Skip to content

Commit

Permalink
For mozilla-mobile#10332 - Adds undo snackbar when deleting tabs in t…
Browse files Browse the repository at this point in the history
…he tab tray
  • Loading branch information
boek committed May 6, 2020
1 parent 69bcfaf commit 02e8a6a
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 96 deletions.
64 changes: 57 additions & 7 deletions app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import android.view.View
import androidx.core.view.isVisible
import mozilla.components.concept.engine.prompt.ShareData
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import mozilla.components.feature.tabs.tabstray.TabsFeature
import kotlinx.android.synthetic.main.fragment_tab_tray.tabsTray
import kotlinx.android.synthetic.main.fragment_tab_tray.view.*
Expand All @@ -28,10 +29,12 @@ import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.collections.SaveCollectionStep
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.sessionsOfType
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.utils.allowUndo

@SuppressWarnings("TooManyFunctions", "LargeClass")
class TabTrayFragment : Fragment(R.layout.fragment_tab_tray), TabsTray.Observer, UserInteractionHandler {
Expand Down Expand Up @@ -130,16 +133,42 @@ class TabTrayFragment : Fragment(R.layout.fragment_tab_tray), TabsTray.Observer,
true
}
R.id.tab_tray_close_menu_item -> {
val tabs = getListOfSessions()
tabs.forEach {
sessionManager.remove(it)
}
closeAllTabs()
true
}
else -> super.onOptionsItemSelected(item)
}
}

private fun closeAllTabs() {
val tabs = getListOfSessions()
val snapshot = tabs
.map(sessionManager::createSessionSnapshot)
.map { it.copy(engineSession = null, engineSessionState = it.engineSession?.saveState()) }
.let { SessionManager.Snapshot(it, -1) }

tabs.forEach {
sessionManager.remove(it)
}

val isPrivate = (activity as HomeActivity).browsingModeManager.mode.isPrivate
val snackbarMessage = if (isPrivate) {
getString(R.string.snackbar_private_tabs_closed)
} else {
getString(R.string.snackbar_tabs_closed)
}

viewLifecycleOwner.lifecycleScope.allowUndo(
requireView(),
snackbarMessage,
getString(R.string.snackbar_deleted_undo),
{
sessionManager.restore(snapshot)
},
operation = { }
)
}

private fun saveToCollection() {
val tabs = getListOfSessions()
val tabIds = tabs.map { it.id }.toList().toTypedArray()
Expand Down Expand Up @@ -169,15 +198,15 @@ class TabTrayFragment : Fragment(R.layout.fragment_tab_tray), TabsTray.Observer,
override fun onStart() {
super.onStart()

tabsFeature?.start()
tabsTray.register(this)
tabsFeature?.start()
}

override fun onStop() {
super.onStop()

tabsFeature?.stop()
tabsTray.unregister(this)
tabsFeature?.stop()
}

override fun onBackPressed(): Boolean {
Expand All @@ -196,7 +225,28 @@ class TabTrayFragment : Fragment(R.layout.fragment_tab_tray), TabsTray.Observer,
}

override fun onTabClosed(tab: Tab) {
// noop
val snapshot = sessionManager
.findSessionById(tab.id)?.let {
sessionManager.createSessionSnapshot(it)
} ?: return

val state = snapshot.engineSession?.saveState()

val snackbarMessage = if (snapshot.session.private) {
getString(R.string.snackbar_private_tab_closed)
} else {
getString(R.string.snackbar_tab_closed)
}

viewLifecycleOwner.lifecycleScope.allowUndo(
requireView(),
snackbarMessage,
getString(R.string.snackbar_deleted_undo),
{
sessionManager.add(snapshot.session, false, engineSessionState = state)
},
operation = { }
)
}

override fun onTabSelected(tab: Tab) {
Expand Down
184 changes: 95 additions & 89 deletions app/src/main/res/layout/fragment_tab_tray.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,102 +2,108 @@
<!-- 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/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:mozac="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:layout_width="match_parent">

<TextView
android:id="@+id/tab_tray_empty_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="@string/no_open_tabs_description"
android:textColor="?secondaryText"
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<mozilla.components.concept.tabstray.TabsTray
android:id="@+id/tabsTray"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/save_to_collection_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
mozac:tabsTrayItemBackgroundColor="?tabTrayItemBackground"
mozac:tabsTrayItemTextColor="?tabTrayItemText"
mozac:tabsTraySelectedItemBackgroundColor="?tabTrayItemSelectedBackground"
mozac:tabsTraySelectedItemTextColor="?tabTrayItemText"
mozac:tabsTrayItemUrlTextColor="?tabTrayItemUrl"
mozac:tabsTraySelectedItemUrlTextColor="?tabTrayItemUrl"/>
android:layout_height="match_parent">

<include
layout="@layout/save_to_collection_button"
android:id="@+id/save_to_collection_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toTopOf="@id/bottomBarShadow"
app:layout_constraintTop_toBottomOf="@+id/tabsTray" />
<TextView
android:id="@+id/tab_tray_empty_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="@string/no_open_tabs_description"
android:textColor="?secondaryText"
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<mozilla.components.concept.tabstray.TabsTray
android:id="@+id/tabsTray"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/save_to_collection_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
mozac:tabsTrayItemBackgroundColor="?tabTrayItemBackground"
mozac:tabsTrayItemTextColor="?tabTrayItemText"
mozac:tabsTraySelectedItemBackgroundColor="?tabTrayItemSelectedBackground"
mozac:tabsTraySelectedItemTextColor="?tabTrayItemText"
mozac:tabsTrayItemUrlTextColor="?tabTrayItemUrl"
mozac:tabsTraySelectedItemUrlTextColor="?tabTrayItemUrl"/>

<include
layout="@layout/save_to_collection_button"
android:id="@+id/save_to_collection_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toTopOf="@id/bottomBarShadow"
app:layout_constraintTop_toBottomOf="@+id/tabsTray" />

<View
android:id="@+id/bottomBarShadow"
android:layout_width="0dp"
android:layout_height="1dp"
android:background="@color/bottom_bar_shadow"
app:layout_constraintBottom_toTopOf="@id/tab_tray_controls"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="@+id/bottomBarShadow"
android:layout_width="0dp"
android:layout_height="1dp"
android:background="@color/bottom_bar_shadow"
app:layout_constraintBottom_toTopOf="@id/tab_tray_controls"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

<View
android:id="@+id/tab_tray_controls"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="?bottomBarBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="@+id/tab_tray_controls"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="?bottomBarBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

<ImageButton
android:id="@+id/private_browsing_button"
android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/content_description_private_browsing_button"
app:srcCompat="@drawable/private_browsing_button"
app:layout_constraintTop_toTopOf="@id/tab_tray_controls"
app:layout_constraintBottom_toBottomOf="@+id/tab_tray_controls"
app:layout_constraintEnd_toStartOf="@+id/tab_tray_go_home"
app:layout_constraintStart_toStartOf="@id/tab_tray_controls" />
<ImageButton
android:id="@+id/private_browsing_button"
android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/content_description_private_browsing_button"
app:srcCompat="@drawable/private_browsing_button"
app:layout_constraintTop_toTopOf="@id/tab_tray_controls"
app:layout_constraintBottom_toBottomOf="@+id/tab_tray_controls"
app:layout_constraintEnd_toStartOf="@+id/tab_tray_go_home"
app:layout_constraintStart_toStartOf="@id/tab_tray_controls" />

<ImageButton
android:id="@+id/tab_tray_go_home"
android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/tab_tray_menu_home"
app:srcCompat="@drawable/ic_home"
app:layout_constraintTop_toTopOf="@id/tab_tray_controls"
app:layout_constraintBottom_toBottomOf="@+id/tab_tray_controls"
app:layout_constraintEnd_toStartOf="@+id/tab_tray_open_new_tab"
app:layout_constraintStart_toEndOf="@+id/private_browsing_button" />
<ImageButton
android:id="@+id/tab_tray_go_home"
android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/tab_tray_menu_home"
app:srcCompat="@drawable/ic_home"
app:layout_constraintTop_toTopOf="@id/tab_tray_controls"
app:layout_constraintBottom_toBottomOf="@+id/tab_tray_controls"
app:layout_constraintEnd_toStartOf="@+id/tab_tray_open_new_tab"
app:layout_constraintStart_toEndOf="@+id/private_browsing_button" />

<ImageButton
android:id="@+id/tab_tray_open_new_tab"
android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/tab_tray_menu_open_new_tab"
app:srcCompat="@drawable/ic_new"
app:layout_constraintTop_toTopOf="@id/tab_tray_controls"
app:layout_constraintBottom_toBottomOf="@+id/tab_tray_controls"
app:layout_constraintEnd_toEndOf="@+id/tab_tray_controls"
app:layout_constraintStart_toEndOf="@+id/tab_tray_go_home" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageButton
android:id="@+id/tab_tray_open_new_tab"
android:layout_width="@dimen/glyph_button_height"
android:layout_height="@dimen/glyph_button_height"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/tab_tray_menu_open_new_tab"
app:srcCompat="@drawable/ic_new"
app:layout_constraintTop_toTopOf="@id/tab_tray_controls"
app:layout_constraintBottom_toBottomOf="@+id/tab_tray_controls"
app:layout_constraintEnd_toEndOf="@+id/tab_tray_controls"
app:layout_constraintStart_toEndOf="@+id/tab_tray_go_home" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

0 comments on commit 02e8a6a

Please sign in to comment.