1
0
Fork 0

For #11851: Close tab tray when last tab closed (#12615)

master
Sawyer Blatz 2020-07-20 11:05:32 -07:00 committed by GitHub
parent 1dc0ad39f4
commit afbb039a08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 27 deletions

View File

@ -117,6 +117,7 @@ class DefaultTabTrayController(
} }
showUndoSnackbar(snackbarMessage, snapshot) showUndoSnackbar(snackbarMessage, snapshot)
dismissTabTray()
} }
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)

View File

@ -38,6 +38,7 @@ import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.TabCollectionStorage import org.mozilla.fenix.components.TabCollectionStorage
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getRootView
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.utils.allowUndo import org.mozilla.fenix.utils.allowUndo
@ -204,19 +205,32 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
getString(R.string.snackbar_tab_closed) getString(R.string.snackbar_tab_closed)
} }
view?.tabLayout?.let { // Check if this is the last tab of this session type
viewLifecycleOwner.lifecycleScope.allowUndo( val isLastOpenTab = sessionManager.sessions.filter { snapshot.session.private }.size == 1
it, val rootView = if (isLastOpenTab) { requireActivity().getRootView()!! } else { requireView().tabLayout }
snackbarMessage, val anchorView = if (isLastOpenTab) { null } else { snackbarAnchor }
getString(R.string.snackbar_deleted_undo),
{ requireActivity().lifecycleScope.allowUndo(
sessionManager.add(snapshot.session, isSelected, engineSessionState = state) rootView,
tabTrayView.scrollToTab(snapshot.session.id) snackbarMessage,
}, getString(R.string.snackbar_deleted_undo),
operation = { }, {
elevation = ELEVATION, sessionManager.add(snapshot.session, isSelected, engineSessionState = state)
anchorView = snackbarAnchor _tabTrayView?.scrollToTab(snapshot.session.id)
) },
operation = { },
elevation = ELEVATION,
paddedForBottomToolbar = isLastOpenTab,
anchorView = anchorView
)
dismissTabTrayIfNecessary()
}
private fun dismissTabTrayIfNecessary() {
if (requireComponents.core.sessionManager.sessions.size == 1) {
findNavController().popBackStack(R.id.homeFragment, false)
dismissAllowingStateLoss()
} }
} }
@ -250,19 +264,20 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
} }
private fun showUndoSnackbar(snackbarMessage: String, snapshot: SessionManager.Snapshot) { private fun showUndoSnackbar(snackbarMessage: String, snapshot: SessionManager.Snapshot) {
view?.let { // Warning: removing this definition and using it directly in the onCancel block will fail silently.
viewLifecycleOwner.lifecycleScope.allowUndo( val sessionManager = view?.context?.components?.core?.sessionManager
it,
snackbarMessage, requireActivity().lifecycleScope.allowUndo(
getString(R.string.snackbar_deleted_undo), requireActivity().getRootView()!!,
{ snackbarMessage,
context?.components?.core?.sessionManager?.restore(snapshot) getString(R.string.snackbar_deleted_undo),
}, {
operation = { }, sessionManager?.restore(snapshot)
elevation = ELEVATION, },
anchorView = snackbarAnchor operation = { },
) elevation = ELEVATION,
} paddedForBottomToolbar = true
)
} }
private fun showCollectionSnackbar(tabSize: Int, isNewCollection: Boolean = false) { private fun showCollectionSnackbar(tabSize: Int, isNewCollection: Boolean = false) {

View File

@ -5,10 +5,12 @@
package org.mozilla.fenix.utils package org.mozilla.fenix.utils
import android.view.View import android.view.View
import androidx.appcompat.widget.ContentFrameLayout
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@ -37,7 +39,8 @@ fun CoroutineScope.allowUndo(
onCancel: suspend () -> Unit = {}, onCancel: suspend () -> Unit = {},
operation: suspend () -> Unit, operation: suspend () -> Unit,
anchorView: View? = null, anchorView: View? = null,
elevation: Float? = null elevation: Float? = null,
paddedForBottomToolbar: Boolean = false
) { ) {
// By using an AtomicBoolean, we achieve memory effects of reading and // By using an AtomicBoolean, we achieve memory effects of reading and
// writing a volatile variable. // writing a volatile variable.
@ -63,6 +66,30 @@ fun CoroutineScope.allowUndo(
snackbar.view.elevation = it snackbar.view.elevation = it
} }
val shouldUseBottomToolbar = view.context.settings().shouldUseBottomToolbar
val toolbarHeight = view.context.resources
.getDimensionPixelSize(R.dimen.browser_toolbar_height)
snackbar.view.setPadding(
0,
0,
0,
if (
paddedForBottomToolbar &&
shouldUseBottomToolbar &&
// If the view passed in is a ContentFrameLayout, it does not matter
// if the user has a dynamicBottomToolbar or not, as the Android system
// can't intelligently position the snackbar on the upper most view.
// Ideally we should not pass ContentFrameLayout in, but it's the only
// way to display snackbars through a fragment transition.
view is ContentFrameLayout
) {
toolbarHeight
} else {
0
}
)
snackbar.show() snackbar.show()
// Wait a bit, and if user didn't request cancellation, proceed with // Wait a bit, and if user didn't request cancellation, proceed with