mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-30 08:35:02 -04:00
#1990 more experimentation with history listt rewrite
This commit is contained in:
parent
de88dd6c55
commit
f3b891ad32
@ -9,6 +9,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.activity_history.recycler_view
|
||||
import kotlinx.android.synthetic.main.layout_toolbar.toolbar
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.R.id
|
||||
import org.kiwix.kiwixmobile.core.R.string
|
||||
@ -38,9 +39,7 @@ class HistoryActivity : OnItemClickListener, BaseActivity(){
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
private val historyAdapter: HistoryAdapter2 by lazy {
|
||||
HistoryAdapter2(
|
||||
HistoryItemDelegate(deleteList,this){
|
||||
historyViewModel.actions.offer(OnItemLongClick(it))
|
||||
}
|
||||
HistoryItemDelegate(deleteList, ::onItemClick, ::onItemLongClick)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
package org.kiwix.kiwixmobile.core.history
|
||||
|
||||
import android.content.DialogInterface.OnClickListener
|
||||
import android.view.View.OnClickListener
|
||||
import android.view.View.OnLongClickListener
|
||||
import android.view.ViewGroup
|
||||
import org.kiwix.kiwixmobile.core.base.adapter.AbsDelegateAdapter
|
||||
import org.kiwix.kiwixmobile.core.extensions.ViewGroupExtensions.inflate
|
||||
import org.kiwix.kiwixmobile.core.history.HistoryAdapter.OnItemClickListener
|
||||
import org.kiwix.kiwixmobile.core.history.HistoryListItem.HistoryItem
|
||||
|
||||
sealed class HistoryDelegate<I : HistoryListItem, out VH : HistoryItemViewHolder2<I>> :
|
||||
@ -12,12 +12,13 @@ sealed class HistoryDelegate<I : HistoryListItem, out VH : HistoryItemViewHolder
|
||||
|
||||
class HistoryItemDelegate(
|
||||
private val deleteList: List<HistoryListItem>,
|
||||
private val itemClickListener: OnItemClickListener
|
||||
private val onClickListener: OnClickListener,
|
||||
private val onLongClickListener: OnLongClickListener,
|
||||
) : HistoryDelegate<HistoryItem, HistoryItemViewHolder2.HistoryItemViewHolder>(){
|
||||
override val itemClass = HistoryItem::class.java
|
||||
|
||||
override fun createViewHolder(parent: ViewGroup) = HistoryItemViewHolder2.HistoryItemViewHolder(parent.inflate(android.R.layout.simple_selectable_list_item, false),
|
||||
deleteList, itemClickListener)
|
||||
deleteList, onClickListener, onLongClickListener)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package org.kiwix.kiwixmobile.core.history
|
||||
|
||||
import android.view.View
|
||||
import android.view.View.OnClickListener
|
||||
import android.view.View.OnLongClickListener
|
||||
import kotlinx.android.synthetic.main.item_bookmark_history.favicon
|
||||
import kotlinx.android.synthetic.main.item_bookmark_history.title
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
@ -18,7 +20,8 @@ sealed class HistoryItemViewHolder2 <in T : HistoryListItem>(containerView: View
|
||||
class HistoryItemViewHolder(
|
||||
override val containerView: View,
|
||||
private val deleteList: List<HistoryListItem>,
|
||||
private val itemClickListener: OnItemClickListener
|
||||
private val onClickListener: OnClickListener,
|
||||
private val onLongClickListener: OnLongClickListener
|
||||
) : HistoryItemViewHolder2<HistoryItem>(containerView){
|
||||
override fun bind(item: HistoryItem) {
|
||||
title.text = item.historyTitle
|
||||
@ -27,8 +30,8 @@ sealed class HistoryItemViewHolder2 <in T : HistoryListItem>(containerView: View
|
||||
} else {
|
||||
favicon.setBitmap(Base64String(item.favicon))
|
||||
}
|
||||
itemView.setOnClickListener { itemClickListener.onItemClick(favicon, item) }
|
||||
itemView.setOnLongClickListener { itemClickListener.onItemLongClick(favicon, item) }
|
||||
itemView.setOnClickListener(onClickListener)
|
||||
itemView.setOnLongClickListener(onLongClickListener)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ sealed class Action {
|
||||
data class OnItemClick(val historyListItem: HistoryListItem) : Action()
|
||||
data class OnItemLongClick(val historyListItem: HistoryListItem) : Action()
|
||||
data class Filter(val term: String) : Action()
|
||||
data class ConfirmedDelete(val historyListItem: HistoryListItem) : Action()
|
||||
data class ConfirmedDelete(val historyListItems: List<HistoryListItem.HistoryItem>) : Action()
|
||||
data class CreatedWithIntent(val intent: Intent?) : Action()
|
||||
data class ActivityResultReceived(val requestCode: Int, val resultCode: Int, val data: Intent?) :
|
||||
Action()
|
||||
|
@ -1,17 +1,23 @@
|
||||
package org.kiwix.kiwixmobile.core.history.ViewModel
|
||||
|
||||
import DeleteRecentSearch
|
||||
import Finish
|
||||
import OpenSearchItem
|
||||
import ProcessActivityResult
|
||||
import SearchInPreviousScreen
|
||||
import SearchIntentProcessing
|
||||
import ShowToast
|
||||
import StartSpeechInput
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.processors.BehaviorProcessor
|
||||
import io.reactivex.processors.PublishProcessor
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.dao.HistoryDao
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.ActivityResultReceived
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.ClickedSearchInText
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.ConfirmedDelete
|
||||
@ -23,19 +29,19 @@ import org.kiwix.kiwixmobile.core.history.ViewModel.Action.OnItemLongClick
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.ReceivedPromptForSpeechInput
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.StartSpeechInputFailed
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.State.NoResults
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchResultGenerator
|
||||
import javax.inject.Inject
|
||||
|
||||
class HistoryViewModel @Inject constructor() : ViewModel(){
|
||||
class HistoryViewModel @Inject constructor(
|
||||
private val historyDao: HistoryDao,
|
||||
private val searchResultGenerator: SearchResultGenerator
|
||||
) : ViewModel(){
|
||||
val state = MutableLiveData<State>().apply{ value = NoResults("")}
|
||||
val effects = PublishProcessor.create<SideEffect<*>>()
|
||||
val actions = PublishProcessor.create<Action>()
|
||||
private val filter = BehaviorProcessor.createDefault("")
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
init {
|
||||
compositeDisposable.addAll(viwStateRduce(),actionMapper())
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
compositeDisposable.clear()
|
||||
super.onCleared()
|
||||
@ -44,8 +50,6 @@ class HistoryViewModel @Inject constructor() : ViewModel(){
|
||||
private fun actionMapper() = actions.map {
|
||||
when (it) {
|
||||
ExitedSearch -> effects.offer(Finish)
|
||||
is OnItemClick -> saveSearchAndOpenItem(it)
|
||||
is OnItemLongClick -> showDeleteDialog(it)
|
||||
is Filter -> filter.offer(it.term)
|
||||
ClickedSearchInText -> searchPreviousScreenWhenStateIsValid()
|
||||
is ConfirmedDelete -> deleteItemAndShowToast(it)
|
||||
@ -54,59 +58,25 @@ class HistoryViewModel @Inject constructor() : ViewModel(){
|
||||
StartSpeechInputFailed -> effects.offer(ShowToast(R.string.speech_not_supported))
|
||||
is ActivityResultReceived ->
|
||||
effects.offer(ProcessActivityResult(it.requestCode, it.resultCode, it.data, actions))
|
||||
else -> {}
|
||||
}
|
||||
}.subscribe(
|
||||
{},
|
||||
Throwable::printStackTrace
|
||||
)
|
||||
|
||||
private fun deleteItemAndShowToast(it: ConfirmedDelete) {
|
||||
effects.offer(DeleteRecentSearch(it.searchListItem, recentSearchDao))
|
||||
private fun deleteItemsAndShowToast(it: ConfirmedDelete) {
|
||||
effects.offer(DeleteRecentSearch(it.historyListItems, historyDao))
|
||||
effects.offer(ShowToast(R.string.delete_specific_search_toast))
|
||||
|
||||
}
|
||||
|
||||
private fun deleteItemAndShowToast(it: ConfirmedDelete) {
|
||||
}
|
||||
|
||||
private fun searchPreviousScreenWhenStateIsValid(): Any =
|
||||
effects.offer(SearchInPreviousScreen(state.value!!.searchString))
|
||||
|
||||
private fun showDeleteDialog(longClick: OnItemLongClick) {
|
||||
effects.offer(ShowDeleteSearchDialog(longClick.searchListItem, actions))
|
||||
}
|
||||
|
||||
private fun saveSearchAndOpenItem(it: OnItemClick) {
|
||||
effects.offer(
|
||||
SaveSearchToRecents(recentSearchDao, it.searchListItem, zimReaderContainer.id)
|
||||
)
|
||||
effects.offer(
|
||||
OpenSearchItem(it.searchListItem)
|
||||
)
|
||||
}
|
||||
|
||||
private fun viewStateReducer() =
|
||||
Flowable.combineLatest(
|
||||
recentSearchDao.recentSearches(zimReaderContainer.id),
|
||||
searchResultsFromZimReader(),
|
||||
filter,
|
||||
searchOrigin,
|
||||
Function4(this::reduce)
|
||||
).subscribe(state::postValue, Throwable::printStackTrace)
|
||||
|
||||
private fun reduce(
|
||||
recentSearchResults: List<SearchListItem>,
|
||||
zimSearchResults: List<SearchListItem>,
|
||||
searchString: String,
|
||||
searchOrigin: SearchOrigin
|
||||
) = when {
|
||||
searchString.isNotEmpty() && zimSearchResults.isNotEmpty() ->
|
||||
Results(searchString, zimSearchResults, searchOrigin)
|
||||
searchString.isEmpty() && recentSearchResults.isNotEmpty() ->
|
||||
Results(searchString, recentSearchResults, searchOrigin)
|
||||
else -> NoResults(searchString, searchOrigin)
|
||||
}
|
||||
|
||||
private fun searchResultsFromZimReader() = filter
|
||||
.distinctUntilChanged()
|
||||
.switchMap(::searchResults)
|
||||
|
||||
private fun searchResults(it: String) = Flowable.fromCallable {
|
||||
searchResultGenerator.generateSearchResults(it)
|
||||
}.subscribeOn(Schedulers.io())
|
||||
|
@ -19,14 +19,14 @@
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao
|
||||
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
|
||||
import org.kiwix.kiwixmobile.core.dao.HistoryDao
|
||||
import org.kiwix.kiwixmobile.core.history.HistoryListItem
|
||||
|
||||
data class DeleteRecentSearch(
|
||||
private val searchListItem: SearchListItem,
|
||||
private val recentSearchDao: NewRecentSearchDao
|
||||
private val historyListItems: List<HistoryListItem.HistoryItem>,
|
||||
private val historyDao: HistoryDao
|
||||
) : SideEffect<Unit> {
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
recentSearchDao.deleteSearchString(searchListItem.value)
|
||||
historyDao.deleteHistory(historyListItems)
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ import android.speech.RecognizerIntent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import io.reactivex.processors.PublishProcessor
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.Filter
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.Filter
|
||||
|
||||
data class ProcessActivityResult(
|
||||
private val requestCode: Int,
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao
|
||||
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
|
||||
|
||||
data class SaveSearchToRecents(
|
||||
private val recentSearchDao: NewRecentSearchDao,
|
||||
private val searchListItem: SearchListItem,
|
||||
private val id: String?
|
||||
) : SideEffect<Unit> {
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
id?.let { recentSearchDao.saveSearch(searchListItem.value, it) }
|
||||
}
|
||||
}
|
@ -23,15 +23,11 @@ import android.os.Build.VERSION_CODES
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import io.reactivex.processors.PublishProcessor
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.Filter
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ReceivedPromptForSpeechInput
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ScreenWasStartedFrom
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromTabView
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromWebView
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.Filter
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.ReceivedPromptForSpeechInput
|
||||
import org.kiwix.kiwixmobile.core.utils.EXTRA_SEARCH
|
||||
import org.kiwix.kiwixmobile.core.utils.EXTRA_IS_WIDGET_VOICE
|
||||
import org.kiwix.kiwixmobile.core.utils.TAG_FROM_TAB_SWITCHER
|
||||
|
||||
data class SearchIntentProcessing(
|
||||
private val intent: Intent?,
|
||||
@ -40,12 +36,6 @@ data class SearchIntentProcessing(
|
||||
@TargetApi(VERSION_CODES.M)
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
intent?.let {
|
||||
actions.offer(
|
||||
ScreenWasStartedFrom(
|
||||
if (it.getBooleanExtra(TAG_FROM_TAB_SWITCHER, false)) FromTabView
|
||||
else FromWebView
|
||||
)
|
||||
)
|
||||
if (it.hasExtra(Intent.EXTRA_PROCESS_TEXT)) {
|
||||
actions.offer(Filter(it.getStringExtra(Intent.EXTRA_PROCESS_TEXT)))
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import io.reactivex.processors.PublishProcessor
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.search.SearchActivity
|
||||
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action
|
||||
import org.kiwix.kiwixmobile.core.utils.DialogShower
|
||||
import org.kiwix.kiwixmobile.core.utils.KiwixDialog.DeleteSearch
|
||||
import javax.inject.Inject
|
||||
|
||||
data class ShowDeleteSearchDialog(
|
||||
private val searchListItem: SearchListItem,
|
||||
private val actions: PublishProcessor<Action>
|
||||
) : SideEffect<Unit> {
|
||||
|
||||
@Inject lateinit var dialogShower: DialogShower
|
||||
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
(activity as SearchActivity).activityComponent.inject(this)
|
||||
dialogShower.show(DeleteSearch, { actions.offer(Action.ConfirmedDelete(searchListItem)) })
|
||||
}
|
||||
}
|
@ -24,8 +24,8 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import io.reactivex.processors.PublishProcessor
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.StartSpeechInputFailed
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action
|
||||
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.StartSpeechInputFailed
|
||||
import java.util.Locale
|
||||
|
||||
data class StartSpeechInput(private val actions: PublishProcessor<Action>) : SideEffect<Unit> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user