#2154 more merging of viewmodels bookmark and history

This commit is contained in:
Frans-Lukas 2020-07-01 20:01:24 +02:00
parent 8679e390f2
commit 37418efb53
9 changed files with 77 additions and 44 deletions

View File

@ -1,11 +1,12 @@
package org.kiwix.kiwixmobile.core.page.bookmark package org.kiwix.kiwixmobile.core.page.bookmark
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.di.components.CoreComponent
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.viewModel import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.viewModel
import org.kiwix.kiwixmobile.core.page.PageActivity import org.kiwix.kiwixmobile.core.page.PageActivity
import org.kiwix.kiwixmobile.core.page.adapter.PageAdapter import org.kiwix.kiwixmobile.core.page.adapter.PageAdapter
import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.BookmarkViewModel
import org.kiwix.kiwixmobile.core.page.adapter.PageDelegate.PageItemDelegate import org.kiwix.kiwixmobile.core.page.adapter.PageDelegate.PageItemDelegate
import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.BookmarkViewModel
class BookmarksActivity : PageActivity() { class BookmarksActivity : PageActivity() {
override val pageViewModel by lazy { viewModel<BookmarkViewModel>(viewModelFactory) } override val pageViewModel by lazy { viewModel<BookmarkViewModel>(viewModelFactory) }
@ -14,6 +15,10 @@ class BookmarksActivity : PageActivity() {
PageAdapter(PageItemDelegate(this)) PageAdapter(PageItemDelegate(this))
} }
override fun injection(coreComponent: CoreComponent) {
activityComponent.inject(this)
}
override val title: String by lazy { getString(R.string.bookmarks) } override val title: String by lazy { getString(R.string.bookmarks) }
override val noItemsString: String by lazy { getString(R.string.no_bookmarks) } override val noItemsString: String by lazy { getString(R.string.no_bookmarks) }
override val switchString: String by lazy { getString(R.string.bookmarks_from_current_book) } override val switchString: String by lazy { getString(R.string.bookmarks_from_current_book) }

View File

@ -31,13 +31,13 @@ import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import javax.inject.Inject import javax.inject.Inject
class BookmarkViewModel @Inject constructor( class BookmarkViewModel @Inject constructor(
override val pageDao: NewBookmarksDao, bookmarksDao: NewBookmarksDao,
override val zimReaderContainer: ZimReaderContainer, override val zimReaderContainer: ZimReaderContainer,
override val sharedPreferenceUtil: SharedPreferenceUtil override val sharedPreferenceUtil: SharedPreferenceUtil
) : PageViewModel<BookmarkState>() { ) : PageViewModel<BookmarkState>(bookmarksDao) {
override fun initialState(): BookmarkState = override fun initialState(): BookmarkState =
BookmarkState(emptyList(), sharedPreferenceUtil.showBookmarksAllBooks, zimReaderContainer.id) BookmarkState(emptyList(), true, null)
init { init {
compositeDisposable.addAll( compositeDisposable.addAll(
@ -61,11 +61,9 @@ class BookmarkViewModel @Inject constructor(
return (state as BookmarkState).copy(showAll = action.isChecked) return (state as BookmarkState).copy(showAll = action.isChecked)
} }
override fun offerShowDeleteDialog(state: PageState): PageState {
effects.offer(ShowDeleteBookmarksDialog(effects, state as BookmarkState, pageDao))
return state
}
override fun deselectAllPages(state: PageState): PageState = override fun deselectAllPages(state: PageState): PageState =
(state as BookmarkState).copy(pageItems = state.pageItems.map { it.copy(isSelected = false) }) (state as BookmarkState).copy(pageItems = state.pageItems.map { it.copy(isSelected = false) })
override fun createDeletePageDialogEffect(state: PageState) =
ShowDeleteBookmarksDialog(effects, state as BookmarkState, pageDao)
} }

View File

@ -21,7 +21,7 @@ package org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.effects
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import io.reactivex.processors.PublishProcessor import io.reactivex.processors.PublishProcessor
import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.page.bookmark.BookmarksActivity import org.kiwix.kiwixmobile.core.page.bookmark.BookmarksActivity
import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.BookmarkState import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.BookmarkState
import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems
@ -33,7 +33,7 @@ import javax.inject.Inject
data class ShowDeleteBookmarksDialog( data class ShowDeleteBookmarksDialog(
private val effects: PublishProcessor<SideEffect<*>>, private val effects: PublishProcessor<SideEffect<*>>,
private val state: BookmarkState, private val state: BookmarkState,
private val bookmarksDao: NewBookmarksDao private val bookmarksDao: PageDao
) : SideEffect<Unit> { ) : SideEffect<Unit> {
@Inject lateinit var dialogShower: DialogShower @Inject lateinit var dialogShower: DialogShower
override fun invokeWith(activity: AppCompatActivity) { override fun invokeWith(activity: AppCompatActivity) {

View File

@ -1,6 +1,7 @@
package org.kiwix.kiwixmobile.core.page.history package org.kiwix.kiwixmobile.core.page.history
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.di.components.CoreComponent
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.viewModel import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.viewModel
import org.kiwix.kiwixmobile.core.page.PageActivity import org.kiwix.kiwixmobile.core.page.PageActivity
import org.kiwix.kiwixmobile.core.page.adapter.PageAdapter import org.kiwix.kiwixmobile.core.page.adapter.PageAdapter
@ -17,6 +18,10 @@ class HistoryActivity : PageActivity() {
PageAdapter(PageItemDelegate(this), HistoryDateDelegate()) PageAdapter(PageItemDelegate(this), HistoryDateDelegate())
} }
override fun injection(coreComponent: CoreComponent) {
activityComponent.inject(this)
}
override val noItemsString: String by lazy { getString(R.string.no_history) } override val noItemsString: String by lazy { getString(R.string.no_history) }
override val switchString: String by lazy { getString(R.string.history_from_current_book) } override val switchString: String by lazy { getString(R.string.history_from_current_book) }
override val title: String by lazy { getString(R.string.history) } override val title: String by lazy { getString(R.string.history) }

View File

@ -18,7 +18,6 @@
package org.kiwix.kiwixmobile.core.page.history.viewmodel package org.kiwix.kiwixmobile.core.page.history.viewmodel
import io.reactivex.schedulers.Schedulers
import org.kiwix.kiwixmobile.core.dao.HistoryDao import org.kiwix.kiwixmobile.core.dao.HistoryDao
import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem
import org.kiwix.kiwixmobile.core.page.history.viewmodel.effects.ShowDeleteHistoryDialog import org.kiwix.kiwixmobile.core.page.history.viewmodel.effects.ShowDeleteHistoryDialog
@ -31,21 +30,13 @@ import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import javax.inject.Inject import javax.inject.Inject
class HistoryViewModel @Inject constructor( class HistoryViewModel @Inject constructor(
override val pageDao: HistoryDao,
override val zimReaderContainer: ZimReaderContainer, override val zimReaderContainer: ZimReaderContainer,
override val sharedPreferenceUtil: SharedPreferenceUtil override val sharedPreferenceUtil: SharedPreferenceUtil,
) : PageViewModel<HistoryState>() { historyDao: HistoryDao
) : PageViewModel<HistoryState>(historyDao) {
override fun initialState(): HistoryState = override fun initialState(): HistoryState =
HistoryState(emptyList(), sharedPreferenceUtil.showHistoryAllBooks, zimReaderContainer.id) HistoryState(emptyList(), true, null)
init {
compositeDisposable.addAll(
viewStateReducer(),
pageDao.pages().subscribeOn(Schedulers.io())
.subscribe({ actions.offer(Action.UpdatePages(it)) }, Throwable::printStackTrace)
)
}
override fun updatePagesBasedOnFilter(state: PageState, action: Action.Filter): PageState = override fun updatePagesBasedOnFilter(state: PageState, action: Action.Filter): PageState =
(state as HistoryState).copy(searchTerm = action.searchTerm) (state as HistoryState).copy(searchTerm = action.searchTerm)
@ -61,10 +52,8 @@ class HistoryViewModel @Inject constructor(
return (state as HistoryState).copy(showAll = action.isChecked) return (state as HistoryState).copy(showAll = action.isChecked)
} }
override fun offerShowDeleteDialog(state: PageState): PageState { override fun createDeletePageDialogEffect(state: PageState) =
effects.offer(ShowDeleteHistoryDialog(effects, state as HistoryState, pageDao)) ShowDeleteHistoryDialog(effects, state as HistoryState, pageDao)
return state
}
override fun deselectAllPages(state: PageState): PageState = override fun deselectAllPages(state: PageState): PageState =
(state as HistoryState).copy(pageItems = state.pageItems.map { it.copy(isSelected = false) }) (state as HistoryState).copy(pageItems = state.pageItems.map { it.copy(isSelected = false) })

View File

@ -21,7 +21,7 @@ package org.kiwix.kiwixmobile.core.page.history.viewmodel.effects
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import io.reactivex.processors.PublishProcessor import io.reactivex.processors.PublishProcessor
import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.HistoryDao import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.page.history.HistoryActivity import org.kiwix.kiwixmobile.core.page.history.HistoryActivity
import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryState import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryState
import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems
@ -33,7 +33,7 @@ import javax.inject.Inject
data class ShowDeleteHistoryDialog( data class ShowDeleteHistoryDialog(
private val effects: PublishProcessor<SideEffect<*>>, private val effects: PublishProcessor<SideEffect<*>>,
private val state: HistoryState, private val state: HistoryState,
private val historyDao: HistoryDao private val historyDao: PageDao
) : SideEffect<Unit> { ) : SideEffect<Unit> {
@Inject lateinit var dialogShower: DialogShower @Inject lateinit var dialogShower: DialogShower
override fun invokeWith(activity: AppCompatActivity) { override fun invokeWith(activity: AppCompatActivity) {

View File

@ -23,6 +23,7 @@ import androidx.lifecycle.ViewModel
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.processors.PublishProcessor import io.reactivex.processors.PublishProcessor
import io.reactivex.schedulers.Schedulers
import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.PageDao import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.page.viewmodel.Action.Exit import org.kiwix.kiwixmobile.core.page.viewmodel.Action.Exit
@ -39,17 +40,24 @@ import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.Finish import org.kiwix.kiwixmobile.core.search.viewmodel.effects.Finish
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
abstract class PageViewModel<out T : PageState> : ViewModel() { abstract class PageViewModel<out T : PageState>(val pageDao: PageDao) : ViewModel() {
abstract val zimReaderContainer: ZimReaderContainer abstract val zimReaderContainer: ZimReaderContainer
abstract val sharedPreferenceUtil: SharedPreferenceUtil abstract val sharedPreferenceUtil: SharedPreferenceUtil
abstract val pageDao: PageDao
val state = MutableLiveData<PageState>().apply { val state = MutableLiveData<PageState>().apply {
value = initialState() value = initialState()
} }
val compositeDisposable = CompositeDisposable()
val effects = PublishProcessor.create<SideEffect<*>>() val effects = PublishProcessor.create<SideEffect<*>>()
val actions = PublishProcessor.create<Action>() val actions = PublishProcessor.create<Action>()
val compositeDisposable = CompositeDisposable()
init {
compositeDisposable.addAll(
viewStateReducer(),
pageDao.pages().subscribeOn(Schedulers.io())
.subscribe({ actions.offer(Action.UpdatePages(it)) }, Throwable::printStackTrace)
)
}
fun viewStateReducer(): Disposable = fun viewStateReducer(): Disposable =
actions.map { reduce(it, state.value!!) } actions.map { reduce(it, state.value!!) }
@ -77,6 +85,11 @@ abstract class PageViewModel<out T : PageState> : ViewModel() {
state: PageState state: PageState
): PageState ): PageState
private fun offerShowDeleteDialog(state: PageState): PageState {
effects.offer(createDeletePageDialogEffect(state))
return state
}
private fun handleItemLongClick(state: PageState, action: OnItemLongClick): PageState = private fun handleItemLongClick(state: PageState, action: OnItemLongClick): PageState =
state.toggleSelectionOfItem(action.page) state.toggleSelectionOfItem(action.page)
@ -88,8 +101,6 @@ abstract class PageViewModel<out T : PageState> : ViewModel() {
return state return state
} }
abstract fun offerShowDeleteDialog(state: PageState): PageState
abstract fun deselectAllPages(state: PageState): PageState abstract fun deselectAllPages(state: PageState): PageState
private fun finishActivity(state: PageState): PageState { private fun finishActivity(state: PageState): PageState {
@ -101,4 +112,6 @@ abstract class PageViewModel<out T : PageState> : ViewModel() {
compositeDisposable.clear() compositeDisposable.clear()
super.onCleared() super.onCleared()
} }
abstract fun createDeletePageDialogEffect(state: PageState): SideEffect<*>
} }

View File

@ -84,14 +84,26 @@ internal class HistoryViewModelTest {
@Test @Test
internal fun `UserClickedDeleteButton offers ShowDeleteHistoryDialog`() { internal fun `UserClickedDeleteButton offers ShowDeleteHistoryDialog`() {
viewModel.effects.test().also { viewModel.actions.offer(UserClickedDeleteButton) } viewModel.effects.test().also { viewModel.actions.offer(UserClickedDeleteButton) }
.assertValue(ShowDeleteHistoryDialog(viewModel.effects, historyState(), historyDao)) .assertValue(
ShowDeleteHistoryDialog(
viewModel.effects,
historyState(),
historyDao
)
)
viewModel.state.test().assertValue(historyState()) viewModel.state.test().assertValue(historyState())
} }
@Test @Test
internal fun `UserClickedDeleteSelectedHistoryItems offers ShowDeleteHistoryDialog`() { internal fun `UserClickedDeleteSelectedHistoryItems offers ShowDeleteHistoryDialog`() {
viewModel.effects.test().also { viewModel.actions.offer(UserClickedDeleteSelectedPages) } viewModel.effects.test().also { viewModel.actions.offer(UserClickedDeleteSelectedPages) }
.assertValue(ShowDeleteHistoryDialog(viewModel.effects, historyState(), historyDao)) .assertValue(
ShowDeleteHistoryDialog(
viewModel.effects,
historyState(),
historyDao
)
)
viewModel.state.test().assertValue(historyState()) viewModel.state.test().assertValue(historyState())
} }

View File

@ -24,7 +24,12 @@ internal class ShowDeleteHistoryDialogTest {
@Test @Test
fun `invoke with shows dialog that offers ConfirmDelete action`() { fun `invoke with shows dialog that offers ConfirmDelete action`() {
val showDeleteHistoryDialog = ShowDeleteHistoryDialog(effects, historyState(), historyDao) val showDeleteHistoryDialog =
ShowDeleteHistoryDialog(
effects,
historyState(),
historyDao
)
mockkActivityInjection(showDeleteHistoryDialog) mockkActivityInjection(showDeleteHistoryDialog)
val lambdaSlot = slot<() -> Unit>() val lambdaSlot = slot<() -> Unit>()
showDeleteHistoryDialog.invokeWith(activity) showDeleteHistoryDialog.invokeWith(activity)
@ -35,11 +40,12 @@ internal class ShowDeleteHistoryDialogTest {
@Test @Test
fun `invoke with selected item shows dialog with delete selected items title`() { fun `invoke with selected item shows dialog with delete selected items title`() {
val showDeleteHistoryDialog = ShowDeleteHistoryDialog( val showDeleteHistoryDialog =
effects, ShowDeleteHistoryDialog(
historyState(listOf(historyItem(isSelected = true))), effects,
historyDao historyState(listOf(historyItem(isSelected = true))),
) historyDao
)
mockkActivityInjection(showDeleteHistoryDialog) mockkActivityInjection(showDeleteHistoryDialog)
showDeleteHistoryDialog.invokeWith(activity) showDeleteHistoryDialog.invokeWith(activity)
verify { dialogShower.show(DeleteSelectedHistory, any()) } verify { dialogShower.show(DeleteSelectedHistory, any()) }
@ -47,7 +53,12 @@ internal class ShowDeleteHistoryDialogTest {
@Test @Test
fun `invoke with no selected items shows dialog with delete all items title`() { fun `invoke with no selected items shows dialog with delete all items title`() {
val showDeleteHistoryDialog = ShowDeleteHistoryDialog(effects, historyState(), historyDao) val showDeleteHistoryDialog =
ShowDeleteHistoryDialog(
effects,
historyState(),
historyDao
)
mockkActivityInjection(showDeleteHistoryDialog) mockkActivityInjection(showDeleteHistoryDialog)
showDeleteHistoryDialog.invokeWith(activity) showDeleteHistoryDialog.invokeWith(activity)
verify { dialogShower.show(DeleteAllHistory, any()) } verify { dialogShower.show(DeleteAllHistory, any()) }