From de88dd6c55e23bfbea14f489b85128f3fdf1fce1 Mon Sep 17 00:00:00 2001 From: Frans-Lukas Date: Sun, 12 Apr 2020 15:01:30 +0200 Subject: [PATCH] #1990 rewrite of HistoryActivity WORK IN PROGRESS --- .../core/history/HistoryActivity.kt | 108 +++++++++++++++++ .../core/history/HistoryAdapter2.kt | 10 ++ .../core/history/HistoryDelegate.kt | 23 ++++ .../core/history/HistoryItemViewHolder2.kt | 37 ++++++ .../core/history/ViewModel/Action.kt | 38 ++++++ .../history/ViewModel/HistoryViewModel.kt | 113 ++++++++++++++++++ .../core/history/ViewModel/State.kt | 37 ++++++ .../ViewModel/effects/DeleteRecentSearch.kt | 32 +++++ .../core/history/ViewModel/effects/Finish.kt | 25 ++++ .../ViewModel/effects/OpenSearchItem.kt | 35 ++++++ .../effects/ProcessActivityResult.kt | 43 +++++++ .../ViewModel/effects/SaveSearchToRecents.kt | 33 +++++ .../effects/SearchInPreviousScreen.kt | 41 +++++++ .../effects/SearchIntentProcessing.kt | 60 ++++++++++ .../effects/ShowDeleteSearchDialog.kt | 41 +++++++ .../history/ViewModel/effects/ShowToast.kt | 30 +++++ .../ViewModel/effects/StartSpeechInput.kt | 54 +++++++++ 17 files changed, 760 insertions(+) create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryActivity.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryAdapter2.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryDelegate.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryItemViewHolder2.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/Action.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/HistoryViewModel.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/State.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/DeleteRecentSearch.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/Finish.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/OpenSearchItem.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ProcessActivityResult.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SaveSearchToRecents.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SearchInPreviousScreen.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SearchIntentProcessing.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ShowDeleteSearchDialog.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ShowToast.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/StartSpeechInput.kt diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryActivity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryActivity.kt new file mode 100644 index 000000000..3003982e3 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryActivity.kt @@ -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 = ArrayList() + private val fullHistory: List = ArrayList() + private val deleteList: List = ArrayList() + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val recyclerView: RecyclerView = recycler_view + private val historyViewModel by lazy { viewMdel(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") + } + +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryAdapter2.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryAdapter2.kt new file mode 100644 index 000000000..3c4103ed2 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryAdapter2.kt @@ -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 +) : BaseDelegateAdapter(*delegates){ + override fun getIdFor(item: HistoryListItem): Long = item.id +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryDelegate.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryDelegate.kt new file mode 100644 index 000000000..e5b3b84d4 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryDelegate.kt @@ -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> : + AbsDelegateAdapter { + + class HistoryItemDelegate( + private val deleteList: List, + private val itemClickListener: OnItemClickListener + ) : HistoryDelegate(){ + 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) + } + + } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryItemViewHolder2.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryItemViewHolder2.kt new file mode 100644 index 000000000..a12bc290d --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/HistoryItemViewHolder2.kt @@ -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 (containerView: View): + BaseViewHolder(containerView){ + + class HistoryItemViewHolder( + override val containerView: View, + private val deleteList: List, + private val itemClickListener: OnItemClickListener + ) : HistoryItemViewHolder2(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) } + } + + } + + +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/Action.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/Action.kt new file mode 100644 index 000000000..235b91aa0 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/Action.kt @@ -0,0 +1,38 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + +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() +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/HistoryViewModel.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/HistoryViewModel.kt new file mode 100644 index 000000000..b707cd84c --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/HistoryViewModel.kt @@ -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().apply{ value = NoResults("")} + val effects = PublishProcessor.create>() + val actions = PublishProcessor.create() + 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, + zimSearchResults: List, + 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()) +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/State.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/State.kt new file mode 100644 index 000000000..6e46b80aa --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/State.kt @@ -0,0 +1,37 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + +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, + val viewAllHistoryToggle: Boolean + ) : State() + + data class NoResults(override val searchString: String) : + State() +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/DeleteRecentSearch.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/DeleteRecentSearch.kt new file mode 100644 index 000000000..3540211fe --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/DeleteRecentSearch.kt @@ -0,0 +1,32 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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 { + override fun invokeWith(activity: AppCompatActivity) { + recentSearchDao.deleteSearchString(searchListItem.value) + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/Finish.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/Finish.kt new file mode 100644 index 000000000..6692a7d6d --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/Finish.kt @@ -0,0 +1,25 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ +import androidx.appcompat.app.AppCompatActivity +import org.kiwix.kiwixmobile.core.base.SideEffect + +object Finish : SideEffect { + override fun invokeWith(activity: AppCompatActivity) { + activity.finish() + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/OpenSearchItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/OpenSearchItem.kt new file mode 100644 index 000000000..778230fb1 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/OpenSearchItem.kt @@ -0,0 +1,35 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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 { + override fun invokeWith(activity: AppCompatActivity) { + activity.setResult( + Activity.RESULT_OK, + Intent().putExtra(TAG_FILE_SEARCHED, searchListItem.value) + ) + activity.finish() + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ProcessActivityResult.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ProcessActivityResult.kt new file mode 100644 index 000000000..80b1d54b5 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ProcessActivityResult.kt @@ -0,0 +1,43 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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 +) : SideEffect { + 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])) + } + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SaveSearchToRecents.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SaveSearchToRecents.kt new file mode 100644 index 000000000..3fc8bfad4 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SaveSearchToRecents.kt @@ -0,0 +1,33 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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 { + override fun invokeWith(activity: AppCompatActivity) { + id?.let { recentSearchDao.saveSearch(searchListItem.value, it) } + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SearchInPreviousScreen.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SearchInPreviousScreen.kt new file mode 100644 index 000000000..105d04d6b --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SearchInPreviousScreen.kt @@ -0,0 +1,41 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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 { + 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" + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SearchIntentProcessing.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SearchIntentProcessing.kt new file mode 100644 index 000000000..ad20e7bbc --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/SearchIntentProcessing.kt @@ -0,0 +1,60 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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 +) : SideEffect { + @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) + } + } + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ShowDeleteSearchDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ShowDeleteSearchDialog.kt new file mode 100644 index 000000000..f746829db --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ShowDeleteSearchDialog.kt @@ -0,0 +1,41 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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 +) : SideEffect { + + @Inject lateinit var dialogShower: DialogShower + + override fun invokeWith(activity: AppCompatActivity) { + (activity as SearchActivity).activityComponent.inject(this) + dialogShower.show(DeleteSearch, { actions.offer(Action.ConfirmedDelete(searchListItem)) }) + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ShowToast.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ShowToast.kt new file mode 100644 index 000000000..936ef84a4 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/ShowToast.kt @@ -0,0 +1,30 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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 { + override fun invokeWith(activity: AppCompatActivity) { + activity.toast(stringId, Toast.LENGTH_SHORT) + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/StartSpeechInput.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/StartSpeechInput.kt new file mode 100644 index 000000000..db70e6a1b --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/history/ViewModel/effects/StartSpeechInput.kt @@ -0,0 +1,54 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * 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 . + * + */ + + +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) : SideEffect { + + 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 + } +}