diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryDataSourceFactory.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryDataSourceFactory.kt index e7d1bca7b..78eb2fc5e 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryDataSourceFactory.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryDataSourceFactory.kt @@ -1,3 +1,7 @@ +/* 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.library.history import androidx.lifecycle.MutableLiveData @@ -7,12 +11,11 @@ import org.mozilla.fenix.components.history.PagedHistoryProvider class HistoryDataSourceFactory( private val historyProvider: PagedHistoryProvider ) : DataSource.Factory() { - - val datasourceLiveData = MutableLiveData() + val datasource = MutableLiveData() override fun create(): DataSource { val datasource = HistoryDataSource(historyProvider) - datasourceLiveData.postValue(datasource) + this.datasource.postValue(datasource) return datasource } } diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt index aa3325496..86626d772 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt @@ -82,6 +82,10 @@ class HistoryFragment : Fragment(), BackHandler { requireComponents.core.historyStorage.createSynchronousPagedHistoryProvider() ) + viewModel.userHasHistory.observe(this, Observer { + historyView.updateEmptyState(it) + }) + requireComponents.analytics.metrics.track(Event.HistoryOpened) setHasOptionsMenu(true) diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryView.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryView.kt index eb32e2954..13c2a079b 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryView.kt @@ -14,10 +14,13 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat +import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.SimpleItemAnimator import kotlinx.android.extensions.LayoutContainer +import kotlinx.android.synthetic.main.component_history.* import kotlinx.android.synthetic.main.component_history.view.* +import kotlinx.android.synthetic.main.component_history.view.history_list import mozilla.components.support.base.feature.BackHandler import org.mozilla.fenix.R import org.mozilla.fenix.ext.asActivity @@ -132,6 +135,11 @@ class HistoryView( mode = state.mode } + fun updateEmptyState(userHasHistory: Boolean) { + history_list.isVisible = userHasHistory + history_empty_view.isVisible = !userHasHistory + } + private fun setUIForSelectingMode(selectedItemSize: Int) { activity?.title = context.getString(R.string.history_multi_select_title, selectedItemSize) @@ -143,8 +151,6 @@ class HistoryView( private fun setUIForNormalMode() { activity?.title = context.getString(R.string.library_history) -// history_list?.isVisible = !isEmpty -// history_empty_view.isVisible = isEmpty setToolbarColors( context!!.getColorResFromAttr(R.attr.primaryText), context.getColorResFromAttr(R.attr.foundation) diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryViewModel.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryViewModel.kt index 0466f098a..37e9bb3d9 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryViewModel.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryViewModel.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.library.history import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.paging.PagedList import androidx.paging.LivePagedListBuilder @@ -12,13 +13,20 @@ import org.mozilla.fenix.components.history.PagedHistoryProvider class HistoryViewModel(historyProvider: PagedHistoryProvider) : ViewModel() { var history: LiveData> + var userHasHistory = MutableLiveData(true) private val datasource: LiveData init { val historyDataSourceFactory = HistoryDataSourceFactory(historyProvider) - datasource = historyDataSourceFactory.datasourceLiveData + datasource = historyDataSourceFactory.datasource - history = LivePagedListBuilder(historyDataSourceFactory, PAGE_SIZE).build() + history = LivePagedListBuilder(historyDataSourceFactory, PAGE_SIZE) + .setBoundaryCallback(object : PagedList.BoundaryCallback() { + override fun onZeroItemsLoaded() { + userHasHistory.value = false + } + }) + .build() } fun invalidate() { diff --git a/app/src/test/java/org/mozilla/fenix/library/history/HistoryInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/library/history/HistoryInteractorTest.kt index 056780a1f..a341c12ac 100644 --- a/app/src/test/java/org/mozilla/fenix/library/history/HistoryInteractorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/library/history/HistoryInteractorTest.kt @@ -4,66 +4,107 @@ package org.mozilla.fenix.library.history +import io.mockk.every import io.mockk.mockk import io.mockk.verify import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Test class HistoryInteractorTest { @Test - fun onHistoryItemOpened() { + fun onPressHistoryItemInNormalMode() { var historyItemReceived: HistoryItem? = null val historyItem = HistoryItem(0, "title", "url", 0.toLong()) + val store: HistoryStore = mockk() + val state: HistoryState = mockk() + every { store.state } returns state + every { state.mode } returns HistoryState.Mode.Normal + val interactor = HistoryInteractor( - mockk(), + store, { historyItemReceived = it }, mockk(), mockk(), mockk() ) - interactor.onHistoryItemOpened(historyItem) + + interactor.onItemPress(historyItem) assertEquals(historyItem, historyItemReceived) } @Test - fun onEnterEditMode() { + fun onPressHistoryItemInEditMode() { + val historyItem = HistoryItem(0, "title", "url", 0.toLong()) val store: HistoryStore = mockk(relaxed = true) - val newHistoryItem: HistoryItem = mockk(relaxed = true) - val interactor = - HistoryInteractor(store, mockk(), mockk(), mockk(), mockk()) - interactor.onEnterEditMode(newHistoryItem) - verify { store.dispatch(HistoryAction.EnterEditMode(newHistoryItem)) } + val state: HistoryState = mockk() + every { store.state } returns state + every { state.mode } returns HistoryState.Mode.Editing(setOf()) + + val interactor = HistoryInteractor( + store, + { }, + mockk(), + mockk(), + mockk() + ) + + interactor.onItemPress(historyItem) + + verify { + store.dispatch(HistoryAction.AddItemForRemoval(historyItem)) + } } @Test - fun onBackPressed() { + fun onPressSelectedHistoryItemInEditMode() { + val historyItem = HistoryItem(0, "title", "url", 0.toLong()) val store: HistoryStore = mockk(relaxed = true) - val interactor = - HistoryInteractor(store, mockk(), mockk(), mockk(), mockk()) - interactor.onBackPressed() - verify { store.dispatch(HistoryAction.ExitEditMode) } + val state: HistoryState = mockk() + every { store.state } returns state + every { state.mode } returns HistoryState.Mode.Editing(setOf(historyItem)) + + val interactor = HistoryInteractor( + store, + { }, + mockk(), + mockk(), + mockk() + ) + + interactor.onItemPress(historyItem) + + verify { + store.dispatch(HistoryAction.RemoveItemForRemoval(historyItem)) + } } @Test - fun onItemAddedForRemoval() { + fun onBackPressedInNormalMode() { val store: HistoryStore = mockk(relaxed = true) - val newHistoryItem: HistoryItem = mockk(relaxed = true) + val state: HistoryState = mockk() + every { store.state } returns state + every { state.mode } returns HistoryState.Mode.Normal - val interactor = - HistoryInteractor(store, mockk(), mockk(), mockk(), mockk()) - interactor.onItemAddedForRemoval(newHistoryItem) - verify { store.dispatch(HistoryAction.AddItemForRemoval(newHistoryItem)) } + val interactor = HistoryInteractor(store, mockk(), mockk(), mockk(), mockk()) + assertFalse(interactor.onBackPressed()) } @Test - fun onItemRemovedForRemoval() { + fun onBackPressedInEditMode() { val store: HistoryStore = mockk(relaxed = true) - val newHistoryItem: HistoryItem = mockk(relaxed = true) - val interactor = - HistoryInteractor(store, mockk(), mockk(), mockk(), mockk()) - interactor.onItemRemovedForRemoval(newHistoryItem) - verify { store.dispatch(HistoryAction.RemoveItemForRemoval(newHistoryItem)) } + val state: HistoryState = mockk() + every { store.state } returns state + every { state.mode } returns HistoryState.Mode.Editing(setOf()) + + val interactor = HistoryInteractor(store, mockk(), mockk(), mockk(), mockk()) + assertTrue(interactor.onBackPressed()) + + verify { + store.dispatch(HistoryAction.ExitEditMode) + } } @Test @@ -96,7 +137,7 @@ class HistoryInteractorTest { @Test fun onDeleteOne() { - var itemsToDelete: List? = null + var itemsToDelete: Set? = null val historyItem = HistoryItem(0, "title", "url", 0.toLong()) val interactor = HistoryInteractor( @@ -107,12 +148,12 @@ class HistoryInteractorTest { { itemsToDelete = it } ) interactor.onDeleteOne(historyItem) - assertEquals(itemsToDelete, listOf(historyItem)) + assertEquals(itemsToDelete, setOf(historyItem)) } @Test fun onDeleteSome() { - var itemsToDelete: List? = null + var itemsToDelete: Set? = null val historyItem = HistoryItem(0, "title", "url", 0.toLong()) val newHistoryItem = HistoryItem(1, "title", "url", 0.toLong()) val interactor = @@ -123,7 +164,7 @@ class HistoryInteractorTest { mockk(), { itemsToDelete = it } ) - interactor.onDeleteSome(listOf(historyItem, newHistoryItem)) - assertEquals(itemsToDelete, listOf(historyItem, newHistoryItem)) + interactor.onDeleteSome(setOf(historyItem, newHistoryItem)) + assertEquals(itemsToDelete, setOf(historyItem, newHistoryItem)) } } diff --git a/app/src/test/java/org/mozilla/fenix/library/history/HistoryStoreTest.kt b/app/src/test/java/org/mozilla/fenix/library/history/HistoryStoreTest.kt index ee55f06f0..cba0e7c22 100644 --- a/app/src/test/java/org/mozilla/fenix/library/history/HistoryStoreTest.kt +++ b/app/src/test/java/org/mozilla/fenix/library/history/HistoryStoreTest.kt @@ -13,15 +13,15 @@ class HistoryStoreTest { private val historyItem = HistoryItem(0, "title", "url", 0.toLong()) private val newHistoryItem = HistoryItem(1, "title", "url", 0.toLong()) - @Test - fun enterEditMode() = runBlocking { - val initialState = emptyDefaultState() - val store = HistoryStore(initialState) - - store.dispatch(HistoryAction.EnterEditMode(historyItem)).join() - assertNotSame(initialState, store.state) - assertEquals(store.state.mode, HistoryState.Mode.Editing(listOf(historyItem))) - } +// @Test +// fun enterEditMode() = runBlocking { +// val initialState = emptyDefaultState() +// val store = HistoryStore(initialState) +// +// store.dispatch(HistoryAction.EnterEditMode(historyItem)).join() +// assertNotSame(initialState, store.state) +// assertEquals(store.state.mode, HistoryState.Mode.Editing(listOf(historyItem))) +// } @Test fun exitEditMode() = runBlocking { @@ -42,7 +42,7 @@ class HistoryStoreTest { assertNotSame(initialState, store.state) assertEquals( store.state.mode, - HistoryState.Mode.Editing(listOf(historyItem, newHistoryItem)) + HistoryState.Mode.Editing(setOf(historyItem, newHistoryItem)) ) } @@ -53,7 +53,7 @@ class HistoryStoreTest { store.dispatch(HistoryAction.RemoveItemForRemoval(newHistoryItem)).join() assertNotSame(initialState, store.state) - assertEquals(store.state.mode, HistoryState.Mode.Editing(listOf(historyItem))) + assertEquals(store.state.mode, HistoryState.Mode.Editing(setOf(historyItem))) } private fun emptyDefaultState(): HistoryState = HistoryState( @@ -63,11 +63,11 @@ class HistoryStoreTest { private fun oneItemEditState(): HistoryState = HistoryState( items = listOf(), - mode = HistoryState.Mode.Editing(listOf(historyItem)) + mode = HistoryState.Mode.Editing(setOf(historyItem)) ) private fun twoItemEditState(): HistoryState = HistoryState( items = listOf(), - mode = HistoryState.Mode.Editing(listOf(historyItem, newHistoryItem)) + mode = HistoryState.Mode.Editing(setOf(historyItem, newHistoryItem)) ) } \ No newline at end of file