mirror of
https://github.com/FossifyOrg/Keyboard.git
synced 2026-02-18 22:58:23 -05:00
feat: add option to play sound on keypress (#361)
* feat: add option to play sound on keypress * fix: use consistent naming * fix: respect system preference by default Refs: https://github.com/FossifyOrg/Keyboard/issues/79
This commit is contained in:
@@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Option to play sound on keypress ([#79])
|
||||
- Optional key to quickly switch keyboard language ([#62])
|
||||
- Added apostrophe as a pop-up character on the dot key ([#356])
|
||||
|
||||
@@ -123,6 +124,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
[#47]: https://github.com/FossifyOrg/Keyboard/issues/47
|
||||
[#62]: https://github.com/FossifyOrg/Keyboard/issues/62
|
||||
[#78]: https://github.com/FossifyOrg/Keyboard/issues/78
|
||||
[#79]: https://github.com/FossifyOrg/Keyboard/issues/79
|
||||
[#100]: https://github.com/FossifyOrg/Keyboard/issues/100
|
||||
[#117]: https://github.com/FossifyOrg/Keyboard/issues/117
|
||||
[#129]: https://github.com/FossifyOrg/Keyboard/issues/129
|
||||
|
||||
@@ -3,10 +3,8 @@ package org.fossify.keyboard.activities
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import org.fossify.commons.dialogs.RadioGroupDialog
|
||||
import org.fossify.commons.extensions.beGoneIf
|
||||
import org.fossify.commons.extensions.beVisibleIf
|
||||
import org.fossify.commons.extensions.getProperPrimaryColor
|
||||
import org.fossify.commons.extensions.isOrWasThankYouInstalled
|
||||
import org.fossify.commons.extensions.toast
|
||||
import org.fossify.commons.extensions.updateTextColors
|
||||
import org.fossify.commons.extensions.viewBinding
|
||||
@@ -29,6 +27,9 @@ import org.fossify.keyboard.helpers.KEYBOARD_HEIGHT_160_PERCENT
|
||||
import org.fossify.keyboard.helpers.KEYBOARD_HEIGHT_70_PERCENT
|
||||
import org.fossify.keyboard.helpers.KEYBOARD_HEIGHT_80_PERCENT
|
||||
import org.fossify.keyboard.helpers.KEYBOARD_HEIGHT_90_PERCENT
|
||||
import org.fossify.keyboard.helpers.SOUND_ALWAYS
|
||||
import org.fossify.keyboard.helpers.SOUND_NONE
|
||||
import org.fossify.keyboard.helpers.SOUND_SYSTEM
|
||||
import java.util.Locale
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@@ -54,6 +55,7 @@ class SettingsActivity : SimpleActivity() {
|
||||
setupLanguage()
|
||||
setupManageClipboardItems()
|
||||
setupVibrateOnKeypress()
|
||||
setupSoundOnKeypress()
|
||||
setupShowPopupOnKeypress()
|
||||
setupShowKeyBorders()
|
||||
setupManageKeyboardLanguages()
|
||||
@@ -128,6 +130,35 @@ class SettingsActivity : SimpleActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSoundOnKeypress() {
|
||||
binding.apply {
|
||||
settingsSoundOnKeypress.text = getSoundOnKeypressText(config.soundOnKeypress)
|
||||
settingsSoundOnKeypressHolder.setOnClickListener {
|
||||
val items = arrayListOf(
|
||||
RadioItem(SOUND_NONE, getString(R.string.sound_none)),
|
||||
RadioItem(SOUND_SYSTEM, getString(R.string.sound_system)),
|
||||
RadioItem(SOUND_ALWAYS, getString(R.string.sound_always))
|
||||
)
|
||||
RadioGroupDialog(
|
||||
activity = this@SettingsActivity,
|
||||
items = items,
|
||||
checkedItemId = config.soundOnKeypress
|
||||
) {
|
||||
config.soundOnKeypress = it as Int
|
||||
settingsSoundOnKeypress.text = getSoundOnKeypressText(config.soundOnKeypress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSoundOnKeypressText(mode: Int): String = getString(
|
||||
when (mode) {
|
||||
SOUND_SYSTEM -> R.string.sound_system
|
||||
SOUND_ALWAYS -> R.string.sound_always
|
||||
else -> R.string.sound_none
|
||||
}
|
||||
)
|
||||
|
||||
private fun setupShowPopupOnKeypress() {
|
||||
binding.apply {
|
||||
settingsShowPopupOnKeypress.isChecked = config.showPopupOnKeypress
|
||||
|
||||
@@ -15,6 +15,10 @@ class Config(context: Context) : BaseConfig(context) {
|
||||
get() = prefs.getBoolean(VIBRATE_ON_KEYPRESS, true)
|
||||
set(vibrateOnKeypress) = prefs.edit().putBoolean(VIBRATE_ON_KEYPRESS, vibrateOnKeypress).apply()
|
||||
|
||||
var soundOnKeypress: Int
|
||||
get() = prefs.getInt(SOUND_ON_KEYPRESS, SOUND_SYSTEM)
|
||||
set(soundOnKeypress) = prefs.edit().putInt(SOUND_ON_KEYPRESS, soundOnKeypress).apply()
|
||||
|
||||
var showPopupOnKeypress: Boolean
|
||||
get() = prefs.getBoolean(SHOW_POPUP_ON_KEYPRESS, true)
|
||||
set(showPopupOnKeypress) = prefs.edit().putBoolean(SHOW_POPUP_ON_KEYPRESS, showPopupOnKeypress).apply()
|
||||
|
||||
@@ -12,6 +12,12 @@ const val MAX_KEYS_PER_MINI_ROW = 9
|
||||
|
||||
// shared prefs
|
||||
const val VIBRATE_ON_KEYPRESS = "vibrate_on_keypress"
|
||||
|
||||
const val SOUND_ON_KEYPRESS = "sound_on_keypress"
|
||||
const val SOUND_NONE = 0
|
||||
const val SOUND_SYSTEM = 1
|
||||
const val SOUND_ALWAYS = 2
|
||||
|
||||
const val SHOW_POPUP_ON_KEYPRESS = "show_popup_on_keypress"
|
||||
const val SHOW_KEY_BORDERS = "show_key_borders"
|
||||
const val SENTENCES_CAPITALIZATION = "sentences_capitalization"
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.fossify.keyboard.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioManager
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.View
|
||||
import org.fossify.commons.extensions.performHapticFeedback
|
||||
import org.fossify.commons.helpers.isOreoMr1Plus
|
||||
import org.fossify.keyboard.extensions.config
|
||||
import org.fossify.keyboard.extensions.safeStorageContext
|
||||
|
||||
/**
|
||||
* Helper for keypress haptics and audio.
|
||||
*/
|
||||
class KeyboardFeedbackManager(private val context: Context) {
|
||||
|
||||
private val config = context.safeStorageContext.config
|
||||
private val audioManager by lazy {
|
||||
context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform haptic feedback for standard keypress.
|
||||
*/
|
||||
fun vibrateIfNeeded(view: View) {
|
||||
if (config.vibrateOnKeypress) view.performHapticFeedback()
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform haptic feedback for cursor handle movement.
|
||||
*/
|
||||
fun performHapticHandleMove(view: View) {
|
||||
if (!config.vibrateOnKeypress) return
|
||||
if (isOreoMr1Plus()) {
|
||||
@Suppress("DEPRECATION")
|
||||
view.performHapticFeedback(
|
||||
HapticFeedbackConstants.TEXT_HANDLE_MOVE,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Play keypress sound if enabled.
|
||||
*/
|
||||
fun playKeypressSoundIfNeeded(code: Int) {
|
||||
val soundMode = config.soundOnKeypress
|
||||
if (soundMode == SOUND_NONE) return
|
||||
|
||||
val effect = when (code) {
|
||||
MyKeyboard.KEYCODE_DELETE -> AudioManager.FX_KEYPRESS_DELETE
|
||||
MyKeyboard.KEYCODE_ENTER -> AudioManager.FX_KEYPRESS_RETURN
|
||||
MyKeyboard.KEYCODE_SPACE -> AudioManager.FX_KEYPRESS_SPACEBAR
|
||||
else -> AudioManager.FX_KEYPRESS_STANDARD
|
||||
}
|
||||
|
||||
when (soundMode) {
|
||||
SOUND_SYSTEM -> audioManager.playSoundEffect(effect)
|
||||
SOUND_ALWAYS -> audioManager.playSoundEffect(effect, 1.0f)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform both haptic and audio feedback for a keypress.
|
||||
*/
|
||||
fun performKeypressFeedback(view: View, keyCode: Int) {
|
||||
vibrateIfNeeded(view)
|
||||
playKeypressSoundIfNeeded(keyCode)
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,28 @@ import android.icu.util.ULocale
|
||||
import android.inputmethodservice.InputMethodService
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.InputType.*
|
||||
import android.text.InputType.TYPE_CLASS_DATETIME
|
||||
import android.text.InputType.TYPE_CLASS_NUMBER
|
||||
import android.text.InputType.TYPE_CLASS_PHONE
|
||||
import android.text.InputType.TYPE_CLASS_TEXT
|
||||
import android.text.InputType.TYPE_MASK_CLASS
|
||||
import android.text.InputType.TYPE_MASK_VARIATION
|
||||
import android.text.InputType.TYPE_NULL
|
||||
import android.text.TextUtils
|
||||
import android.util.Size
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.*
|
||||
import android.view.inputmethod.CursorAnchorInfo
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.EditorInfo.IME_ACTION_NONE
|
||||
import android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION
|
||||
import android.view.inputmethod.EditorInfo.IME_MASK_ACTION
|
||||
import android.view.inputmethod.ExtractedTextRequest
|
||||
import android.view.inputmethod.InlineSuggestionsRequest
|
||||
import android.view.inputmethod.InlineSuggestionsResponse
|
||||
import android.view.inputmethod.InputConnection
|
||||
import android.view.inputmethod.InputMethodSubtype
|
||||
import android.widget.inline.InlinePresentationSpec
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.autofill.inline.UiVersions
|
||||
@@ -35,8 +47,23 @@ import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat.Type
|
||||
import androidx.core.view.updatePadding
|
||||
import org.fossify.commons.extensions.*
|
||||
import org.fossify.commons.helpers.*
|
||||
import org.fossify.commons.extensions.applyColorFilter
|
||||
import org.fossify.commons.extensions.getProperBackgroundColor
|
||||
import org.fossify.commons.extensions.getProperTextColor
|
||||
import org.fossify.commons.extensions.getSharedPrefs
|
||||
import org.fossify.commons.extensions.setSystemBarsAppearance
|
||||
import org.fossify.commons.helpers.ACCENT_COLOR
|
||||
import org.fossify.commons.helpers.BACKGROUND_COLOR
|
||||
import org.fossify.commons.helpers.CUSTOM_ACCENT_COLOR
|
||||
import org.fossify.commons.helpers.CUSTOM_BACKGROUND_COLOR
|
||||
import org.fossify.commons.helpers.CUSTOM_PRIMARY_COLOR
|
||||
import org.fossify.commons.helpers.CUSTOM_TEXT_COLOR
|
||||
import org.fossify.commons.helpers.IS_GLOBAL_THEME_ENABLED
|
||||
import org.fossify.commons.helpers.IS_SYSTEM_THEME_ENABLED
|
||||
import org.fossify.commons.helpers.PRIMARY_COLOR
|
||||
import org.fossify.commons.helpers.TEXT_COLOR
|
||||
import org.fossify.commons.helpers.isNougatPlus
|
||||
import org.fossify.commons.helpers.isPiePlus
|
||||
import org.fossify.keyboard.R
|
||||
import org.fossify.keyboard.activities.SettingsActivity
|
||||
import org.fossify.keyboard.databinding.KeyboardViewKeyboardBinding
|
||||
@@ -46,7 +73,56 @@ import org.fossify.keyboard.extensions.getKeyboardLanguageText
|
||||
import org.fossify.keyboard.extensions.getSelectedLanguagesSorted
|
||||
import org.fossify.keyboard.extensions.getStrokeColor
|
||||
import org.fossify.keyboard.extensions.safeStorageContext
|
||||
import org.fossify.keyboard.helpers.*
|
||||
import org.fossify.keyboard.helpers.HEIGHT_PERCENTAGE
|
||||
import org.fossify.keyboard.helpers.KEYBOARD_LANGUAGE
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ARABIC
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_BELARUSIAN_CYRL
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_BELARUSIAN_LATN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_BENGALI
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_BULGARIAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_CENTRAL_KURDISH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_CHUVASH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_CZECH_QWERTY
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_CZECH_QWERTZ
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_DANISH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_DUTCH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_ASSET
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_COLEMAK
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_COLEMAKDH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_DVORAK
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_NIRO
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_QWERTZ
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_SOUL
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ENGLISH_WORKMAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ESPERANTO
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_FRENCH_AZERTY
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_FRENCH_BEPO
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_GERMAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_GERMAN_QWERTZ
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_GREEK
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_HEBREW
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ITALIAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_KABYLE_AZERTY
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_LATVIAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_LITHUANIAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_NORWEGIAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_POLISH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_PORTUGUESE
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_PORTUGUESE_HCESAR
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_ROMANIAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_RUSSIAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_SLOVENIAN
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_SPANISH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_SWEDISH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_TURKISH
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_TURKISH_Q
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_UKRAINIAN
|
||||
import org.fossify.keyboard.helpers.MyKeyboard
|
||||
import org.fossify.keyboard.helpers.SHOW_KEY_BORDERS
|
||||
import org.fossify.keyboard.helpers.SHOW_NUMBERS_ROW
|
||||
import org.fossify.keyboard.helpers.ShiftState
|
||||
import org.fossify.keyboard.helpers.VOICE_INPUT_METHOD
|
||||
import org.fossify.keyboard.helpers.cachedVNTelexData
|
||||
import org.fossify.keyboard.interfaces.OnKeyboardActionListener
|
||||
import org.fossify.keyboard.views.MyKeyboardView
|
||||
import java.io.ByteArrayOutputStream
|
||||
@@ -108,7 +184,7 @@ class SimpleKeyboardIME : InputMethodService(), OnKeyboardActionListener, Shared
|
||||
|
||||
override fun onPress(primaryCode: Int) {
|
||||
if (primaryCode != 0) {
|
||||
keyboardView?.vibrateIfNeeded()
|
||||
keyboardView?.performKeypressFeedback(primaryCode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.os.Message
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
@@ -61,12 +60,10 @@ import org.fossify.commons.extensions.getProperPrimaryColor
|
||||
import org.fossify.commons.extensions.getProperTextColor
|
||||
import org.fossify.commons.extensions.isDynamicTheme
|
||||
import org.fossify.commons.extensions.lightenColor
|
||||
import org.fossify.commons.extensions.performHapticFeedback
|
||||
import org.fossify.commons.extensions.removeUnderlines
|
||||
import org.fossify.commons.extensions.toast
|
||||
import org.fossify.commons.helpers.HIGHER_ALPHA
|
||||
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||
import org.fossify.commons.helpers.isOreoMr1Plus
|
||||
import org.fossify.commons.helpers.isPiePlus
|
||||
import org.fossify.keyboard.R
|
||||
import org.fossify.keyboard.activities.ManageClipboardItemsActivity
|
||||
@@ -90,6 +87,7 @@ import org.fossify.keyboard.extensions.safeStorageContext
|
||||
import org.fossify.keyboard.helpers.AccessHelper
|
||||
import org.fossify.keyboard.helpers.EMOJI_SPEC_FILE_PATH
|
||||
import org.fossify.keyboard.helpers.EmojiData
|
||||
import org.fossify.keyboard.helpers.KeyboardFeedbackManager
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_TURKISH_Q
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_VIETNAMESE_TELEX
|
||||
import org.fossify.keyboard.helpers.LANGUAGE_VN_TELEX
|
||||
@@ -137,6 +135,7 @@ class MyKeyboardView @JvmOverloads constructor(
|
||||
private var keyboardViewBinding: KeyboardViewKeyboardBinding? = null
|
||||
|
||||
private var accessHelper: AccessHelper? = null
|
||||
private val feedbackManager by lazy { KeyboardFeedbackManager(context) }
|
||||
|
||||
private var mKeyboard: MyKeyboard? = null
|
||||
private var mCurrentKeyIndex: Int = NOT_A_KEY
|
||||
@@ -546,20 +545,15 @@ class MyKeyboardView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
fun vibrateIfNeeded() {
|
||||
if (context.config.vibrateOnKeypress) {
|
||||
performHapticFeedback()
|
||||
}
|
||||
feedbackManager.vibrateIfNeeded(this)
|
||||
}
|
||||
|
||||
fun performKeypressFeedback(keyCode: Int) {
|
||||
feedbackManager.performKeypressFeedback(this, keyCode)
|
||||
}
|
||||
|
||||
fun performHapticHandleMove() {
|
||||
if (!context.config.vibrateOnKeypress) return
|
||||
if (isOreoMr1Plus()) {
|
||||
@Suppress("DEPRECATION")
|
||||
performHapticFeedback(
|
||||
HapticFeedbackConstants.TEXT_HANDLE_MOVE,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING
|
||||
)
|
||||
}
|
||||
feedbackManager.performHapticHandleMove(this)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -177,6 +177,28 @@
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_sound_on_keypress_holder"
|
||||
style="@style/SettingsHolderTextViewStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_sound_on_keypress_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sound_on_keypress" />
|
||||
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_sound_on_keypress"
|
||||
style="@style/SettingsTextValueStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/settings_sound_on_keypress_label" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_show_popup_on_keypress_holder"
|
||||
style="@style/SettingsHolderSwitchStyle"
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
<string name="show_clipboard_content">Show clipboard content if available</string>
|
||||
<string name="show_popup">Show a popup on keypress</string>
|
||||
<string name="vibrate_on_keypress">Vibrate on keypress</string>
|
||||
<string name="sound_on_keypress">Sound on keypress</string>
|
||||
<string name="sound_none">Off</string>
|
||||
<string name="sound_system">Follow system</string>
|
||||
<string name="sound_always">Always on</string>
|
||||
<string name="keyboard_language">Keyboard language</string>
|
||||
<string name="keyboard_height">Keyboard height</string>
|
||||
<string name="show_key_borders">Show key borders</string>
|
||||
|
||||
Reference in New Issue
Block a user