mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-16 19:05:27 -04:00
#2119 re-re-write of History activity
This commit is contained in:
parent
935536b027
commit
0b699fd89d
@ -67,10 +67,9 @@ class Repository @Inject internal constructor(
|
|||||||
override fun booksOnDiskAsListItems(): Flowable<List<BooksOnDiskListItem>> = bookDao.books()
|
override fun booksOnDiskAsListItems(): Flowable<List<BooksOnDiskListItem>> = bookDao.books()
|
||||||
.map { it.sortedBy { bookOnDisk -> bookOnDisk.book.language + bookOnDisk.book.title } }
|
.map { it.sortedBy { bookOnDisk -> bookOnDisk.book.language + bookOnDisk.book.title } }
|
||||||
.map {
|
.map {
|
||||||
HeaderizableList(it as List<BooksOnDiskListItem>).foldOverAddingHeaders(
|
HeaderizableList<BooksOnDiskListItem, BookOnDisk, LanguageItem>(it).foldOverAddingHeaders(
|
||||||
{ bookOnDisk -> LanguageItem((bookOnDisk as BookOnDisk).locale) },
|
{ bookOnDisk -> LanguageItem(bookOnDisk.locale) },
|
||||||
{ current, next ->
|
{ current, next -> current.locale.displayName != next.locale.displayName })
|
||||||
(current as BookOnDisk).locale.displayName != (next as BookOnDisk).locale.displayName })
|
|
||||||
}
|
}
|
||||||
.map { it.toList() }
|
.map { it.toList() }
|
||||||
|
|
||||||
@ -93,10 +92,11 @@ class Repository @Inject internal constructor(
|
|||||||
zimReaderContainer.zimCanonicalPath
|
zimReaderContainer.zimCanonicalPath
|
||||||
)
|
)
|
||||||
).map {
|
).map {
|
||||||
HeaderizableList(it as List<HistoryListItem>).foldOverAddingHeaders(
|
HeaderizableList<HistoryListItem, HistoryItem, DateItem>(it).foldOverAddingHeaders(
|
||||||
{ historyItem -> DateItem((historyItem as HistoryItem).dateString) },
|
{ historyItem -> DateItem(historyItem.dateString) },
|
||||||
{ current, next ->
|
{ current, next ->
|
||||||
(current as HistoryItem).dateString != (next as HistoryItem).dateString })
|
current.dateString != next.dateString
|
||||||
|
})
|
||||||
}
|
}
|
||||||
.subscribeOn(io)
|
.subscribeOn(io)
|
||||||
.observeOn(mainThread)
|
.observeOn(mainThread)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.kiwix.kiwixmobile.core.extensions
|
package org.kiwix.kiwixmobile.core.extensions
|
||||||
|
|
||||||
inline class HeaderizableList<SUPERTYPE, ITEM : SUPERTYPE, HEADER : SUPERTYPE>(
|
inline class HeaderizableList<SUPERTYPE, out ITEM : SUPERTYPE, in HEADER : SUPERTYPE>(
|
||||||
val list: List<ITEM>
|
val list: List<ITEM>
|
||||||
) {
|
) {
|
||||||
fun foldOverAddingHeaders(
|
fun foldOverAddingHeaders(
|
||||||
@ -13,7 +13,7 @@ inline class HeaderizableList<SUPERTYPE, ITEM : SUPERTYPE, HEADER : SUPERTYPE>(
|
|||||||
}
|
}
|
||||||
acc.add(currentItem)
|
acc.add(currentItem)
|
||||||
if (index < list.size - 1) {
|
if (index < list.size - 1) {
|
||||||
val nextItem = list.get(index + 1)
|
val nextItem = list[index + 1]
|
||||||
if (criteriaToAddHeader.invoke(currentItem, nextItem)) {
|
if (criteriaToAddHeader.invoke(currentItem, nextItem)) {
|
||||||
acc.add(headerConstructor.invoke(nextItem))
|
acc.add(headerConstructor.invoke(nextItem))
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import kotlinx.android.synthetic.main.activity_history.no_history
|
|||||||
import kotlinx.android.synthetic.main.activity_history.recycler_view
|
import kotlinx.android.synthetic.main.activity_history.recycler_view
|
||||||
import kotlinx.android.synthetic.main.layout_toolbar.toolbar
|
import kotlinx.android.synthetic.main.layout_toolbar.toolbar
|
||||||
import org.kiwix.kiwixmobile.core.R
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import org.kiwix.kiwixmobile.core.R.id
|
|
||||||
import org.kiwix.kiwixmobile.core.R.string
|
import org.kiwix.kiwixmobile.core.R.string
|
||||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||||
import org.kiwix.kiwixmobile.core.di.components.CoreComponent
|
import org.kiwix.kiwixmobile.core.di.components.CoreComponent
|
||||||
@ -33,12 +32,11 @@ import org.kiwix.kiwixmobile.core.history.viewmodel.Action
|
|||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitHistory
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitHistory
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.Filter
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.Filter
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemLongClick
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemLongClick
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.RequestDeleteAllHistoryItems
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.RequestDeleteSelectedHistoryItems
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ToggleShowHistoryFromAllBooks
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ToggleShowHistoryFromAllBooks
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDeleteButton
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDeleteSelectedHistoryItems
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.HistoryViewModel
|
import org.kiwix.kiwixmobile.core.history.viewmodel.HistoryViewModel
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State
|
import org.kiwix.kiwixmobile.core.history.viewmodel.State
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.NoResults
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.Results
|
import org.kiwix.kiwixmobile.core.history.viewmodel.State.Results
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.SelectionResults
|
import org.kiwix.kiwixmobile.core.history.viewmodel.State.SelectionResults
|
||||||
import org.kiwix.kiwixmobile.core.utils.SimpleTextListener
|
import org.kiwix.kiwixmobile.core.utils.SimpleTextListener
|
||||||
@ -60,13 +58,11 @@ class HistoryActivity : OnItemClickListener, BaseActivity() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean = false
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||||
if (item.itemId == R.id.menu_context_delete) {
|
if (item.itemId == R.id.menu_context_delete) {
|
||||||
historyViewModel.actions.offer(RequestDeleteSelectedHistoryItems)
|
historyViewModel.actions.offer(UserClickedDeleteSelectedHistoryItems)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
historyViewModel.actions.offer(Action.ExitActionModeMenu)
|
historyViewModel.actions.offer(Action.ExitActionModeMenu)
|
||||||
@ -101,7 +97,7 @@ class HistoryActivity : OnItemClickListener, BaseActivity() {
|
|||||||
history_switch.setOnCheckedChangeListener { _, isChecked ->
|
history_switch.setOnCheckedChangeListener { _, isChecked ->
|
||||||
historyViewModel.actions.offer(ToggleShowHistoryFromAllBooks(isChecked))
|
historyViewModel.actions.offer(ToggleShowHistoryFromAllBooks(isChecked))
|
||||||
}
|
}
|
||||||
history_switch.isChecked = !sharedPreferenceUtil.showHistoryCurrentBook
|
history_switch.isChecked = !sharedPreferenceUtil.showHistoryAllBooks
|
||||||
|
|
||||||
compositeDisposable.add(historyViewModel.effects.subscribe { it.invokeWith(this) })
|
compositeDisposable.add(historyViewModel.effects.subscribe { it.invokeWith(this) })
|
||||||
}
|
}
|
||||||
@ -127,7 +123,7 @@ class HistoryActivity : OnItemClickListener, BaseActivity() {
|
|||||||
historyViewModel.actions.offer(ExitHistory)
|
historyViewModel.actions.offer(ExitHistory)
|
||||||
}
|
}
|
||||||
if (item.itemId == R.id.menu_history_clear) {
|
if (item.itemId == R.id.menu_history_clear) {
|
||||||
historyViewModel.actions.offer(RequestDeleteAllHistoryItems)
|
historyViewModel.actions.offer(UserClickedDeleteButton)
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
@ -136,23 +132,18 @@ class HistoryActivity : OnItemClickListener, BaseActivity() {
|
|||||||
when (state) {
|
when (state) {
|
||||||
is Results -> {
|
is Results -> {
|
||||||
actionMode?.finish()
|
actionMode?.finish()
|
||||||
state.historyItems?.let { historyAdapter.items = it }
|
state.historyListItems.let { historyAdapter.items = it }
|
||||||
history_switch.isEnabled = true
|
history_switch.isEnabled = true
|
||||||
no_history.visibility = View.GONE
|
no_history.visibility = View.GONE
|
||||||
}
|
}
|
||||||
is SelectionResults -> {
|
is SelectionResults -> {
|
||||||
if (state.historyItems?.filterIsInstance<HistoryItem>()?.any { it.isSelected } == true &&
|
if (state.historyItems.any(HistoryItem::isSelected) && actionMode == null) {
|
||||||
actionMode == null) {
|
|
||||||
actionMode = startSupportActionMode(actionModeCallback)
|
actionMode = startSupportActionMode(actionModeCallback)
|
||||||
}
|
}
|
||||||
state.historyItems?.let { historyAdapter.items = it }
|
state.historyListItems.let { historyAdapter.items = it }
|
||||||
history_switch.isEnabled = false
|
history_switch.isEnabled = false
|
||||||
no_history.visibility = View.GONE
|
no_history.visibility = View.GONE
|
||||||
}
|
}
|
||||||
is NoResults -> {
|
|
||||||
state.historyItems?.let { historyAdapter.items = it }
|
|
||||||
no_history.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClick(favicon: ImageView, history: HistoryItem) {
|
override fun onItemClick(favicon: ImageView, history: HistoryItem) {
|
||||||
|
@ -18,18 +18,19 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.history.viewmodel
|
package org.kiwix.kiwixmobile.core.history.viewmodel
|
||||||
|
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem
|
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
||||||
|
|
||||||
sealed class Action {
|
sealed class Action {
|
||||||
object ExitHistory : Action()
|
object ExitHistory : Action()
|
||||||
object ExitActionModeMenu : Action()
|
object ExitActionModeMenu : Action()
|
||||||
object DeleteHistoryItems : Action()
|
object UserClickedDelete : Action()
|
||||||
object RequestDeleteAllHistoryItems : Action()
|
object UserClickedDeleteButton : Action()
|
||||||
object RequestDeleteSelectedHistoryItems : Action()
|
object UserClickedDeleteSelectedHistoryItems : Action()
|
||||||
|
|
||||||
data class OnItemClick(val historyListItem: HistoryListItem) : Action()
|
data class OnItemClick(val historyItem: HistoryItem) : Action()
|
||||||
data class OnItemLongClick(val historyItem: HistoryItem) : Action()
|
data class OnItemLongClick(val historyItem: HistoryItem) : Action()
|
||||||
data class ToggleShowHistoryFromAllBooks(val isChecked: Boolean) : Action()
|
data class ToggleShowHistoryFromAllBooks(val isChecked: Boolean) : Action()
|
||||||
|
data class AllHistoryPreferenceChanged(val showAll: Boolean) : Action()
|
||||||
data class Filter(val searchTerm: String) : Action()
|
data class Filter(val searchTerm: String) : Action()
|
||||||
|
data class UpdateHistory(val history: List<HistoryItem>) : Action()
|
||||||
}
|
}
|
||||||
|
@ -1,41 +1,31 @@
|
|||||||
package org.kiwix.kiwixmobile.core.history.viewmodel
|
package org.kiwix.kiwixmobile.core.history.viewmodel
|
||||||
|
|
||||||
import DeleteSelectedOrAllHistoryItems
|
|
||||||
import OpenHistoryItem
|
import OpenHistoryItem
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import io.reactivex.Flowable
|
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.functions.Function3
|
|
||||||
import io.reactivex.processors.BehaviorProcessor
|
|
||||||
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.HistoryDao
|
||||||
import org.kiwix.kiwixmobile.core.extensions.HeaderizableList
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.AllHistoryPreferenceChanged
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem
|
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.DateItem
|
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.DeleteHistoryItems
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitActionModeMenu
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitActionModeMenu
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitHistory
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitHistory
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.Filter
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.Filter
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemClick
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemClick
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemLongClick
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemLongClick
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.RequestDeleteAllHistoryItems
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.RequestDeleteSelectedHistoryItems
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ToggleShowHistoryFromAllBooks
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ToggleShowHistoryFromAllBooks
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.NoResults
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UpdateHistory
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDelete
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDeleteButton
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDeleteSelectedHistoryItems
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.Results
|
import org.kiwix.kiwixmobile.core.history.viewmodel.State.Results
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.SelectionResults
|
import org.kiwix.kiwixmobile.core.history.viewmodel.State.SelectionResults
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.DeleteHistoryItems
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.ShowDeleteHistoryDialog
|
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.ShowDeleteHistoryDialog
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.ToggleShowAllHistorySwitchAndSaveItsStateToPrefs
|
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.UpdateAllHistoryPreference
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
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.KiwixDialog.DeleteAllHistory
|
|
||||||
import org.kiwix.kiwixmobile.core.utils.KiwixDialog.DeleteSelectedHistory
|
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Locale
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class HistoryViewModel @Inject constructor(
|
class HistoryViewModel @Inject constructor(
|
||||||
@ -43,133 +33,142 @@ class HistoryViewModel @Inject constructor(
|
|||||||
private val zimReaderContainer: ZimReaderContainer,
|
private val zimReaderContainer: ZimReaderContainer,
|
||||||
private val sharedPreferenceUtil: SharedPreferenceUtil
|
private val sharedPreferenceUtil: SharedPreferenceUtil
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val state = MutableLiveData<State>().apply { value = NoResults(emptyList()) }
|
val state = MutableLiveData<State>().apply {
|
||||||
|
value = Results(emptyList(), sharedPreferenceUtil.showHistoryAllBooks)
|
||||||
|
}
|
||||||
val effects = PublishProcessor.create<SideEffect<*>>()
|
val effects = PublishProcessor.create<SideEffect<*>>()
|
||||||
val actions = PublishProcessor.create<Action>()
|
val actions = PublishProcessor.create<Action>()
|
||||||
private val filter = BehaviorProcessor.createDefault("")
|
|
||||||
private val compositeDisposable = CompositeDisposable()
|
private val compositeDisposable = CompositeDisposable()
|
||||||
val showAllSwitchToggle =
|
|
||||||
BehaviorProcessor.createDefault(!sharedPreferenceUtil.showHistoryCurrentBook)
|
|
||||||
private val dateFormatter = SimpleDateFormat("d MMM yyyy", Locale.getDefault())
|
|
||||||
private val deselectAllItems = BehaviorProcessor.createDefault(false)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
compositeDisposable.addAll(
|
compositeDisposable.addAll(
|
||||||
viewStateReducer(),
|
historyDao.history().subscribe { actions.offer(UpdateHistory(it)) },
|
||||||
actionMapper(),
|
sharedPreferenceUtil.showAllHistoryToggleSwitch.subscribe {
|
||||||
deselectAllItems()
|
actions.offer(AllHistoryPreferenceChanged(it))
|
||||||
|
},
|
||||||
|
viewStateReducer()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deselectAllItems() = deselectAllItems.subscribe {
|
|
||||||
state.value?.historyItems?.filterIsInstance<HistoryItem>()?.forEach { it.isSelected = false }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun viewStateReducer() =
|
private fun viewStateReducer() =
|
||||||
Flowable.combineLatest(
|
actions.map { reduce(it, state.value!!) }.subscribe(state::postValue)
|
||||||
filter,
|
|
||||||
showAllSwitchToggle,
|
|
||||||
historyDao.history(),
|
|
||||||
Function3(::searchResults)
|
|
||||||
).subscribe { state.postValue(updateResultsState(it)) }
|
|
||||||
|
|
||||||
private fun updateResultsState(
|
private fun reduce(action: Action, state: State): State =
|
||||||
historyListWithDateItems: List<HistoryListItem>
|
when (action) {
|
||||||
|
ExitHistory -> finishHistoryActivity(state)
|
||||||
|
ExitActionModeMenu -> deselectAllHistoryItems(state)
|
||||||
|
UserClickedDelete -> offerDeletionOfItems(state)
|
||||||
|
UserClickedDeleteButton -> offerShowDeleteDialog(state)
|
||||||
|
is OnItemClick -> handleItemClick(state, action)
|
||||||
|
is OnItemLongClick -> handleItemLongClick(state, action)
|
||||||
|
is ToggleShowHistoryFromAllBooks -> offerUpdateToShowAllToggle(action, state)
|
||||||
|
is Filter -> updateHistoryItemsBasedOnFilter(state, action)
|
||||||
|
is UpdateHistory -> updateHistoryList(state, action)
|
||||||
|
UserClickedDeleteSelectedHistoryItems -> offerShowDeleteDialog(state)
|
||||||
|
is AllHistoryPreferenceChanged -> changeShowHistoryToggle(state, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateHistoryItemsBasedOnFilter(state: State, action: Filter) =
|
||||||
|
when (state) {
|
||||||
|
is Results -> state.copy(searchTerm = action.searchTerm)
|
||||||
|
is SelectionResults -> state.copy(searchTerm = action.searchTerm)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun changeShowHistoryToggle(
|
||||||
|
state: State,
|
||||||
|
action: AllHistoryPreferenceChanged
|
||||||
): State {
|
): State {
|
||||||
return when {
|
return when (state) {
|
||||||
historyListWithDateItems.isEmpty() -> NoResults(historyListWithDateItems)
|
is SelectionResults -> state
|
||||||
historyListWithDateItems.filterIsInstance<HistoryItem>()
|
is Results -> state.copy(showAll = action.showAll)
|
||||||
.any { it.isSelected } -> SelectionResults(
|
|
||||||
historyListWithDateItems
|
|
||||||
)
|
|
||||||
else -> Results(historyListWithDateItems)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun searchResults(
|
private fun updateHistoryList(
|
||||||
searchString: String,
|
state: State,
|
||||||
showAllToggle: Boolean,
|
action: UpdateHistory
|
||||||
historyList: List<HistoryListItem>
|
): State {
|
||||||
): List<HistoryListItem> = HeaderizableList(historyList
|
return when (state) {
|
||||||
.filterIsInstance<HistoryItem>()
|
is Results -> state.copy(historyItems = action.history)
|
||||||
.filter { h ->
|
is SelectionResults -> {
|
||||||
h.historyTitle.contains(searchString, true) &&
|
val selectedItems = state.selectedItems
|
||||||
(h.zimName == zimReaderContainer.name || showAllToggle)
|
state.copy(historyItems = action.history.map {
|
||||||
|
if (selectedItems.contains(it)) it.copy(isSelected = true) else it
|
||||||
|
})
|
||||||
}
|
}
|
||||||
.sortedByDescending { dateFormatter.parse(it.dateString) } as List<HistoryListItem>)
|
}
|
||||||
.foldOverAddingHeaders(
|
}
|
||||||
{ historyItem -> DateItem((historyItem as HistoryItem).dateString) },
|
|
||||||
{ current, next -> (current as HistoryItem).dateString != (next as HistoryItem).dateString }
|
private fun offerUpdateToShowAllToggle(
|
||||||
|
action: ToggleShowHistoryFromAllBooks,
|
||||||
|
state: State
|
||||||
|
): State {
|
||||||
|
effects.offer(
|
||||||
|
UpdateAllHistoryPreference(
|
||||||
|
sharedPreferenceUtil,
|
||||||
|
action.isChecked
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleItemLongClick(
|
||||||
|
state: State,
|
||||||
|
action: OnItemLongClick
|
||||||
|
): State {
|
||||||
|
return when (state) {
|
||||||
|
is Results -> state.toggleSelectionOfItem(action.historyItem)
|
||||||
|
else -> state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleItemClick(
|
||||||
|
state: State,
|
||||||
|
action: OnItemClick
|
||||||
|
): State {
|
||||||
|
return when (state) {
|
||||||
|
is Results -> {
|
||||||
|
effects.offer(OpenHistoryItem(action.historyItem, zimReaderContainer))
|
||||||
|
state
|
||||||
|
}
|
||||||
|
is SelectionResults -> state.toggleSelectionOfItem(action.historyItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun offerShowDeleteDialog(state: State): State {
|
||||||
|
effects.offer(ShowDeleteHistoryDialog(actions))
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun offerDeletionOfItems(state: State): State {
|
||||||
|
return when (state) {
|
||||||
|
is Results -> {
|
||||||
|
effects.offer(DeleteHistoryItems(state.historyItems, historyDao))
|
||||||
|
state
|
||||||
|
}
|
||||||
|
is SelectionResults -> {
|
||||||
|
effects.offer(DeleteHistoryItems(state.selectedItems, historyDao))
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deselectAllHistoryItems(state: State): State {
|
||||||
|
return when (state) {
|
||||||
|
is SelectionResults -> {
|
||||||
|
state.copy(historyItems = state.historyItems.map { it.copy(isSelected = false) })
|
||||||
|
}
|
||||||
|
else -> state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun finishHistoryActivity(state: State): State {
|
||||||
|
effects.offer(Finish)
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
compositeDisposable.clear()
|
compositeDisposable.clear()
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleSelectionOfItem(historyItem: HistoryItem): State =
|
|
||||||
when (state.value) {
|
|
||||||
is Results -> SelectionResults(toggleGivenItemAndReturnListOfResultingItems(historyItem))
|
|
||||||
is SelectionResults -> {
|
|
||||||
if (toggleGivenItemAndReturnListOfResultingItems(historyItem)
|
|
||||||
?.filterIsInstance<HistoryItem>()
|
|
||||||
?.any { it.isSelected } == true) {
|
|
||||||
SelectionResults(toggleGivenItemAndReturnListOfResultingItems(historyItem))
|
|
||||||
} else {
|
|
||||||
Results(toggleGivenItemAndReturnListOfResultingItems(historyItem))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is NoResults -> NoResults(emptyList())
|
|
||||||
null -> NoResults(emptyList())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun toggleGivenItemAndReturnListOfResultingItems(historyItem: HistoryItem):
|
|
||||||
List<HistoryListItem>? {
|
|
||||||
return state.value
|
|
||||||
?.historyItems
|
|
||||||
?.map {
|
|
||||||
if (it.id == historyItem.id && it is HistoryItem)
|
|
||||||
it.copy(isSelected = !it.isSelected) else it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun actionMapper() = actions.map {
|
|
||||||
when (it) {
|
|
||||||
ExitHistory -> effects.offer(Finish)
|
|
||||||
is Filter -> filter.offer(it.searchTerm)
|
|
||||||
is ToggleShowHistoryFromAllBooks ->
|
|
||||||
toggleShowAllHistorySwitchAndSaveItsStateToPrefs(it.isChecked)
|
|
||||||
is OnItemLongClick -> state.postValue(toggleSelectionOfItem(it.historyItem))
|
|
||||||
is OnItemClick -> appendItemToSelectionOrOpenIt(it)
|
|
||||||
is RequestDeleteAllHistoryItems ->
|
|
||||||
effects.offer(ShowDeleteHistoryDialog(actions, DeleteAllHistory))
|
|
||||||
is RequestDeleteSelectedHistoryItems ->
|
|
||||||
effects.offer(ShowDeleteHistoryDialog(actions, DeleteSelectedHistory))
|
|
||||||
ExitActionModeMenu -> state.postValue(Results(
|
|
||||||
state.value
|
|
||||||
?.historyItems
|
|
||||||
?.map { item -> if (item is HistoryItem) item.copy(isSelected = false) else item })
|
|
||||||
)
|
|
||||||
DeleteHistoryItems -> effects.offer(DeleteSelectedOrAllHistoryItems(state, historyDao))
|
|
||||||
}
|
|
||||||
}.subscribe({}, Throwable::printStackTrace)
|
|
||||||
|
|
||||||
private fun toggleShowAllHistorySwitchAndSaveItsStateToPrefs(isChecked: Boolean) {
|
|
||||||
effects.offer(
|
|
||||||
ToggleShowAllHistorySwitchAndSaveItsStateToPrefs(
|
|
||||||
showAllSwitchToggle,
|
|
||||||
sharedPreferenceUtil,
|
|
||||||
isChecked
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun appendItemToSelectionOrOpenIt(onItemClick: OnItemClick) {
|
|
||||||
val historyItem = onItemClick.historyListItem as HistoryItem
|
|
||||||
if (state.value?.containsSelectedItems() == true) {
|
|
||||||
state.postValue(toggleSelectionOfItem(historyItem))
|
|
||||||
} else {
|
|
||||||
effects.offer(OpenHistoryItem(historyItem, zimReaderContainer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,26 +18,64 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.history.viewmodel
|
package org.kiwix.kiwixmobile.core.history.viewmodel
|
||||||
|
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.HeaderizableList
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem
|
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem
|
||||||
|
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.DateItem
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
sealed class State(
|
sealed class State(
|
||||||
open val historyItems: List<HistoryListItem>?
|
open val historyItems: List<HistoryItem>,
|
||||||
|
open val showAll: Boolean,
|
||||||
|
open val searchTerm: String = ""
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun containsSelectedItems(): Boolean {
|
private val dateFormatter = SimpleDateFormat("d MMM yyyy", Locale.getDefault())
|
||||||
return historyItems?.filterIsInstance<HistoryItem>()?.any { it.isSelected } == true
|
|
||||||
|
val historyListItems: List<HistoryListItem> by lazy {
|
||||||
|
HeaderizableList<HistoryListItem, HistoryItem, DateItem>(historyItems
|
||||||
|
.filter { it.historyTitle.contains(searchTerm, true) }
|
||||||
|
.sortedByDescending { dateFormatter.parse(it.dateString) })
|
||||||
|
.foldOverAddingHeaders(
|
||||||
|
{ historyItem -> DateItem(historyItem.dateString) },
|
||||||
|
{ current, next -> current.dateString != next.dateString }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toggleSelectionOfItem(historyListItem: HistoryItem): State {
|
||||||
|
val newList = historyItems.map {
|
||||||
|
if (it.id == historyListItem.id) it.apply {
|
||||||
|
isSelected = !isSelected
|
||||||
|
} else it
|
||||||
|
}
|
||||||
|
if (newList.isEmpty()) {
|
||||||
|
return Results(newList, showAll)
|
||||||
|
}
|
||||||
|
return SelectionResults(newList, showAll, searchTerm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fun filterBasedOnSearchTerm(searchTerm: String): State =
|
||||||
|
// copy(historyListItems = historyItems.filter {
|
||||||
|
// it.historyTitle.contains(
|
||||||
|
// searchTerm,
|
||||||
|
// true
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
|
||||||
data class Results(
|
data class Results(
|
||||||
override val historyItems: List<HistoryListItem>?
|
override val historyItems: List<HistoryItem>,
|
||||||
) : State(historyItems)
|
override val showAll: Boolean,
|
||||||
|
override val searchTerm: String = ""
|
||||||
data class NoResults(
|
) : State(historyItems, showAll, searchTerm)
|
||||||
override val historyItems: List<HistoryListItem>?
|
|
||||||
) : State(historyItems)
|
|
||||||
|
|
||||||
data class SelectionResults(
|
data class SelectionResults(
|
||||||
override val historyItems: List<HistoryListItem>?
|
override val historyItems: List<HistoryItem>,
|
||||||
) : State(historyItems)
|
override val showAll: Boolean,
|
||||||
|
override val searchTerm: String
|
||||||
|
) : State(historyItems, showAll, searchTerm) {
|
||||||
|
|
||||||
|
val selectedItems: List<HistoryItem> =
|
||||||
|
historyListItems.filterIsInstance<HistoryItem>().filter(HistoryItem::isSelected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
package org.kiwix.kiwixmobile.core.history.viewmodel.effects
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kiwix Android
|
* Kiwix Android
|
||||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
||||||
@ -17,22 +19,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
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.HistoryDao
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State
|
|
||||||
|
|
||||||
data class DeleteSelectedOrAllHistoryItems(
|
data class DeleteHistoryItems(
|
||||||
private val state: MutableLiveData<State>,
|
private val itemsToDelete: List<HistoryItem>,
|
||||||
private val historyDao: HistoryDao
|
private val historyDao: HistoryDao
|
||||||
) : SideEffect<Unit> {
|
) : SideEffect<Unit> {
|
||||||
override fun invokeWith(activity: AppCompatActivity) {
|
override fun invokeWith(activity: AppCompatActivity) {
|
||||||
val historyItems = state.value?.historyItems?.filterIsInstance<HistoryItem>()
|
historyDao.deleteHistory(itemsToDelete)
|
||||||
if (historyItems?.any { it.isSelected } == true) {
|
|
||||||
historyDao.deleteHistory(historyItems.filter { it.isSelected })
|
|
||||||
} else if (historyItems != null) {
|
|
||||||
historyDao.deleteHistory(historyItems)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,20 +23,19 @@ import io.reactivex.processors.PublishProcessor
|
|||||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||||
import org.kiwix.kiwixmobile.core.history.HistoryActivity
|
import org.kiwix.kiwixmobile.core.history.HistoryActivity
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.DeleteHistoryItems
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDelete
|
||||||
import org.kiwix.kiwixmobile.core.utils.DialogShower
|
import org.kiwix.kiwixmobile.core.utils.DialogShower
|
||||||
import org.kiwix.kiwixmobile.core.utils.KiwixDialog
|
import org.kiwix.kiwixmobile.core.utils.KiwixDialog.DeleteAllHistory
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
data class ShowDeleteHistoryDialog(
|
data class ShowDeleteHistoryDialog(
|
||||||
private val actions: PublishProcessor<Action>,
|
private val actions: PublishProcessor<Action>
|
||||||
private val dialogType: KiwixDialog
|
|
||||||
) : SideEffect<Unit> {
|
) : SideEffect<Unit> {
|
||||||
@Inject lateinit var dialogShower: DialogShower
|
@Inject lateinit var dialogShower: DialogShower
|
||||||
override fun invokeWith(activity: AppCompatActivity) {
|
override fun invokeWith(activity: AppCompatActivity) {
|
||||||
(activity as HistoryActivity).activityComponent.inject(this)
|
(activity as HistoryActivity).activityComponent.inject(this)
|
||||||
dialogShower.show(dialogType, {
|
dialogShower.show(DeleteAllHistory, {
|
||||||
actions.offer(DeleteHistoryItems)
|
actions.offer(UserClickedDelete)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
package org.kiwix.kiwixmobile.core.history.viewmodel.effects
|
package org.kiwix.kiwixmobile.core.history.viewmodel.effects
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import io.reactivex.processors.BehaviorProcessor
|
|
||||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
|
|
||||||
data class ToggleShowAllHistorySwitchAndSaveItsStateToPrefs(
|
data class UpdateAllHistoryPreference(
|
||||||
private val showAllSwitchToggle: BehaviorProcessor<Boolean>,
|
|
||||||
private val sharedPreferenceUtil: SharedPreferenceUtil,
|
private val sharedPreferenceUtil: SharedPreferenceUtil,
|
||||||
private val isChecked: Boolean
|
private val isChecked: Boolean
|
||||||
) : SideEffect<Unit> {
|
) : SideEffect<Unit> {
|
||||||
override fun invokeWith(activity: AppCompatActivity) {
|
override fun invokeWith(activity: AppCompatActivity) {
|
||||||
showAllSwitchToggle.offer(isChecked)
|
sharedPreferenceUtil.showHistoryAllBooks = !isChecked
|
||||||
sharedPreferenceUtil.showHistoryCurrentBook = !isChecked
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -55,11 +55,12 @@ public class SharedPreferenceUtil {
|
|||||||
private static final String PREF_EXTERNAL_LINK_POPUP = "pref_external_link_popup";
|
private static final String PREF_EXTERNAL_LINK_POPUP = "pref_external_link_popup";
|
||||||
private static final String PREF_IS_FIRST_RUN = "isFirstRun";
|
private static final String PREF_IS_FIRST_RUN = "isFirstRun";
|
||||||
private static final String PREF_SHOW_BOOKMARKS_CURRENT_BOOK = "show_bookmarks_current_book";
|
private static final String PREF_SHOW_BOOKMARKS_CURRENT_BOOK = "show_bookmarks_current_book";
|
||||||
private static final String PREF_SHOW_HISTORY_CURRENT_BOOK = "show_history_current_book";
|
private static final String PREF_SHOW_HISTORY_ALL_BOOKS = "show_history_current_book";
|
||||||
private static final String PREF_HOSTED_BOOKS = "hosted_books";
|
private static final String PREF_HOSTED_BOOKS = "hosted_books";
|
||||||
public static final String PREF_NIGHT_MODE = "pref_night_mode";
|
public static final String PREF_NIGHT_MODE = "pref_night_mode";
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
private final PublishProcessor<String> prefStorages = PublishProcessor.create();
|
private final PublishProcessor<String> prefStorages = PublishProcessor.create();
|
||||||
|
public final PublishProcessor<Boolean> showAllHistoryToggleSwitch = PublishProcessor.create();
|
||||||
private final PublishProcessor<NightModeConfig.Mode> nightModes = PublishProcessor.create();
|
private final PublishProcessor<NightModeConfig.Mode> nightModes = PublishProcessor.create();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -152,6 +153,10 @@ public class SharedPreferenceUtil {
|
|||||||
return prefStorages.startWith(getPrefStorage());
|
return prefStorages.startWith(getPrefStorage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Flowable<Boolean> getShowAllHistoryToggleSwitches() {
|
||||||
|
return showAllHistoryToggleSwitch.startWith(getShowHistoryAllBooks());
|
||||||
|
}
|
||||||
|
|
||||||
public void putPrefFullScreen(boolean fullScreen) {
|
public void putPrefFullScreen(boolean fullScreen) {
|
||||||
sharedPreferences.edit().putBoolean(PREF_FULLSCREEN, fullScreen).apply();
|
sharedPreferences.edit().putBoolean(PREF_FULLSCREEN, fullScreen).apply();
|
||||||
}
|
}
|
||||||
@ -168,14 +173,15 @@ public class SharedPreferenceUtil {
|
|||||||
sharedPreferences.edit().putBoolean(PREF_SHOW_INTRO, false).apply();
|
sharedPreferences.edit().putBoolean(PREF_SHOW_INTRO, false).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getShowHistoryCurrentBook() {
|
public boolean getShowHistoryAllBooks() {
|
||||||
return sharedPreferences.getBoolean(PREF_SHOW_HISTORY_CURRENT_BOOK, true);
|
return sharedPreferences.getBoolean(PREF_SHOW_HISTORY_ALL_BOOKS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowHistoryCurrentBook(boolean prefShowHistoryCurrentBook) {
|
public void setShowHistoryAllBooks(boolean prefShowHistoryAllBooks) {
|
||||||
sharedPreferences.edit()
|
sharedPreferences.edit()
|
||||||
.putBoolean(PREF_SHOW_HISTORY_CURRENT_BOOK, prefShowHistoryCurrentBook)
|
.putBoolean(PREF_SHOW_HISTORY_ALL_BOOKS, prefShowHistoryAllBooks)
|
||||||
.apply();
|
.apply();
|
||||||
|
showAllHistoryToggleSwitch.offer(prefShowHistoryAllBooks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getShowBookmarksCurrentBook() {
|
public boolean getShowBookmarksCurrentBook() {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.kiwix.kiwixmobile.core.history.viewmodel
|
package org.kiwix.kiwixmobile.core.history.viewmodel
|
||||||
|
|
||||||
import DeleteSelectedOrAllHistoryItems
|
|
||||||
import OpenHistoryItem
|
import OpenHistoryItem
|
||||||
import com.jraska.livedata.test
|
import com.jraska.livedata.test
|
||||||
import io.mockk.clearAllMocks
|
import io.mockk.clearAllMocks
|
||||||
@ -18,24 +17,22 @@ import org.kiwix.kiwixmobile.core.base.SideEffect
|
|||||||
import org.kiwix.kiwixmobile.core.dao.HistoryDao
|
import org.kiwix.kiwixmobile.core.dao.HistoryDao
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.DateItem
|
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.DateItem
|
||||||
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
import org.kiwix.kiwixmobile.core.history.adapter.HistoryListItem.HistoryItem
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.DeleteHistoryItems
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitActionModeMenu
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitActionModeMenu
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitHistory
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ExitHistory
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.NoResults
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.Results
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.Filter
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.Filter
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemClick
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemClick
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemLongClick
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.OnItemLongClick
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.RequestDeleteAllHistoryItems
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.RequestDeleteSelectedHistoryItems
|
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ToggleShowHistoryFromAllBooks
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.ToggleShowHistoryFromAllBooks
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDelete
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDeleteButton
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDeleteSelectedHistoryItems
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.State.Results
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.State.SelectionResults
|
import org.kiwix.kiwixmobile.core.history.viewmodel.State.SelectionResults
|
||||||
|
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.DeleteHistoryItems
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.ShowDeleteHistoryDialog
|
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.ShowDeleteHistoryDialog
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.ToggleShowAllHistorySwitchAndSaveItsStateToPrefs
|
import org.kiwix.kiwixmobile.core.history.viewmodel.effects.UpdateAllHistoryPreference
|
||||||
|
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.KiwixDialog.DeleteAllHistory
|
|
||||||
import org.kiwix.kiwixmobile.core.utils.KiwixDialog.DeleteSelectedHistory
|
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
import org.kiwix.sharedFunctions.InstantExecutorExtension
|
import org.kiwix.sharedFunctions.InstantExecutorExtension
|
||||||
import org.kiwix.sharedFunctions.setScheduler
|
import org.kiwix.sharedFunctions.setScheduler
|
||||||
@ -62,7 +59,7 @@ internal class HistoryViewModelTest {
|
|||||||
clearAllMocks()
|
clearAllMocks()
|
||||||
every { zimReaderContainer.id } returns "id"
|
every { zimReaderContainer.id } returns "id"
|
||||||
every { zimReaderContainer.name } returns "zimName"
|
every { zimReaderContainer.name } returns "zimName"
|
||||||
every { sharedPreferenceUtil.showHistoryCurrentBook } returns true
|
every { sharedPreferenceUtil.showHistoryAllBooks } returns true
|
||||||
every { historyDao.history() } returns itemsFromDb.distinctUntilChanged()
|
every { historyDao.history() } returns itemsFromDb.distinctUntilChanged()
|
||||||
viewModel = HistoryViewModel(historyDao, zimReaderContainer, sharedPreferenceUtil)
|
viewModel = HistoryViewModel(historyDao, zimReaderContainer, sharedPreferenceUtil)
|
||||||
}
|
}
|
||||||
@ -86,7 +83,7 @@ internal class HistoryViewModelTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `initial state is Initialising`() {
|
fun `initial state is Initialising`() {
|
||||||
viewModel.state.test().assertValue(NoResults(listOf()))
|
viewModel.state.test().assertValue(Results(listOf(), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -101,7 +98,7 @@ internal class HistoryViewModelTest {
|
|||||||
searchTerm = searchTerm,
|
searchTerm = searchTerm,
|
||||||
databaseResults = listOf(item)
|
databaseResults = listOf(item)
|
||||||
)
|
)
|
||||||
resultsIn(Results((listOf(date, item))))
|
resultsIn(Results(listOf(item), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -114,7 +111,7 @@ internal class HistoryViewModelTest {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
resultsIn(NoResults(emptyList()))
|
resultsIn(Results(emptyList(), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -126,7 +123,7 @@ internal class HistoryViewModelTest {
|
|||||||
searchTerm = "",
|
searchTerm = "",
|
||||||
databaseResults = listOf(item)
|
databaseResults = listOf(item)
|
||||||
)
|
)
|
||||||
resultsIn(Results(listOf(date, item)))
|
resultsIn(Results(listOf(item), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -135,7 +132,7 @@ internal class HistoryViewModelTest {
|
|||||||
searchTerm = "",
|
searchTerm = "",
|
||||||
databaseResults = emptyList()
|
databaseResults = emptyList()
|
||||||
)
|
)
|
||||||
resultsIn(NoResults(emptyList()))
|
resultsIn(Results(emptyList(), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -150,7 +147,7 @@ internal class HistoryViewModelTest {
|
|||||||
databaseResults = listOf(item)
|
databaseResults = listOf(item)
|
||||||
)
|
)
|
||||||
viewModel.actions.offer(Filter(searchString2))
|
viewModel.actions.offer(Filter(searchString2))
|
||||||
resultsIn(Results(listOf(date, item)))
|
resultsIn(Results(listOf(item), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -166,7 +163,7 @@ internal class HistoryViewModelTest {
|
|||||||
searchTerm = "b",
|
searchTerm = "b",
|
||||||
databaseResults = listOf(item)
|
databaseResults = listOf(item)
|
||||||
)
|
)
|
||||||
resultsIn(Results(listOf(date, item)))
|
resultsIn(Results(listOf(item), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -184,7 +181,7 @@ internal class HistoryViewModelTest {
|
|||||||
searchTerm = "b",
|
searchTerm = "b",
|
||||||
databaseResults = listOf(item)
|
databaseResults = listOf(item)
|
||||||
)
|
)
|
||||||
resultsIn(SelectionResults(listOf(date, item)))
|
resultsIn(SelectionResults(listOf(item), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -208,7 +205,7 @@ internal class HistoryViewModelTest {
|
|||||||
searchTerm = "",
|
searchTerm = "",
|
||||||
databaseResults = listOf(item2, item3, item1)
|
databaseResults = listOf(item2, item3, item1)
|
||||||
)
|
)
|
||||||
resultsIn(Results(listOf(date3, item3, date1, item1, date2, item2)))
|
resultsIn(Results(listOf(item3, item1, item2), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -231,7 +228,7 @@ internal class HistoryViewModelTest {
|
|||||||
searchTerm = "",
|
searchTerm = "",
|
||||||
databaseResults = listOf(item2, item3, item1)
|
databaseResults = listOf(item2, item3, item1)
|
||||||
)
|
)
|
||||||
resultsIn(Results(listOf(date1, item2, item1, date3, item3)))
|
resultsIn(Results(listOf(item2, item1, item3), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -247,7 +244,7 @@ internal class HistoryViewModelTest {
|
|||||||
)
|
)
|
||||||
viewModel.actions.offer(OnItemLongClick(item1))
|
viewModel.actions.offer(OnItemLongClick(item1))
|
||||||
item1.isSelected = true
|
item1.isSelected = true
|
||||||
resultsIn(SelectionResults(listOf(date, item1)))
|
resultsIn(SelectionResults(listOf(item1), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -267,8 +264,9 @@ internal class HistoryViewModelTest {
|
|||||||
)
|
)
|
||||||
viewModel.actions.offer(OnItemLongClick(item1))
|
viewModel.actions.offer(OnItemLongClick(item1))
|
||||||
viewModel.actions.offer(OnItemClick(item1))
|
viewModel.actions.offer(OnItemClick(item1))
|
||||||
resultsIn(Results(listOf(date, item1, item2)))
|
resultsIn(Results(listOf(item1, item2), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Deselection via OnItemLongClick exits selection state if last item is deselected`() {
|
fun `Deselection via OnItemLongClick exits selection state if last item is deselected`() {
|
||||||
val item1 =
|
val item1 =
|
||||||
@ -286,7 +284,7 @@ internal class HistoryViewModelTest {
|
|||||||
)
|
)
|
||||||
viewModel.actions.offer(OnItemLongClick(item1))
|
viewModel.actions.offer(OnItemLongClick(item1))
|
||||||
viewModel.actions.offer(OnItemLongClick(item1))
|
viewModel.actions.offer(OnItemLongClick(item1))
|
||||||
resultsIn(Results(listOf(date, item1, item2)))
|
resultsIn(Results(listOf(item1, item2), true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -307,7 +305,7 @@ internal class HistoryViewModelTest {
|
|||||||
viewModel.actions.offer(ExitActionModeMenu)
|
viewModel.actions.offer(ExitActionModeMenu)
|
||||||
item1.isSelected = false
|
item1.isSelected = false
|
||||||
item2.isSelected = false
|
item2.isSelected = false
|
||||||
resultsIn(Results(listOf(date, item1, item2)))
|
resultsIn(Results(listOf(item1, item2), true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,12 +366,17 @@ internal class HistoryViewModelTest {
|
|||||||
|
|
||||||
private fun assertItemIsSelected(item: HistoryItem) {
|
private fun assertItemIsSelected(item: HistoryItem) {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
(viewModel.state.value?.historyItems?.find { it.id == item.id } as HistoryItem).isSelected
|
(viewModel.state.value?.historyListItems?.find {
|
||||||
|
it.id == item.id
|
||||||
|
} as HistoryItem).isSelected
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertItemIsDeselected(item: HistoryItem) {
|
private fun assertItemIsDeselected(item: HistoryItem) {
|
||||||
assertFalse(
|
assertFalse(
|
||||||
(viewModel.state.value?.historyItems?.find { it.id == item.id } as HistoryItem).isSelected
|
(viewModel.state.value?.historyListItems?.find {
|
||||||
|
it.id == item.id
|
||||||
|
} as HistoryItem).isSelected
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,31 +432,35 @@ internal class HistoryViewModelTest {
|
|||||||
fun `ToggleShowHistoryFromAllBooks switches show all books toggle`() {
|
fun `ToggleShowHistoryFromAllBooks switches show all books toggle`() {
|
||||||
actionResultsInEffects(
|
actionResultsInEffects(
|
||||||
ToggleShowHistoryFromAllBooks(true),
|
ToggleShowHistoryFromAllBooks(true),
|
||||||
ToggleShowAllHistorySwitchAndSaveItsStateToPrefs(
|
UpdateAllHistoryPreference(
|
||||||
viewModel.showAllSwitchToggle,
|
|
||||||
sharedPreferenceUtil,
|
sharedPreferenceUtil,
|
||||||
true))
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `RequestDeleteAllHistoryItems opens dialog to request deletion`() {
|
fun `RequestDeleteAllHistoryItems opens dialog to request deletion`() {
|
||||||
actionResultsInEffects(
|
actionResultsInEffects(
|
||||||
RequestDeleteAllHistoryItems,
|
UserClickedDeleteButton,
|
||||||
ShowDeleteHistoryDialog(viewModel.actions, DeleteAllHistory))
|
ShowDeleteHistoryDialog(viewModel.actions)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `RequestDeleteSelectedHistoryItems opens dialog to request deletion`() {
|
fun `RequestDeleteSelectedHistoryItems opens dialog to request deletion`() {
|
||||||
actionResultsInEffects(
|
actionResultsInEffects(
|
||||||
RequestDeleteSelectedHistoryItems,
|
UserClickedDeleteSelectedHistoryItems,
|
||||||
ShowDeleteHistoryDialog(viewModel.actions, DeleteSelectedHistory))
|
ShowDeleteHistoryDialog(viewModel.actions)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `DeleteHistoryItems calls DeleteSelectedOrAllHistoryItems side effect`() {
|
fun `DeleteHistoryItems calls DeleteSelectedOrAllHistoryItems side effect`() {
|
||||||
actionResultsInEffects(
|
actionResultsInEffects(
|
||||||
DeleteHistoryItems,
|
UserClickedDelete,
|
||||||
DeleteSelectedOrAllHistoryItems(viewModel.state, historyDao))
|
DeleteHistoryItems(viewModel.state.value!!.historyItems, historyDao)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun actionResultsInEffects(
|
private fun actionResultsInEffects(
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.kiwix.kiwixmobile.core.history.viewmodel.effects
|
package org.kiwix.kiwixmobile.core.history.viewmodel.effects
|
||||||
|
|
||||||
import DeleteSelectedOrAllHistoryItems
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
@ -22,7 +21,7 @@ internal class DeleteSelectedOrAllHistoryItemsTest {
|
|||||||
every { state.value } returns SelectionResults(listOf(item1, item2))
|
every { state.value } returns SelectionResults(listOf(item1, item2))
|
||||||
val historyDao: HistoryDao = mockk()
|
val historyDao: HistoryDao = mockk()
|
||||||
val activity: AppCompatActivity = mockk()
|
val activity: AppCompatActivity = mockk()
|
||||||
DeleteSelectedOrAllHistoryItems(state, historyDao).invokeWith(activity)
|
DeleteHistoryItems(state, historyDao).invokeWith(activity)
|
||||||
verify { historyDao.deleteHistory(listOf(item1)) }
|
verify { historyDao.deleteHistory(listOf(item1)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ internal class DeleteSelectedOrAllHistoryItemsTest {
|
|||||||
every { state.value } returns SelectionResults(listOf(item1, item2))
|
every { state.value } returns SelectionResults(listOf(item1, item2))
|
||||||
val historyDao: HistoryDao = mockk()
|
val historyDao: HistoryDao = mockk()
|
||||||
val activity: AppCompatActivity = mockk()
|
val activity: AppCompatActivity = mockk()
|
||||||
DeleteSelectedOrAllHistoryItems(state, historyDao).invokeWith(activity)
|
DeleteHistoryItems(state, historyDao).invokeWith(activity)
|
||||||
verify { historyDao.deleteHistory(listOf(item1, item2)) }
|
verify { historyDao.deleteHistory(listOf(item1, item2)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import io.reactivex.processors.PublishProcessor
|
|||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.kiwix.kiwixmobile.core.history.HistoryActivity
|
import org.kiwix.kiwixmobile.core.history.HistoryActivity
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action
|
||||||
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.DeleteHistoryItems
|
import org.kiwix.kiwixmobile.core.history.viewmodel.Action.UserClickedDelete
|
||||||
import org.kiwix.kiwixmobile.core.utils.DialogShower
|
import org.kiwix.kiwixmobile.core.utils.DialogShower
|
||||||
import org.kiwix.kiwixmobile.core.utils.KiwixDialog.DeleteSelectedHistory
|
import org.kiwix.kiwixmobile.core.utils.KiwixDialog.DeleteSelectedHistory
|
||||||
|
|
||||||
@ -30,6 +30,6 @@ internal class ShowDeleteHistoryDialogTest {
|
|||||||
dialogShower.show(DeleteSelectedHistory, capture(lambdaSlot))
|
dialogShower.show(DeleteSelectedHistory, capture(lambdaSlot))
|
||||||
}
|
}
|
||||||
lambdaSlot.captured.invoke()
|
lambdaSlot.captured.invoke()
|
||||||
verify { actions.offer(DeleteHistoryItems) }
|
verify { actions.offer(UserClickedDelete) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,14 +15,14 @@ internal class ToggleShowAllHistorySwitchAndSaveItsStateToPrefsTest {
|
|||||||
every { toggleSwitch.offer(true) } returns true
|
every { toggleSwitch.offer(true) } returns true
|
||||||
val sharedPreferenceUtil: SharedPreferenceUtil = mockk()
|
val sharedPreferenceUtil: SharedPreferenceUtil = mockk()
|
||||||
val activity: AppCompatActivity = mockk()
|
val activity: AppCompatActivity = mockk()
|
||||||
ToggleShowAllHistorySwitchAndSaveItsStateToPrefs(
|
UpdateAllHistoryPreference(
|
||||||
toggleSwitch,
|
toggleSwitch,
|
||||||
sharedPreferenceUtil,
|
sharedPreferenceUtil,
|
||||||
true
|
true
|
||||||
).invokeWith(activity)
|
).invokeWith(activity)
|
||||||
verify {
|
verify {
|
||||||
toggleSwitch.offer(true)
|
toggleSwitch.offer(true)
|
||||||
sharedPreferenceUtil.showHistoryCurrentBook = false
|
sharedPreferenceUtil.showHistoryAllBooks = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user