From 068399dbb3452e982e499a82b436c839260db649 Mon Sep 17 00:00:00 2001 From: Ivan Iskandar Date: Fri, 27 Aug 2021 20:57:28 +0700 Subject: [PATCH] Add IME_FLAG_NO_PERSONALIZED_LEARNING flag to text input when incognito is enabled Tested with Gboard only. --- .../ui/base/controller/DialogController.kt | 19 +++++++++ .../controller/SearchableNucleusController.kt | 11 ++++- .../browse/extension/ExtensionController.kt | 9 +++- .../ui/category/CategoryCreateDialog.kt | 2 +- .../ui/category/CategoryRenameDialog.kt | 2 +- .../ui/manga/track/TrackSearchDialog.kt | 2 + .../ui/recent/history/HistoryController.kt | 7 +++- .../tachiyomi/util/view/ViewExtensions.kt | 41 +++++++++++++++++++ .../MaterialAlertDialogBuilderExtensions.kt | 4 ++ 9 files changed, 92 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/DialogController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/DialogController.kt index 9fe0cffd2b..dd62405a33 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/DialogController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/DialogController.kt @@ -9,6 +9,9 @@ import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.Router import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.cancel /** * A controller that displays a dialog window, floating on top of its activity's window. @@ -23,6 +26,22 @@ abstract class DialogController : Controller { private var dismissed = false + lateinit var lifecycleScope: CoroutineScope + + init { + addLifecycleListener( + object : LifecycleListener() { + override fun preCreateView(controller: Controller) { + lifecycleScope = MainScope() + } + + override fun preDestroyView(controller: Controller, view: View) { + lifecycleScope.cancel() + } + } + ) + } + /** * Convenience constructor for use when no arguments are needed. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SearchableNucleusController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SearchableNucleusController.kt index ddeadcb33f..89862c682c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SearchableNucleusController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SearchableNucleusController.kt @@ -9,6 +9,7 @@ import androidx.annotation.StringRes import androidx.appcompat.widget.SearchView import androidx.viewbinding.ViewBinding import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.util.view.setIncognitoFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.appcompat.QueryTextEvent @@ -49,9 +50,17 @@ abstract class SearchableNucleusController(bundle: Bundle? = null) : DialogController(bundle) override fun onCreateDialog(savedViewState: Bundle?): Dialog { return MaterialAlertDialogBuilder(activity!!) .setTitle(R.string.action_add_category) - .setTextInput(prefill = currentName) { + .setTextInput(lifecycleScope = lifecycleScope, prefill = currentName) { currentName = it } .setPositiveButton(android.R.string.ok) { _, _ -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryRenameDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryRenameDialog.kt index 2910eb1e1d..aaf9dafd2b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryRenameDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryRenameDialog.kt @@ -37,7 +37,7 @@ class CategoryRenameDialog(bundle: Bundle? = null) : DialogController(bundle) override fun onCreateDialog(savedViewState: Bundle?): Dialog { return MaterialAlertDialogBuilder(activity!!) .setTitle(R.string.action_rename_category) - .setTextInput(prefill = currentName) { + .setTextInput(lifecycleScope = lifecycleScope, prefill = currentName) { currentName = it } .setPositiveButton(android.R.string.ok) { _, _ -> onPositive() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt index 441c3943d5..7e69f26b6b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt @@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.databinding.TrackSearchDialogBinding import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.manga.MangaController +import eu.kanade.tachiyomi.util.view.setIncognitoFlow import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn @@ -92,6 +93,7 @@ class TrackSearchDialog : DialogController { search(currentlySearched) // Input listener + binding?.titleInput?.editText?.setIncognitoFlow(trackController.viewScope) binding?.titleInput?.editText ?.editorActionEvents { when (it.actionId) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt index 14347c9eb6..ebbfd70366 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt @@ -28,6 +28,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.view.onAnimationsFinished +import eu.kanade.tachiyomi.util.view.setIncognitoFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -208,7 +209,11 @@ class HistoryController : // Fixes problem with the overflow icon showing up in lieu of search searchItem.fixExpand( - onExpand = { invalidateMenuOnExpand() } + onExpand = { + val result = invalidateMenuOnExpand() + searchView.setIncognitoFlow(viewScope) + result + } ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt index 79d7942df5..08f44504ab 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt @@ -10,16 +10,19 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup +import android.widget.EditText import android.widget.TextView import androidx.annotation.MenuRes import androidx.annotation.StringRes import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.widget.PopupMenu +import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.TooltipCompat import androidx.core.view.children import androidx.core.view.descendants import androidx.core.view.forEach +import androidx.core.view.inputmethod.EditorInfoCompat import androidx.recyclerview.widget.RecyclerView import androidx.viewpager.widget.ViewPager import com.google.android.material.card.MaterialCardView @@ -29,8 +32,14 @@ import com.google.android.material.elevation.ElevationOverlayProvider import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton import com.google.android.material.snackbar.Snackbar import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.isNightMode +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.launchIn +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get /** * Returns coordinates of view. @@ -255,3 +264,35 @@ fun ViewPager.getActivePageView(): View? { false } } + +/** + * Sets Flow to this [SearchView] that sets [EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING] to imeOptions + * if [PreferencesHelper.incognitoMode] is true. + * + * Some IMEs may not respect this flag. + */ +fun SearchView.setIncognitoFlow(viewScope: CoroutineScope) { + Injekt.get().incognitoMode().asImmediateFlow { + imeOptions = if (it) { + imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING + } else { + imeOptions and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() + } + }.launchIn(viewScope) +} + +/** + * Sets Flow to this [EditText] that sets [EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING] to imeOptions + * if [PreferencesHelper.incognitoMode] is true. + * + * Some IMEs may not respect this flag. + */ +fun EditText.setIncognitoFlow(viewScope: CoroutineScope) { + Injekt.get().incognitoMode().asImmediateFlow { + imeOptions = if (it) { + imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING + } else { + imeOptions and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() + } + }.launchIn(viewScope) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialAlertDialogBuilderExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialAlertDialogBuilderExtensions.kt index 7c98756d2e..cdfe8304ac 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialAlertDialogBuilderExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/materialdialogs/MaterialAlertDialogBuilderExtensions.kt @@ -11,8 +11,11 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import eu.kanade.tachiyomi.databinding.DialogStubQuadstatemultichoiceBinding import eu.kanade.tachiyomi.databinding.DialogStubTextinputBinding +import eu.kanade.tachiyomi.util.view.setIncognitoFlow +import kotlinx.coroutines.CoroutineScope fun MaterialAlertDialogBuilder.setTextInput( + lifecycleScope: CoroutineScope, hint: String? = null, prefill: String? = null, onTextChanged: (String) -> Unit @@ -20,6 +23,7 @@ fun MaterialAlertDialogBuilder.setTextInput( val binding = DialogStubTextinputBinding.inflate(LayoutInflater.from(context)) binding.textField.hint = hint binding.textField.editText?.apply { + setIncognitoFlow(lifecycleScope) setText(prefill, TextView.BufferType.EDITABLE) doAfterTextChanged { onTextChanged(it?.toString() ?: "")