#1990 more experimentation with history listt rewrite

This commit is contained in:
Frans-Lukas 2020-04-12 18:19:40 +02:00
parent de88dd6c55
commit f3b891ad32
11 changed files with 44 additions and 155 deletions

View File

@ -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)
)
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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()

View File

@ -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())

View File

@ -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)
}
}

View File

@ -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,

View File

@ -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) }
}
}

View File

@ -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)))
}

View File

@ -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)) })
}
}

View File

@ -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> {