#1990 rewrite of HistoryActivity WORK IN PROGRESS

This commit is contained in:
Frans-Lukas 2020-04-12 15:01:30 +02:00
parent faa8e272a4
commit de88dd6c55
17 changed files with 760 additions and 0 deletions

View File

@ -0,0 +1,108 @@
package org.kiwix.kiwixmobile.core.history
import android.os.Bundle
import android.view.Menu
import android.widget.ImageView
import androidx.appcompat.widget.SearchView
import androidx.lifecycle.ViewModelProvider
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 org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.R.id
import org.kiwix.kiwixmobile.core.R.string
import org.kiwix.kiwixmobile.core.base.BaseActivity
import org.kiwix.kiwixmobile.core.di.components.CoreComponent
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.coreActivityComponent
import org.kiwix.kiwixmobile.core.history.HistoryAdapter.OnItemClickListener
import org.kiwix.kiwixmobile.core.history.HistoryDelegate.HistoryItemDelegate
import org.kiwix.kiwixmobile.core.history.HistoryListItem.HistoryItem
import org.kiwix.kiwixmobile.core.history.ViewModel.HistoryViewModel
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemClick
import org.kiwix.kiwixmobile.core.search.viewmodel.State
import org.kiwix.kiwixmobile.core.utils.SimpleTextListener
import java.util.ArrayList
import javax.inject.Inject
class HistoryActivity : OnItemClickListener, BaseActivity(){
val activityComponent by lazy { coreActivityComponent }
private val historyList: List<HistoryListItem> = ArrayList()
private val fullHistory: List<HistoryListItem> = ArrayList()
private val deleteList: List<HistoryListItem> = ArrayList()
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
private val recyclerView: RecyclerView = recycler_view
private val historyViewModel by lazy { viewMdel<HistoryViewModel>(viewModelFactory) }
private val compositeDisposable = CompositeDisposable()
private val historyAdapter: HistoryAdapter2 by lazy {
HistoryAdapter2(
HistoryItemDelegate(deleteList,this){
historyViewModel.actions.offer(OnItemLongClick(it))
}
)
}
override fun injection(coreComponent: CoreComponent) {
coreComponent.activityComponentBuilder()
.activity(this)
.build()
.inject(this)
activityComponent.inject(this);
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_history)
setSupportActionBar(toolbar)
val actionBar = supportActionBar
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true)
actionBar.setTitle(string.history)
}
recyclerView.run{
adapter = historyAdapter
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false);
setHasFixedSize(true)
}
compositeDisposable.add(historyViewModel.effects.subcribe{ it.invokeWith(this) })
}
override fun onDestroy() {
compositeDisposable.clear()
super.onDestroy()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_history, menu)
val search = menu.findItem(id.menu_history_search).actionView as SearchView
search.queryHint = getString(string.search_history)
search.setOnQueryTextListener(SimpleTextListener{historyViewModel.actions.offer(Filter(it))})
return true
}
private fun render(state: State) {
}
private fun onItemClick(it: SearchListItem) {
searchViewModel.actions.offer(OnItemClick(it))
}
override fun onItemClick(
favicon: ImageView,
history: HistoryItem
) {
TODO("Not yet implemented")
}
override fun onItemLongClick(
favicon: ImageView,
history: HistoryItem
): Boolean {
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,10 @@
package org.kiwix.kiwixmobile.core.history
import org.kiwix.kiwixmobile.core.base.adapter.AdapterDelegate
import org.kiwix.kiwixmobile.core.base.adapter.BaseDelegateAdapter
class HistoryAdapter2(
vararg delegates: AdapterDelegate<HistoryListItem>
) : BaseDelegateAdapter<HistoryListItem>(*delegates){
override fun getIdFor(item: HistoryListItem): Long = item.id
}

View File

@ -0,0 +1,23 @@
package org.kiwix.kiwixmobile.core.history
import android.content.DialogInterface.OnClickListener
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>> :
AbsDelegateAdapter<I, HistoryListItem, VH> {
class HistoryItemDelegate(
private val deleteList: List<HistoryListItem>,
private val itemClickListener: OnItemClickListener
) : 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)
}
}

View File

@ -0,0 +1,37 @@
package org.kiwix.kiwixmobile.core.history
import android.view.View
import kotlinx.android.synthetic.main.item_bookmark_history.favicon
import kotlinx.android.synthetic.main.item_bookmark_history.title
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.base.adapter.BaseViewHolder
import org.kiwix.kiwixmobile.core.downloader.model.Base64String
import org.kiwix.kiwixmobile.core.extensions.setBitmap
import org.kiwix.kiwixmobile.core.extensions.setImageDrawableCompat
import org.kiwix.kiwixmobile.core.history.HistoryAdapter.OnItemClickListener
import org.kiwix.kiwixmobile.core.history.HistoryListItem.HistoryItem
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
sealed class HistoryItemViewHolder2 <in T : HistoryListItem>(containerView: View):
BaseViewHolder<T>(containerView){
class HistoryItemViewHolder(
override val containerView: View,
private val deleteList: List<HistoryListItem>,
private val itemClickListener: OnItemClickListener
) : HistoryItemViewHolder2<HistoryItem>(containerView){
override fun bind(item: HistoryItem) {
title.text = item.historyTitle
if (deleteList.contains(item)) {
favicon.setImageDrawableCompat(R.drawable.ic_check_circle_blue_24dp)
} else {
favicon.setBitmap(Base64String(item.favicon))
}
itemView.setOnClickListener { itemClickListener.onItemClick(favicon, item) }
itemView.setOnLongClickListener { itemClickListener.onItemLongClick(favicon, item) }
}
}
}

View File

@ -0,0 +1,38 @@
/*
* 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/>.
*
*/
package org.kiwix.kiwixmobile.core.history.ViewModel
import android.content.Intent
import org.kiwix.kiwixmobile.core.history.HistoryListItem
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
sealed class Action {
object ExitedSearch : Action()
object ClickedSearchInText : Action()
object ReceivedPromptForSpeechInput : Action()
object StartSpeechInputFailed : 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 CreatedWithIntent(val intent: Intent?) : Action()
data class ActivityResultReceived(val requestCode: Int, val resultCode: Int, val data: Intent?) :
Action()
}

View File

@ -0,0 +1,113 @@
package org.kiwix.kiwixmobile.core.history.ViewModel
import Finish
import ProcessActivityResult
import SearchIntentProcessing
import ShowToast
import StartSpeechInput
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.processors.BehaviorProcessor
import io.reactivex.processors.PublishProcessor
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.base.SideEffect
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
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.CreatedWithIntent
import org.kiwix.kiwixmobile.core.history.ViewModel.Action.ExitedSearch
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.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 javax.inject.Inject
class HistoryViewModel @Inject constructor() : 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()
}
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)
is CreatedWithIntent -> effects.offer(SearchIntentProcessing(it.intent, actions))
ReceivedPromptForSpeechInput -> effects.offer(StartSpeechInput(actions))
StartSpeechInputFailed -> effects.offer(ShowToast(R.string.speech_not_supported))
is ActivityResultReceived ->
effects.offer(ProcessActivityResult(it.requestCode, it.resultCode, it.data, actions))
}
}.subscribe(
{},
Throwable::printStackTrace
)
private fun deleteItemAndShowToast(it: ConfirmedDelete) {
effects.offer(DeleteRecentSearch(it.searchListItem, recentSearchDao))
effects.offer(ShowToast(R.string.delete_specific_search_toast))
}
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

@ -0,0 +1,37 @@
/*
* 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/>.
*
*/
package org.kiwix.kiwixmobile.core.history.ViewModel
import org.kiwix.kiwixmobile.core.history.HistoryListItem
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
sealed class State {
abstract val searchString: String
data class Results(
override val searchString: String,
val selectedItems: List<HistoryListItem>,
val viewAllHistoryToggle: Boolean
) : State()
data class NoResults(override val searchString: String) :
State()
}

View File

@ -0,0 +1,32 @@
/*
* 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 DeleteRecentSearch(
private val searchListItem: SearchListItem,
private val recentSearchDao: NewRecentSearchDao
) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
recentSearchDao.deleteSearchString(searchListItem.value)
}
}

View File

@ -0,0 +1,25 @@
/*
* 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
object Finish : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
activity.finish()
}
}

View File

@ -0,0 +1,35 @@
/*
* 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 android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED
data class OpenSearchItem(private val searchListItem: SearchListItem) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
activity.setResult(
Activity.RESULT_OK,
Intent().putExtra(TAG_FILE_SEARCHED, searchListItem.value)
)
activity.finish()
}
}

View File

@ -0,0 +1,43 @@
/*
* 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 android.app.Activity
import android.content.Intent
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
data class ProcessActivityResult(
private val requestCode: Int,
private val resultCode: Int,
private val data: Intent?,
private val actions: PublishProcessor<Action>
) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
if (requestCode == StartSpeechInput.REQ_CODE_SPEECH_INPUT &&
resultCode == Activity.RESULT_OK &&
data != null
) {
actions.offer(Filter(data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)[0]))
}
}
}

View File

@ -0,0 +1,33 @@
/*
* 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

@ -0,0 +1,41 @@
/*
* 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 android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED
data class SearchInPreviousScreen(private val searchString: String) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
activity.setResult(
Activity.RESULT_OK,
Intent().apply {
putExtra(EXTRA_SEARCH_IN_TEXT, true)
putExtra(TAG_FILE_SEARCHED, searchString)
}
)
activity.finish()
}
companion object {
const val EXTRA_SEARCH_IN_TEXT = "bool_searchintext"
}
}

View File

@ -0,0 +1,60 @@
/*
* 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 android.annotation.TargetApi
import android.content.Intent
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.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?,
private val actions: PublishProcessor<Action>
) : SideEffect<Unit> {
@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)))
}
if (intent.hasExtra(EXTRA_SEARCH)) {
actions.offer(Filter(intent.getStringExtra(EXTRA_SEARCH)))
}
if (intent.getBooleanExtra(EXTRA_IS_WIDGET_VOICE, false)) {
actions.offer(ReceivedPromptForSpeechInput)
}
}
}
}

View File

@ -0,0 +1,41 @@
/*
* 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

@ -0,0 +1,30 @@
/*
* 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 android.widget.Toast
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.extensions.toast
data class ShowToast(@StringRes private val stringId: Int) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
activity.toast(stringId, Toast.LENGTH_SHORT)
}
}

View File

@ -0,0 +1,54 @@
/*
* 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 android.content.ActivityNotFoundException
import android.content.Intent
import android.speech.RecognizerIntent
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 java.util.Locale
data class StartSpeechInput(private val actions: PublishProcessor<Action>) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
try {
activity.startActivityForResult(
Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
putExtra(
RecognizerIntent.EXTRA_PROMPT,
activity.getString(R.string.speech_prompt_text, activity.getString(R.string.app_name))
)
},
REQ_CODE_SPEECH_INPUT
)
} catch (a: ActivityNotFoundException) {
actions.offer(StartSpeechInputFailed)
}
}
companion object {
const val REQ_CODE_SPEECH_INPUT = 100
}
}