mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2025-01-03 09:01:50 +01:00
Add IME_FLAG_NO_PERSONALIZED_LEARNING flag to text input when incognito is enabled
Tested with Gboard only.
This commit is contained in:
parent
4b2a9bc621
commit
068399dbb3
@ -9,6 +9,9 @@ import com.bluelinelabs.conductor.Controller
|
|||||||
import com.bluelinelabs.conductor.Router
|
import com.bluelinelabs.conductor.Router
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler
|
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.
|
* 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
|
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.
|
* Convenience constructor for use when no arguments are needed.
|
||||||
*/
|
*/
|
||||||
|
@ -9,6 +9,7 @@ import androidx.annotation.StringRes
|
|||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
|
import eu.kanade.tachiyomi.util.view.setIncognitoFlow
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import reactivecircus.flowbinding.appcompat.QueryTextEvent
|
import reactivecircus.flowbinding.appcompat.QueryTextEvent
|
||||||
@ -49,9 +50,17 @@ abstract class SearchableNucleusController<VB : ViewBinding, P : BasePresenter<*
|
|||||||
// Initialize search option.
|
// Initialize search option.
|
||||||
val searchItem = menu.findItem(searchItemId)
|
val searchItem = menu.findItem(searchItemId)
|
||||||
val searchView = searchItem.actionView as SearchView
|
val searchView = searchItem.actionView as SearchView
|
||||||
searchItem.fixExpand(onExpand = { invalidateMenuOnExpand() })
|
searchItem.fixExpand(
|
||||||
|
onExpand = {
|
||||||
|
val result = invalidateMenuOnExpand()
|
||||||
|
// For BrowseSourceController :)
|
||||||
|
searchView.setIncognitoFlow(viewScope)
|
||||||
|
result
|
||||||
|
}
|
||||||
|
)
|
||||||
searchView.maxWidth = Int.MAX_VALUE
|
searchView.maxWidth = Int.MAX_VALUE
|
||||||
|
|
||||||
|
searchView.setIncognitoFlow(viewScope)
|
||||||
searchView.queryTextEvents()
|
searchView.queryTextEvents()
|
||||||
.onEach {
|
.onEach {
|
||||||
val newText = it.queryText.toString()
|
val newText = it.queryText.toString()
|
||||||
|
@ -19,6 +19,7 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
|||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.ui.browse.BrowseController
|
import eu.kanade.tachiyomi.ui.browse.BrowseController
|
||||||
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsController
|
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsController
|
||||||
|
import eu.kanade.tachiyomi.util.view.setIncognitoFlow
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@ -127,7 +128,13 @@ open class ExtensionController :
|
|||||||
searchView.maxWidth = Int.MAX_VALUE
|
searchView.maxWidth = Int.MAX_VALUE
|
||||||
|
|
||||||
// Fixes problem with the overflow icon showing up in lieu of search
|
// Fixes problem with the overflow icon showing up in lieu of search
|
||||||
searchItem.fixExpand(onExpand = { invalidateMenuOnExpand() })
|
searchItem.fixExpand(
|
||||||
|
onExpand = {
|
||||||
|
val result = invalidateMenuOnExpand()
|
||||||
|
searchView.setIncognitoFlow(viewScope)
|
||||||
|
result
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if (query.isNotEmpty()) {
|
if (query.isNotEmpty()) {
|
||||||
searchItem.expandActionView()
|
searchItem.expandActionView()
|
||||||
|
@ -32,7 +32,7 @@ class CategoryCreateDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
|||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
return MaterialAlertDialogBuilder(activity!!)
|
return MaterialAlertDialogBuilder(activity!!)
|
||||||
.setTitle(R.string.action_add_category)
|
.setTitle(R.string.action_add_category)
|
||||||
.setTextInput(prefill = currentName) {
|
.setTextInput(lifecycleScope = lifecycleScope, prefill = currentName) {
|
||||||
currentName = it
|
currentName = it
|
||||||
}
|
}
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
@ -37,7 +37,7 @@ class CategoryRenameDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
|||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
return MaterialAlertDialogBuilder(activity!!)
|
return MaterialAlertDialogBuilder(activity!!)
|
||||||
.setTitle(R.string.action_rename_category)
|
.setTitle(R.string.action_rename_category)
|
||||||
.setTextInput(prefill = currentName) {
|
.setTextInput(lifecycleScope = lifecycleScope, prefill = currentName) {
|
||||||
currentName = it
|
currentName = it
|
||||||
}
|
}
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ -> onPositive() }
|
.setPositiveButton(android.R.string.ok) { _, _ -> onPositive() }
|
||||||
|
@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
|||||||
import eu.kanade.tachiyomi.databinding.TrackSearchDialogBinding
|
import eu.kanade.tachiyomi.databinding.TrackSearchDialogBinding
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
|
import eu.kanade.tachiyomi.util.view.setIncognitoFlow
|
||||||
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
|
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
@ -92,6 +93,7 @@ class TrackSearchDialog : DialogController {
|
|||||||
search(currentlySearched)
|
search(currentlySearched)
|
||||||
|
|
||||||
// Input listener
|
// Input listener
|
||||||
|
binding?.titleInput?.editText?.setIncognitoFlow(trackController.viewScope)
|
||||||
binding?.titleInput?.editText
|
binding?.titleInput?.editText
|
||||||
?.editorActionEvents {
|
?.editorActionEvents {
|
||||||
when (it.actionId) {
|
when (it.actionId) {
|
||||||
|
@ -28,6 +28,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
|
|||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.onAnimationsFinished
|
import eu.kanade.tachiyomi.util.view.onAnimationsFinished
|
||||||
|
import eu.kanade.tachiyomi.util.view.setIncognitoFlow
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@ -208,7 +209,11 @@ class HistoryController :
|
|||||||
|
|
||||||
// Fixes problem with the overflow icon showing up in lieu of search
|
// Fixes problem with the overflow icon showing up in lieu of search
|
||||||
searchItem.fixExpand(
|
searchItem.fixExpand(
|
||||||
onExpand = { invalidateMenuOnExpand() }
|
onExpand = {
|
||||||
|
val result = invalidateMenuOnExpand()
|
||||||
|
searchView.setIncognitoFlow(viewScope)
|
||||||
|
result
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,16 +10,19 @@ import android.view.Menu
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.EditText
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.MenuRes
|
import androidx.annotation.MenuRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.appcompat.view.menu.MenuBuilder
|
import androidx.appcompat.view.menu.MenuBuilder
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.appcompat.widget.TooltipCompat
|
import androidx.appcompat.widget.TooltipCompat
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.core.view.descendants
|
import androidx.core.view.descendants
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
|
import androidx.core.view.inputmethod.EditorInfoCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import com.google.android.material.card.MaterialCardView
|
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.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import eu.kanade.tachiyomi.R
|
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.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.system.isNightMode
|
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.
|
* Returns coordinates of view.
|
||||||
@ -255,3 +264,35 @@ fun ViewPager.getActivePageView(): View? {
|
|||||||
false
|
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<PreferencesHelper>().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<PreferencesHelper>().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)
|
||||||
|
}
|
||||||
|
@ -11,8 +11,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import eu.kanade.tachiyomi.databinding.DialogStubQuadstatemultichoiceBinding
|
import eu.kanade.tachiyomi.databinding.DialogStubQuadstatemultichoiceBinding
|
||||||
import eu.kanade.tachiyomi.databinding.DialogStubTextinputBinding
|
import eu.kanade.tachiyomi.databinding.DialogStubTextinputBinding
|
||||||
|
import eu.kanade.tachiyomi.util.view.setIncognitoFlow
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
fun MaterialAlertDialogBuilder.setTextInput(
|
fun MaterialAlertDialogBuilder.setTextInput(
|
||||||
|
lifecycleScope: CoroutineScope,
|
||||||
hint: String? = null,
|
hint: String? = null,
|
||||||
prefill: String? = null,
|
prefill: String? = null,
|
||||||
onTextChanged: (String) -> Unit
|
onTextChanged: (String) -> Unit
|
||||||
@ -20,6 +23,7 @@ fun MaterialAlertDialogBuilder.setTextInput(
|
|||||||
val binding = DialogStubTextinputBinding.inflate(LayoutInflater.from(context))
|
val binding = DialogStubTextinputBinding.inflate(LayoutInflater.from(context))
|
||||||
binding.textField.hint = hint
|
binding.textField.hint = hint
|
||||||
binding.textField.editText?.apply {
|
binding.textField.editText?.apply {
|
||||||
|
setIncognitoFlow(lifecycleScope)
|
||||||
setText(prefill, TextView.BufferType.EDITABLE)
|
setText(prefill, TextView.BufferType.EDITABLE)
|
||||||
doAfterTextChanged {
|
doAfterTextChanged {
|
||||||
onTextChanged(it?.toString() ?: "")
|
onTextChanged(it?.toString() ?: "")
|
||||||
|
Loading…
Reference in New Issue
Block a user