mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-15 18:12:54 +00:00
For #21791 Adds tab auto-close prompt
This commit is contained in:
parent
58e12b18e6
commit
08256ac68c
@ -40,7 +40,7 @@ class TrayPagerAdapter(
|
||||
*/
|
||||
private val normalAdapter by lazy {
|
||||
ConcatAdapter(
|
||||
InactiveTabsAdapter(context, browserInteractor, interactor, INACTIVE_TABS_FEATURE_NAME),
|
||||
InactiveTabsAdapter(context, browserInteractor, interactor, INACTIVE_TABS_FEATURE_NAME, context.settings()),
|
||||
TabGroupAdapter(context, browserInteractor, tabsTrayStore, TAB_GROUP_FEATURE_NAME),
|
||||
TitleHeaderAdapter(browserStore, context.settings()),
|
||||
BrowserTabsAdapter(context, browserInteractor, tabsTrayStore, TABS_TRAY_FEATURE_NAME)
|
||||
|
@ -14,6 +14,7 @@ import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.databinding.InactiveFooterItemBinding
|
||||
import org.mozilla.fenix.databinding.InactiveHeaderItemBinding
|
||||
import org.mozilla.fenix.databinding.InactiveTabListItemBinding
|
||||
import org.mozilla.fenix.databinding.InactiveTabsAutoCloseBinding
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.loadIntoView
|
||||
import org.mozilla.fenix.ext.toShortUrl
|
||||
@ -72,6 +73,27 @@ sealed class InactiveTabViewHolder(itemView: View) : RecyclerView.ViewHolder(ite
|
||||
}
|
||||
}
|
||||
|
||||
class AutoCloseDialogHolder(
|
||||
itemView: View,
|
||||
interactor: InactiveTabsAutoCloseDialogInteractor
|
||||
) : InactiveTabViewHolder(itemView) {
|
||||
private val binding = InactiveTabsAutoCloseBinding.bind(itemView)
|
||||
|
||||
init {
|
||||
binding.closeButton.setOnClickListener {
|
||||
interactor.onCloseClicked()
|
||||
}
|
||||
|
||||
binding.action.setOnClickListener {
|
||||
interactor.onEnabledAutoCloseClicked()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAYOUT_ID = R.layout.inactive_tabs_auto_close
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A RecyclerView ViewHolder implementation for an inactive tab view.
|
||||
*
|
||||
|
@ -15,10 +15,12 @@ import mozilla.components.concept.tabstray.TabsTray
|
||||
import mozilla.components.support.base.observer.ObserverRegistry
|
||||
import org.mozilla.fenix.components.Components
|
||||
import org.mozilla.fenix.tabstray.TabsTrayInteractor
|
||||
import org.mozilla.fenix.tabstray.browser.InactiveTabViewHolder.AutoCloseDialogHolder
|
||||
import org.mozilla.fenix.tabstray.browser.InactiveTabViewHolder.FooterHolder
|
||||
import org.mozilla.fenix.tabstray.browser.InactiveTabViewHolder.HeaderHolder
|
||||
import org.mozilla.fenix.tabstray.browser.InactiveTabViewHolder.TabViewHolder
|
||||
import org.mozilla.fenix.tabstray.ext.autoCloseInterval
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import mozilla.components.support.base.observer.Observable as ComponentObservable
|
||||
|
||||
/**
|
||||
@ -44,16 +46,20 @@ class InactiveTabsAdapter(
|
||||
private val browserTrayInteractor: BrowserTrayInteractor,
|
||||
private val tabsTrayInteractor: TabsTrayInteractor,
|
||||
private val featureName: String,
|
||||
private val settings: Settings,
|
||||
delegate: Observable = ObserverRegistry()
|
||||
) : Adapter(DiffCallback), TabsTray, Observable by delegate {
|
||||
|
||||
internal lateinit var inactiveTabsInteractor: InactiveTabsInteractor
|
||||
internal lateinit var inactiveTabsAutoCloseDialogInteractor: InactiveTabsAutoCloseDialogInteractor
|
||||
internal var inActiveTabsCount: Int = 0
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InactiveTabViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(viewType, parent, false)
|
||||
|
||||
return when (viewType) {
|
||||
AutoCloseDialogHolder.LAYOUT_ID -> AutoCloseDialogHolder(view, inactiveTabsAutoCloseDialogInteractor)
|
||||
HeaderHolder.LAYOUT_ID -> HeaderHolder(view, inactiveTabsInteractor, tabsTrayInteractor)
|
||||
TabViewHolder.LAYOUT_ID -> TabViewHolder(view, browserTrayInteractor, featureName)
|
||||
FooterHolder.LAYOUT_ID -> FooterHolder(view)
|
||||
@ -71,7 +77,7 @@ class InactiveTabsAdapter(
|
||||
val item = getItem(position) as Item.Footer
|
||||
holder.bind(item.interval)
|
||||
}
|
||||
is HeaderHolder -> {
|
||||
is HeaderHolder, is AutoCloseDialogHolder -> {
|
||||
// do nothing.
|
||||
}
|
||||
}
|
||||
@ -80,12 +86,19 @@ class InactiveTabsAdapter(
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (position) {
|
||||
0 -> HeaderHolder.LAYOUT_ID
|
||||
1 -> if (settings.shouldShowInactiveTabsAutoCloseDialog(inActiveTabsCount)) {
|
||||
AutoCloseDialogHolder.LAYOUT_ID
|
||||
} else {
|
||||
TabViewHolder.LAYOUT_ID
|
||||
}
|
||||
itemCount - 1 -> FooterHolder.LAYOUT_ID
|
||||
else -> TabViewHolder.LAYOUT_ID
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateTabs(tabs: Tabs) {
|
||||
inActiveTabsCount = tabs.list.size
|
||||
|
||||
// Early return with an empty list to remove the header/footer items.
|
||||
if (tabs.list.isEmpty()) {
|
||||
submitList(emptyList())
|
||||
@ -100,8 +113,12 @@ class InactiveTabsAdapter(
|
||||
|
||||
val items = tabs.list.map { Item.Tab(it) }
|
||||
val footer = Item.Footer(context.autoCloseInterval)
|
||||
|
||||
submitList(listOf(Item.Header) + items + listOf(footer))
|
||||
val headerItems = if (settings.shouldShowInactiveTabsAutoCloseDialog(items.size)) {
|
||||
listOf(Item.Header, Item.AutoCloseMessage)
|
||||
} else {
|
||||
listOf(Item.Header)
|
||||
}
|
||||
submitList(headerItems + items + listOf(footer))
|
||||
}
|
||||
|
||||
override fun isTabSelected(tabs: Tabs, position: Int): Boolean = false
|
||||
@ -136,6 +153,11 @@ class InactiveTabsAdapter(
|
||||
*/
|
||||
data class Tab(val tab: TabsTrayTab) : Item()
|
||||
|
||||
/**
|
||||
* A dialog for when the inactive tabs section reach 20 tabs.
|
||||
*/
|
||||
object AutoCloseMessage : Item()
|
||||
|
||||
/**
|
||||
* A footer for the inactive tab section. This may be seen only
|
||||
* when at least one inactive tab is present.
|
||||
|
@ -0,0 +1,44 @@
|
||||
/* 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.tabstray.browser
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.tabstray.TabsTray
|
||||
import mozilla.components.feature.tabs.ext.toTabs
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class InactiveTabsAutoCloseDialogController(
|
||||
private val browserStore: BrowserStore,
|
||||
private val settings: Settings,
|
||||
private val tabFilter: (TabSessionState) -> Boolean,
|
||||
private val tray: TabsTray
|
||||
) {
|
||||
/**
|
||||
* Dismiss the auto-close dialog.
|
||||
*/
|
||||
fun close() {
|
||||
settings.hasInactiveTabsAutoCloseDialogBeenDismissed = true
|
||||
refeshInactiveTabsSecion()
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the auto-close feature with the after a month setting.
|
||||
*/
|
||||
fun enableAutoClosed() {
|
||||
settings.closeTabsAfterOneMonth = true
|
||||
settings.closeTabsAfterOneWeek = false
|
||||
settings.closeTabsAfterOneDay = false
|
||||
settings.manuallyCloseTabs = false
|
||||
refeshInactiveTabsSecion()
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun refeshInactiveTabsSecion() {
|
||||
val tabs = browserStore.state.toTabs { tabFilter.invoke(it) }
|
||||
tray.updateTabs(tabs)
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/* 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.tabstray.browser
|
||||
|
||||
interface InactiveTabsAutoCloseDialogInteractor {
|
||||
fun onCloseClicked()
|
||||
fun onEnabledAutoCloseClicked()
|
||||
}
|
||||
|
||||
class DefaultInactiveTabsAutoCloseDialogInteractor(
|
||||
private val controller: InactiveTabsAutoCloseDialogController
|
||||
) : InactiveTabsAutoCloseDialogInteractor {
|
||||
override fun onCloseClicked() {
|
||||
controller.close()
|
||||
}
|
||||
|
||||
override fun onEnabledAutoCloseClicked() {
|
||||
controller.enableAutoClosed()
|
||||
}
|
||||
}
|
@ -39,23 +39,35 @@ class NormalBrowserTrayList @JvmOverloads constructor(
|
||||
private val swipeDelegate = SwipeToDeleteDelegate()
|
||||
private val concatAdapter by lazy { adapter as ConcatAdapter }
|
||||
private val tabSorter by lazy { TabSorter(context, concatAdapter, context.components.core.store) }
|
||||
private val inactiveTabsInteractor by lazy {
|
||||
val tabFilter: (TabSessionState) -> Boolean = filter@{
|
||||
if (!context.settings().inactiveTabsAreEnabled) {
|
||||
return@filter false
|
||||
}
|
||||
it.isNormalTabInactive(maxActiveTime)
|
||||
private val inactiveTabsFilter: (TabSessionState) -> Boolean = filter@{
|
||||
if (!context.settings().inactiveTabsAreEnabled) {
|
||||
return@filter false
|
||||
}
|
||||
it.isNormalTabInactive(maxActiveTime)
|
||||
}
|
||||
|
||||
private val inactiveTabsInteractor by lazy {
|
||||
DefaultInactiveTabsInteractor(
|
||||
InactiveTabsController(
|
||||
context.components.core.store,
|
||||
tabFilter,
|
||||
inactiveTabsFilter,
|
||||
concatAdapter.inactiveTabsAdapter,
|
||||
context.components.analytics.metrics
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val inactiveTabsAutoCloseInteractor by lazy {
|
||||
DefaultInactiveTabsAutoCloseDialogInteractor(
|
||||
InactiveTabsAutoCloseDialogController(
|
||||
context.components.core.store,
|
||||
context.settings(),
|
||||
inactiveTabsFilter,
|
||||
concatAdapter.inactiveTabsAdapter
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override val tabsFeature by lazy {
|
||||
TabsFeature(
|
||||
tabSorter,
|
||||
@ -81,6 +93,7 @@ class NormalBrowserTrayList @JvmOverloads constructor(
|
||||
super.onAttachedToWindow()
|
||||
|
||||
concatAdapter.inactiveTabsAdapter.inactiveTabsInteractor = inactiveTabsInteractor
|
||||
concatAdapter.inactiveTabsAdapter.inactiveTabsAutoCloseDialogInteractor = inactiveTabsAutoCloseInteractor
|
||||
|
||||
tabsFeature.start()
|
||||
|
||||
|
@ -67,6 +67,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
||||
private const val CFR_COUNT_CONDITION_FOCUS_INSTALLED = 1
|
||||
private const val CFR_COUNT_CONDITION_FOCUS_NOT_INSTALLED = 3
|
||||
private const val APP_LAUNCHES_TO_SHOW_DEFAULT_BROWSER_CARD = 3
|
||||
private const val INACTIVE_TAB_MINIMUM_TO_SHOW_AUTO_CLOSE_DIALOG = 20
|
||||
|
||||
const val FOUR_HOURS_MS = 60 * 60 * 4 * 1000L
|
||||
const val ONE_DAY_MS = 60 * 60 * 24 * 1000L
|
||||
@ -838,6 +839,26 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
||||
default = true
|
||||
)
|
||||
|
||||
/**
|
||||
* Indicates if the auto-close dialog for inactive tabs has been dismissed before.
|
||||
*/
|
||||
var hasInactiveTabsAutoCloseDialogBeenDismissed by booleanPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_has_inactive_tabs_auto_close_dialog_dismissed),
|
||||
default = false
|
||||
)
|
||||
|
||||
/**
|
||||
* Indicates if the auto-close dialog should be visible based on
|
||||
* if the user has dismissed it before [hasInactiveTabsAutoCloseDialogBeenDismissed],
|
||||
* if the minimum number of tabs has been accumulated [numbersOfTabs]
|
||||
* and if the auto-close setting is already set to [closeTabsAfterOneMonth].
|
||||
*/
|
||||
fun shouldShowInactiveTabsAutoCloseDialog(numbersOfTabs: Int): Boolean {
|
||||
return !hasInactiveTabsAutoCloseDialogBeenDismissed &&
|
||||
numbersOfTabs >= INACTIVE_TAB_MINIMUM_TO_SHOW_AUTO_CLOSE_DIALOG &&
|
||||
!closeTabsAfterOneMonth
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the jump back in CRF should be shown.
|
||||
*/
|
||||
|
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="?toolbarDivider" />
|
||||
|
||||
<corners android:radius="8dp" />
|
||||
|
||||
<solid android:color="?above" />
|
||||
</shape>
|
79
app/src/main/res/layout/inactive_tabs_auto_close.xml
Normal file
79
app/src/main/res/layout/inactive_tabs_auto_close.xml
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:paddingHorizontal="1dp"
|
||||
android:background="@color/photonLightGrey30">
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?above"
|
||||
android:clickable="false"
|
||||
android:clipToPadding="false"
|
||||
android:focusable="true"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/banner_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="false"
|
||||
android:clipToPadding="false"
|
||||
android:background="@drawable/inactive_tab_auto_close_border_background"
|
||||
android:focusable="true"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/banner_info_message"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:padding="8dp"
|
||||
android:text="@string/tab_tray_inactive_auto_close_title"
|
||||
android:textAppearance="@style/Header14TextStyle"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/close_button"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/close_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/tab_tray_inactive_auto_close_button_content_description"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_close" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/message"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:padding="8dp"
|
||||
android:text="@string/tab_tray_inactive_auto_close_body"
|
||||
android:textAppearance="@style/Body14TextStyle"
|
||||
app:layout_constraintTop_toBottomOf="@id/banner_info_message"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/action"
|
||||
style="@style/DialogButtonStyleDark"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="3dp"
|
||||
android:textAllCaps="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:text="@string/tab_tray_inactive_turn_on_auto_close_button"
|
||||
app:layout_constraintTop_toBottomOf="@+id/message" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
@ -227,6 +227,8 @@
|
||||
|
||||
<!-- A value of `true` means the Inactive tabs onboarding popup has not been shown yet -->
|
||||
<string name="pref_key_should_show_inactive_tabs_popup" translatable="false">pref_key_should_show_inactive_tabs_popup</string>
|
||||
<!-- A value of `true` means the Inactive tabs auto close dialog has been dismissed by the user -->
|
||||
<string name="pref_key_has_inactive_tabs_auto_close_dialog_dismissed" translatable="false">pref_key_has_inactive_tabs_auto_close_dialog_dismissed</string>
|
||||
<!-- A value of `true` means the jump back in onboarding popup has not been shown yet -->
|
||||
<string name="pref_key_should_show_jump_back_in_tabs_popup" translatable="false">pref_key_should_show_jump_back_in_tabs_popup</string>
|
||||
|
||||
|
@ -110,6 +110,14 @@
|
||||
<string name="tab_tray_inactive_onboarding_message">Tabs you haven’t viewed for two weeks get moved here.</string>
|
||||
<!-- Text for the action link to go to Settings for inactive tabs. -->
|
||||
<string name="tab_tray_inactive_onboarding_button_text">Turn off in settings</string>
|
||||
<!-- Text for title for the auto-close dialog of the inactive tabs. -->
|
||||
<string name="tab_tray_inactive_auto_close_title">Auto-close after one month?</string>
|
||||
<!-- Text for the body for the auto-close dialog of the inactive tabs. -->
|
||||
<string name="tab_tray_inactive_auto_close_body">Firefox can close tabs you haven’t viewed over the past month.</string>
|
||||
<!-- Content description for close button in the auto-close dialog of the inactive tabs. -->
|
||||
<string name="tab_tray_inactive_auto_close_button_content_description">Close</string>
|
||||
<!-- Text for turn on auto close tabs button in the auto-close dialog of the inactive tabs. -->
|
||||
<string name="tab_tray_inactive_turn_on_auto_close_button">Turn on auto close</string>
|
||||
|
||||
<!-- Home screen icons - Long press shortcuts -->
|
||||
<!-- Shortcut action to open new tab -->
|
||||
|
@ -0,0 +1,32 @@
|
||||
/* 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.tabstray.browser
|
||||
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import org.junit.Test
|
||||
|
||||
class DefaultInactiveTabsAutoCloseDialogInteractorTest {
|
||||
|
||||
@Test
|
||||
fun `WHEN onCloseClicked THEN close`() {
|
||||
val controller: InactiveTabsAutoCloseDialogController = mockk(relaxed = true)
|
||||
val interactor = DefaultInactiveTabsAutoCloseDialogInteractor(controller)
|
||||
|
||||
interactor.onCloseClicked()
|
||||
|
||||
verify { controller.close() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN onEnabledAutoCloseClicked THEN enableAutoClosed`() {
|
||||
val controller: InactiveTabsAutoCloseDialogController = mockk(relaxed = true)
|
||||
val interactor = DefaultInactiveTabsAutoCloseDialogInteractor(controller)
|
||||
|
||||
interactor.onEnabledAutoCloseClicked()
|
||||
|
||||
verify { controller.enableAutoClosed() }
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/* 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.tabstray.browser
|
||||
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.tabstray.TabsTray
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class InactiveTabsAutoCloseDialogControllerTest {
|
||||
|
||||
@Test
|
||||
fun `WHEN close THEN update settings and refresh`() {
|
||||
val filter: (TabSessionState) -> Boolean = { !it.content.private }
|
||||
val store = BrowserStore()
|
||||
val settings: Settings = mockk(relaxed = true)
|
||||
val tray: TabsTray = mockk(relaxed = true)
|
||||
val controller = spyk(InactiveTabsAutoCloseDialogController(store, settings, filter, tray))
|
||||
|
||||
every { controller.refeshInactiveTabsSecion() } just Runs
|
||||
|
||||
controller.close()
|
||||
|
||||
verify { settings.hasInactiveTabsAutoCloseDialogBeenDismissed = true }
|
||||
verify { controller.refeshInactiveTabsSecion() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN enableAutoClosed THEN update closeTabsAfterOneMonth settings and refresh`() {
|
||||
val filter: (TabSessionState) -> Boolean = { !it.content.private }
|
||||
val store = BrowserStore()
|
||||
val settings: Settings = mockk(relaxed = true)
|
||||
val tray: TabsTray = mockk(relaxed = true)
|
||||
val controller = spyk(InactiveTabsAutoCloseDialogController(store, settings, filter, tray))
|
||||
|
||||
every { controller.refeshInactiveTabsSecion() } just Runs
|
||||
|
||||
controller.enableAutoClosed()
|
||||
|
||||
verify { settings.closeTabsAfterOneMonth = true }
|
||||
verify { settings.closeTabsAfterOneWeek = false }
|
||||
verify { settings.closeTabsAfterOneDay = false }
|
||||
verify { settings.manuallyCloseTabs = false }
|
||||
verify { controller.refeshInactiveTabsSecion() }
|
||||
}
|
||||
}
|
@ -753,4 +753,34 @@ class SettingsTest {
|
||||
// Then
|
||||
assertTrue(settings.inactiveTabsAreEnabled)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN shouldShowInactiveTabsAutoCloseDialog WHEN the dialog has been dismissed before THEN no show the dialog`() {
|
||||
val settings = spyk(settings)
|
||||
every { settings.hasInactiveTabsAutoCloseDialogBeenDismissed } returns true
|
||||
|
||||
assertFalse(settings.shouldShowInactiveTabsAutoCloseDialog(20))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN shouldShowInactiveTabsAutoCloseDialog WHEN the inactive tabs are less than the minimum THEN no show the dialog`() {
|
||||
assertFalse(settings.shouldShowInactiveTabsAutoCloseDialog(19))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN shouldShowInactiveTabsAutoCloseDialog WHEN closeTabsAfterOneMonth is already selected THEN no show the dialog`() {
|
||||
val settings = spyk(settings)
|
||||
every { settings.closeTabsAfterOneMonth } returns true
|
||||
|
||||
assertFalse(settings.shouldShowInactiveTabsAutoCloseDialog(19))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN shouldShowInactiveTabsAutoCloseDialog WHEN the dialog has not been dismissed, with more inactive tabs than the queried and closeTabsAfterOneMonth not set THEN show the dialog`() {
|
||||
val settings = spyk(settings)
|
||||
every { settings.closeTabsAfterOneMonth } returns false
|
||||
every { settings.hasInactiveTabsAutoCloseDialogBeenDismissed } returns false
|
||||
|
||||
assertTrue(settings.shouldShowInactiveTabsAutoCloseDialog(20))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user