mirror of
https://github.com/fcitx5-android/fcitx5-android.git
synced 2026-08-02 04:44:35 +08:00
parent
ac490f743d
commit
a586493f34
@ -141,8 +141,13 @@ class AppPrefs(private val sharedPreferences: SharedPreferences) {
|
||||
"keep_keyboard_letters_uppercase",
|
||||
false
|
||||
)
|
||||
|
||||
val showVoiceInputButton =
|
||||
switch(R.string.show_voice_input_button, "show_voice_input_button", false)
|
||||
val preferredVoiceInput = voiceInputPreference(
|
||||
R.string.preferred_voice_input, "preferred_voice_input", ""
|
||||
) { showVoiceInputButton.getValue() }
|
||||
|
||||
val expandKeypressArea =
|
||||
switch(R.string.expand_keypress_area, "expand_keypress_area", false)
|
||||
val swipeSymbolDirection = enumList(
|
||||
|
||||
@ -64,6 +64,20 @@ abstract class ManagedPreferenceCategory(
|
||||
return list(title, key, defaultValue, codec, entryValues, entryLabels, enableUiOn)
|
||||
}
|
||||
|
||||
protected fun voiceInputPreference(
|
||||
@StringRes
|
||||
title: Int,
|
||||
key: String,
|
||||
defaultValue: String,
|
||||
enableUiOn: (() -> Boolean)? = null
|
||||
): ManagedPreference.PString {
|
||||
val pref = ManagedPreference.PString(sharedPreferences, key, defaultValue)
|
||||
val ui = ManagedPreferenceUi.VoiceInputList(title, key, defaultValue, enableUiOn)
|
||||
pref.register()
|
||||
ui.registerUi()
|
||||
return pref
|
||||
}
|
||||
|
||||
protected fun int(
|
||||
@StringRes
|
||||
title: Int,
|
||||
|
||||
@ -9,10 +9,13 @@ import androidx.annotation.StringRes
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import org.fcitx.fcitx5.android.R
|
||||
import org.fcitx.fcitx5.android.ui.main.modified.MySwitchPreference
|
||||
import org.fcitx.fcitx5.android.ui.main.settings.DialogSeekBarPreference
|
||||
import org.fcitx.fcitx5.android.ui.main.settings.EditTextIntPreference
|
||||
import org.fcitx.fcitx5.android.ui.main.settings.TwinSeekBarPreference
|
||||
import org.fcitx.fcitx5.android.utils.InputMethodUtil
|
||||
import org.fcitx.fcitx5.android.utils.includes
|
||||
|
||||
abstract class ManagedPreferenceUi<T : Preference>(
|
||||
val key: String,
|
||||
@ -67,6 +70,38 @@ abstract class ManagedPreferenceUi<T : Preference>(
|
||||
}
|
||||
}
|
||||
|
||||
class VoiceInputList(
|
||||
@StringRes
|
||||
val title: Int,
|
||||
key: String,
|
||||
val defaultValue: String,
|
||||
enableUiOn: (() -> Boolean)? = null
|
||||
) : ManagedPreferenceUi<ListPreference>(key, enableUiOn) {
|
||||
override fun createUi(context: Context) = ListPreference(context).apply {
|
||||
key = this@VoiceInputList.key
|
||||
isIconSpaceReserved = false
|
||||
isSingleLineTitle = false
|
||||
summaryProvider = ListPreference.SimpleSummaryProvider.getInstance()
|
||||
setDefaultValue(defaultValue)
|
||||
setTitle(this@VoiceInputList.title)
|
||||
setDialogTitle(this@VoiceInputList.title)
|
||||
val voiceInputMethods = InputMethodUtil.listVoiceInputMethods()
|
||||
entryValues = arrayOf("", *voiceInputMethods.map { it.first.id }.toTypedArray())
|
||||
entries = arrayOf(
|
||||
context.getString(R.string.system_default),
|
||||
*voiceInputMethods.map { it.first.loadLabel(context.packageManager) }.toTypedArray()
|
||||
)
|
||||
// shows "(Not Available)" if selected id is not present
|
||||
summaryProvider = Preference.SummaryProvider<ListPreference> { preference ->
|
||||
if (preference.entryValues.includes(preference.value)) {
|
||||
preference.entry
|
||||
} else {
|
||||
context.getString(R.string._not_available_)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EditTextInt(
|
||||
@StringRes
|
||||
val title: Int,
|
||||
|
||||
@ -105,6 +105,7 @@ class KawaiiBarComponent : UniqueViewComponent<KawaiiBarComponent, FrameLayout>(
|
||||
private val expandToolbarByDefault by prefs.keyboard.expandToolbarByDefault
|
||||
private val toolbarNumRowOnPassword by prefs.keyboard.toolbarNumRowOnPassword
|
||||
private val showVoiceInputButton by prefs.keyboard.showVoiceInputButton
|
||||
private val preferredVoiceInput by prefs.keyboard.preferredVoiceInput
|
||||
|
||||
private var clipboardTimeoutJob: Job? = null
|
||||
|
||||
@ -450,7 +451,7 @@ class KawaiiBarComponent : UniqueViewComponent<KawaiiBarComponent, FrameLayout>(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
idleUi.inlineSuggestionsBar.clear()
|
||||
}
|
||||
voiceInputSubtype = InputMethodUtil.firstVoiceInput()
|
||||
voiceInputSubtype = InputMethodUtil.findVoiceSubtype(preferredVoiceInput)
|
||||
val shouldShowVoiceInput =
|
||||
showVoiceInputButton && voiceInputSubtype != null && !capFlags.has(CapabilityFlag.Password)
|
||||
idleUi.setHideKeyboardIsVoiceInput(
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* SPDX-FileCopyrightText: Copyright 2026 Fcitx5 for Android Contributors
|
||||
*/
|
||||
|
||||
package org.fcitx.fcitx5.android.utils
|
||||
|
||||
import android.view.inputmethod.InputMethodInfo
|
||||
import android.view.inputmethod.InputMethodSubtype
|
||||
|
||||
fun InputMethodInfo.firstVoiceSubtype() : InputMethodSubtype? {
|
||||
for (index in 0 until subtypeCount) {
|
||||
val subtype = getSubtypeAt(index)
|
||||
if (subtype.mode.lowercase() == "voice") {
|
||||
return subtype
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* SPDX-FileCopyrightText: Copyright 2021-2023 Fcitx5 for Android Contributors
|
||||
* SPDX-FileCopyrightText: Copyright 2021-2026 Fcitx5 for Android Contributors
|
||||
*/
|
||||
package org.fcitx.fcitx5.android.utils
|
||||
|
||||
@ -9,6 +9,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.view.inputmethod.InputMethodInfo
|
||||
import android.view.inputmethod.InputMethodSubtype
|
||||
import org.fcitx.fcitx5.android.BuildConfig
|
||||
import org.fcitx.fcitx5.android.input.FcitxInputMethodService
|
||||
@ -45,13 +46,36 @@ object InputMethodUtil {
|
||||
|
||||
fun showPicker() = appContext.inputMethodManager.showInputMethodPicker()
|
||||
|
||||
fun firstVoiceInput(): Pair<String, InputMethodSubtype>? =
|
||||
appContext.inputMethodManager
|
||||
.shortcutInputMethodsAndSubtypes
|
||||
.firstNotNullOfOrNull {
|
||||
it.value.find { subType -> subType.mode.lowercase() == "voice" }
|
||||
?.let { subType -> it.key.id to subType }
|
||||
fun listVoiceInputMethods(): List<Pair<InputMethodInfo, InputMethodSubtype>> {
|
||||
return appContext.inputMethodManager.enabledInputMethodList
|
||||
.mapNotNull { info ->
|
||||
info.firstVoiceSubtype()?.let { info to it }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find input method with `"voice"` subtype, preferring one with [id]
|
||||
*/
|
||||
fun findVoiceSubtype(id: String): Pair<String, InputMethodSubtype>? {
|
||||
val inputMethods = appContext.inputMethodManager.enabledInputMethodList
|
||||
if (inputMethods.isEmpty()) return null
|
||||
var firstId: String? = null
|
||||
var firstSubtype: InputMethodSubtype? = null
|
||||
inputMethods.forEach {
|
||||
val voiceSubtype = it.firstVoiceSubtype() ?: return@forEach
|
||||
if (it.id == id) {
|
||||
return id to voiceSubtype
|
||||
}
|
||||
if (firstId == null) {
|
||||
firstId = it.id
|
||||
firstSubtype = voiceSubtype
|
||||
}
|
||||
}
|
||||
if (firstId != null && firstSubtype != null) {
|
||||
return firstId to firstSubtype
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun switchInputMethod(
|
||||
service: FcitxInputMethodService,
|
||||
|
||||
@ -316,4 +316,5 @@
|
||||
<string name="emoji_skin_tone_type_6">🏿 深肤色 (Type-6)</string>
|
||||
<string name="hide_unsupported_emojis">隐藏不支持的表情</string>
|
||||
<string name="key_border_stroke">启用按键边框描边</string>
|
||||
<string name="preferred_voice_input">首选语音输入</string>
|
||||
</resources>
|
||||
|
||||
@ -315,4 +315,5 @@
|
||||
<string name="emoji_skin_tone_type_5">🏾 中等深膚色 (Type-5)</string>
|
||||
<string name="emoji_skin_tone_type_6">🏿 深膚色 (Type-6)</string>
|
||||
<string name="hide_unsupported_emojis">隱藏不支援的表情</string>
|
||||
</resources>
|
||||
<string name="preferred_voice_input">首選語音輸入</string>
|
||||
</resources>
|
||||
|
||||
@ -316,4 +316,5 @@
|
||||
<string name="emoji_skin_tone_type_6">🏿 Type-6</string>
|
||||
<string name="hide_unsupported_emojis">Hide unsupported Emojis</string>
|
||||
<string name="key_border_stroke">Enable stroke for key border</string>
|
||||
<string name="preferred_voice_input">Preferred voice input</string>
|
||||
</resources>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user