Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ private void setKeyboard(final KeyboardElement keyboardElement, @NonNull final K
&& (currentSettingsValues.mInlineEmojiSearch || currentSettingsValues.mSuggestEmojis)) {
EmojiParserKt.loadEmojiDefaultVersionsAndPopupSpecs(mThemeContext);
}

// the mode changed (e.g. numpad/dpad), so refresh the toolbar toggle highlights
if (mSuggestionStripView != null) {
mSuggestionStripView.updateToolbarButtonStates();
}
}

@Nullable public Keyboard getKeyboard() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ class KeyboardIconsSet private constructor() {
"start_onehanded_mode_key" to ToolbarKey.ONE_HANDED.name.lowercase(Locale.US),
)

// todo: incognito and force incognito should not be the same? or not the same as toolbar key?
private val keyboardIconsHolo by lazy { hashMapOf(
NAME_SHIFT_KEY to R.drawable.sym_keyboard_shift_holo,
NAME_SHIFT_KEY_SHIFTED to R.drawable.sym_keyboard_shifted_holo,
Expand Down Expand Up @@ -138,7 +137,7 @@ class KeyboardIconsSet private constructor() {
ToolbarKey.PASTE -> R.drawable.sym_keyboard_paste
ToolbarKey.ONE_HANDED -> R.drawable.sym_keyboard_start_onehanded_holo
ToolbarKey.FLOATING -> R.drawable.ic_drag_indicator
ToolbarKey.INCOGNITO -> R.drawable.sym_keyboard_incognito_holo
ToolbarKey.INCOGNITO -> R.drawable.ic_incognito
ToolbarKey.AUTOCORRECT -> R.drawable.ic_autocorrect
ToolbarKey.CLEAR_CLIPBOARD -> R.drawable.sym_keyboard_clear_clipboard_holo
ToolbarKey.CLOSE_HISTORY -> R.drawable.ic_close
Expand Down Expand Up @@ -202,7 +201,7 @@ class KeyboardIconsSet private constructor() {
ToolbarKey.PASTE -> R.drawable.sym_keyboard_paste
ToolbarKey.ONE_HANDED -> R.drawable.sym_keyboard_start_onehanded_lxx
ToolbarKey.FLOATING -> R.drawable.ic_drag_indicator
ToolbarKey.INCOGNITO -> R.drawable.sym_keyboard_incognito_lxx
ToolbarKey.INCOGNITO -> R.drawable.ic_incognito
ToolbarKey.AUTOCORRECT -> R.drawable.ic_autocorrect
ToolbarKey.CLEAR_CLIPBOARD -> R.drawable.sym_keyboard_clear_clipboard_lxx
ToolbarKey.CLOSE_HISTORY -> R.drawable.ic_close
Expand Down Expand Up @@ -266,7 +265,7 @@ class KeyboardIconsSet private constructor() {
ToolbarKey.PASTE -> R.drawable.sym_keyboard_paste_rounded
ToolbarKey.ONE_HANDED -> R.drawable.sym_keyboard_start_onehanded_rounded
ToolbarKey.FLOATING -> R.drawable.ic_drag_indicator
ToolbarKey.INCOGNITO -> R.drawable.sym_keyboard_incognito_lxx
ToolbarKey.INCOGNITO -> R.drawable.ic_incognito
ToolbarKey.AUTOCORRECT -> R.drawable.ic_autocorrect_rounded
ToolbarKey.CLEAR_CLIPBOARD -> R.drawable.sym_keyboard_clear_clipboard_rounded
ToolbarKey.CLOSE_HISTORY -> R.drawable.ic_close_rounded
Expand Down
16 changes: 6 additions & 10 deletions app/src/main/java/helium314/keyboard/latin/common/Colors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,9 @@ class DynamicColors(context: Context, override val themeStyle: String, override
private val spaceBarStateList: ColorStateList
private val adjustedBackgroundStateList: ColorStateList
private val stripBackgroundList: ColorStateList
private val toolbarKeyStateList = activatedStateList(
keyText,
if (isBrightColor(keyText)) darken(darken(keyText))
else brighten(brighten(keyText))
)
// enabled toolbar toggles use the accent (same as the selected emoji category, EMOJI_CATEGORY_SELECTED
// -> doubleAdjustedAccent), everything else the plain key color
private val toolbarKeyStateList = activatedStateList(darken(darken(accent)), keyText)

/** darkened variant of [accent] because the accent color is always light for dynamic colors */
private val adjustedAccent: Int = darken(accent)
Expand Down Expand Up @@ -400,11 +398,9 @@ class DefaultColors (
private val spaceBarStateList: ColorStateList
private val adjustedBackgroundStateList: ColorStateList
private val stripBackgroundList: ColorStateList
private val toolbarKeyStateList = activatedStateList(
suggestionText,
if (isBrightColor(suggestionText)) darken(darken(suggestionText))
else brighten(brighten(suggestionText))
)
// enabled toolbar toggles use the accent (same as the selected emoji category,
// EMOJI_CATEGORY_SELECTED -> accent), everything else the plain suggestion color
private val toolbarKeyStateList = activatedStateList(accent, suggestionText)
private var backgroundSetupDone = false

init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
Expand Down Expand Up @@ -55,18 +56,14 @@ import helium314.keyboard.latin.utils.getPinnedToolbarKeys
import helium314.keyboard.latin.utils.prefs
import helium314.keyboard.latin.utils.removeFirst
import helium314.keyboard.latin.utils.removePinnedKey
import helium314.keyboard.latin.utils.refreshToolbarButtonActivatedStates
import helium314.keyboard.latin.utils.setToolbarButtonsActivatedStateOnPrefChange
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.math.abs
import kotlin.math.min
import androidx.core.view.isGone
import helium314.keyboard.latin.utils.onClickToolbarKey
import helium314.keyboard.latin.utils.onLongClickToolbarKey
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

@SuppressLint("InflateParams")
class SuggestionStripView(context: Context, attrs: AttributeSet?, defStyle: Int) :
Expand Down Expand Up @@ -119,7 +116,6 @@ class SuggestionStripView(context: Context, attrs: AttributeSet?, defStyle: Int)
private val pinnedKeys: ViewGroup = findViewById(R.id.pinned_keys)
private val suggestionsStrip: ViewGroup = findViewById(R.id.suggestions_strip)
private val toolbarExpandKey = findViewById<ImageButton>(R.id.suggestions_strip_toolbar_key)
private val incognitoIcon = KeyboardIconsSet.instance.getNewDrawable(ToolbarKey.INCOGNITO.name, context)
private val toolbarArrowIcon = KeyboardIconsSet.instance.getNewDrawable(KeyboardIconsSet.NAME_TOOLBAR_KEY, context)
private val defaultToolbarBackground: Drawable = toolbarExpandKey.background
private val enabledToolKeyBackground = GradientDrawable()
Expand Down Expand Up @@ -291,8 +287,12 @@ class SuggestionStripView(context: Context, attrs: AttributeSet?, defStyle: Int)
override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String?) {
setToolbarButtonsActivatedStateOnPrefChange(pinnedKeys, key)
setToolbarButtonsActivatedStateOnPrefChange(toolbar, key)
if (key == Settings.PREF_ALWAYS_INCOGNITO_MODE)
GlobalScope.launch { delay(10); withContext(Dispatchers.Main) { updateKeys() } }
}

/** refresh the toolbar toggle highlights, e.g. after the keyboard mode (numpad/dpad) changed */
fun updateToolbarButtonStates() {
refreshToolbarButtonActivatedStates(toolbar)
refreshToolbarButtonActivatedStates(pinnedKeys)
}

override fun onVisibilityChanged(view: View, visibility: Int) {
Expand Down Expand Up @@ -352,7 +352,10 @@ class SuggestionStripView(context: Context, attrs: AttributeSet?, defStyle: Int)
override fun onLongClick(view: View): Boolean {
if (view.tag is ToolbarKey) {
onLongClickToolbarKey(view)
return true
// when long-press isn't used for pinning keys, don't consume it so the system tooltip
// (set via tooltipText, API 26+) can explain what the key does; on older APIs there is no
// tooltip to consume the press, so keep consuming it to avoid a stray click on release
return Build.VERSION.SDK_INT < Build.VERSION_CODES.O || Settings.getValues().mQuickPinToolbarKeys
}
AudioAndHapticFeedbackManager.getInstance().performHapticFeedback(this, HapticEvent.KEY_LONG_PRESS)
return if (view is TextView && wordViews.contains(view)) {
Expand Down Expand Up @@ -511,19 +514,20 @@ class SuggestionStripView(context: Context, attrs: AttributeSet?, defStyle: Int)
val settingsValues = Settings.getValues()

val toolbarIsExpandable = settingsValues.mToolbarMode == ToolbarMode.EXPANDABLE
if (settingsValues.mIncognitoModeEnabled) {
toolbarExpandKey.setImageDrawable(incognitoIcon)
toolbarExpandKey.isVisible = true
} else {
toolbarExpandKey.setImageDrawable(toolbarArrowIcon)
toolbarExpandKey.isVisible = toolbarIsExpandable
}
updateExpandKeyImage()
// the expand key is only needed when it can toggle the toolbar
toolbarExpandKey.isVisible = toolbarIsExpandable

toolbarExpandKey.setOnClickListener(if (!toolbarIsExpandable) null else this)
pinnedKeys.visibility = suggestionsStrip.visibility
isExternalSuggestionVisible = false
}

private fun updateExpandKeyImage() {
toolbarExpandKey.setImageDrawable(toolbarArrowIcon)
Settings.getValues().mColors.setColor(toolbarExpandKey, ColorType.TOOL_BAR_EXPAND_KEY)
}

private fun addKeyToPinnedKeys(pinnedKey: ToolbarKey) {
val original = toolbar.findViewWithTag<ImageButton>(pinnedKey) ?: return
// copy the original key to a new ImageButton
Expand All @@ -533,6 +537,8 @@ class SuggestionStripView(context: Context, attrs: AttributeSet?, defStyle: Int)
copy.scaleX = original.scaleX
copy.scaleY = original.scaleY
copy.contentDescription = original.contentDescription
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
copy.tooltipText = original.tooltipText // keep the long-press tooltip; also lets it consume the press
copy.setImageDrawable(original.drawable)
copy.layoutParams = original.layoutParams
copy.isActivated = original.isActivated
Expand Down
55 changes: 41 additions & 14 deletions app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package helium314.keyboard.latin.utils

import android.content.Context
import android.content.SharedPreferences
import android.content.res.Configuration
import android.os.Build
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
Expand All @@ -11,6 +13,8 @@ import android.widget.ImageView
import androidx.core.content.edit
import androidx.core.view.forEach
import helium314.keyboard.event.HapticEvent
import helium314.keyboard.keyboard.KeyboardElement
import helium314.keyboard.keyboard.KeyboardSwitcher
import helium314.keyboard.keyboard.internal.KeyboardIconsSet
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
import helium314.keyboard.latin.AudioAndHapticFeedbackManager
Expand All @@ -19,9 +23,6 @@ import helium314.keyboard.latin.common.Constants.Separators
import helium314.keyboard.latin.settings.Defaults
import helium314.keyboard.latin.settings.Settings
import helium314.keyboard.latin.utils.ToolbarKey.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.EnumMap
import java.util.Locale

Expand All @@ -30,8 +31,11 @@ fun createToolbarKey(context: Context, key: ToolbarKey): ImageButton {
button.scaleType = ImageView.ScaleType.CENTER
button.tag = key
button.contentDescription = key.name.lowercase().getStringResourceOrName("", context)
setToolbarButtonActivatedState(button)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
button.tooltipText = button.contentDescription // long-press shows what the key does

button.setImageDrawable(KeyboardIconsSet.instance.getNewDrawable(key.name, context))
setToolbarButtonActivatedState(button)
return button
}

Expand All @@ -41,23 +45,46 @@ fun setToolbarButtonsActivatedStateOnPrefChange(buttonsGroup: ViewGroup, key: St
&& key != Settings.PREF_ALWAYS_INCOGNITO_MODE
&& key != GestureDataGatheringSettings.PREF_BACKGROUND_GATHERING_ENABLED
&& key != GestureDataGatheringSettings.PREF_BACKGROUND_DISABLED_BEFORE_TIME_MILLIS
&& key?.startsWith(Settings.PREF_ONE_HANDED_MODE_PREFIX) == false)
&& key?.startsWith(Settings.PREF_ONE_HANDED_MODE_PREFIX) == false
&& key?.startsWith(Settings.PREF_ENABLE_SPLIT_KEYBOARD) == false)
return

GlobalScope.launch {
delay(10) // need to wait until SettingsValues are reloaded
buttonsGroup.forEach { if (it is ImageButton) setToolbarButtonActivatedState(it) }
}
// states are read straight from prefs (which are already written at this point), so no wait for
// a SettingsValues reload is needed; post only to make sure we touch the views on the UI thread
buttonsGroup.post { buttonsGroup.forEach { if (it is ImageButton) setToolbarButtonActivatedState(it) } }
}

/** refresh the activated state of all toolbar buttons, e.g. after the keyboard mode changed */
fun refreshToolbarButtonActivatedStates(buttonsGroup: ViewGroup) {
buttonsGroup.forEach { if (it is ImageButton) setToolbarButtonActivatedState(it) }
}

private fun setToolbarButtonActivatedState(button: ImageButton) {
// read the current values straight from prefs instead of the cached SettingsValues: that cache is
// only reloaded asynchronously after a pref change, which previously made the toggle color lag or
// show the previous state (and split was never refreshed at all)
val prefs = button.context.prefs()
val landscape = button.context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
val folded = FoldableUtils.isFolded
val split = Settings.readSplitKeyboardEnabled(prefs, landscape, folded)
button.isActivated = when (button.tag) {
INCOGNITO -> button.context.prefs().getBoolean(Settings.PREF_ALWAYS_INCOGNITO_MODE, Defaults.PREF_ALWAYS_INCOGNITO_MODE)
ONE_HANDED -> Settings.getValues().mOneHandedModeEnabled
SPLIT -> Settings.getValues().mIsSplitKeyboardEnabled
AUTOCORRECT -> Settings.getValues().mAutoCorrectionEnabledPerUserSettings
// incognito is highlighted like any other toggle (accent when force-incognito is on); it keeps a
// single plain glasses icon and is only re-tinted, not swapped/crossed out, to match the toolbar
INCOGNITO -> prefs.getBoolean(Settings.PREF_ALWAYS_INCOGNITO_MODE, Defaults.PREF_ALWAYS_INCOGNITO_MODE)
// floating keyboard force-disables one-handed mode (see SettingsValues.mOneHandedModeEnabled),
// so mirror that guard here, otherwise the toggle would light up while floating
ONE_HANDED -> !Settings.getValues().mIsFloatingKeyboard && Settings.readOneHandedModeEnabled(prefs, landscape, split, folded)
SPLIT -> split
AUTOCORRECT -> prefs.getBoolean(Settings.PREF_AUTO_CORRECTION, Defaults.PREF_AUTO_CORRECTION)
// mode keys: highlighted while their panel/mode is the one currently active (not a fleeting action)
NUMPAD -> KeyboardSwitcher.getInstance().isShowingKeyboardId(KeyboardElement.NUMPAD)
DPAD -> KeyboardSwitcher.getInstance().isShowingKeyboardId(KeyboardElement.DPAD)
FLOATING -> Settings.getValues().mIsFloatingKeyboard
BACKGROUND_GATHERING -> useBackgroundGathering
else -> true
// non-toggle keys have no on/off state; keep them neutral so only enabled toggles get
// the activated highlight (previously they were all "activated", which highlighted the
// idle toggles instead of the active ones)
else -> false
}
}

Expand Down
13 changes: 13 additions & 0 deletions app/src/main/res/drawable/ic_incognito.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!--
"incognito" icon from Material Design Icons (Pictogrammers), https://pictogrammers.com/library/mdi/icon/incognito/
SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFF"
android:pathData="M17.06,13C15.2,13 13.64,14.33 13.24,16.1C12.29,15.69 11.42,15.8 10.76,16.09C10.35,14.31 8.79,13 6.94,13C4.77,13 3,14.79 3,17C3,19.21 4.77,21 6.94,21C9,21 10.68,19.38 10.84,17.32C11.18,17.08 12.07,16.63 13.16,17.34C13.34,19.39 15,21 17.06,21C19.23,21 21,19.21 21,17C21,14.79 19.23,13 17.06,13M6.94,19.86C5.38,19.86 4.13,18.58 4.13,17S5.39,14.14 6.94,14.14C8.5,14.14 9.75,15.42 9.75,17S8.5,19.86 6.94,19.86M17.06,19.86C15.5,19.86 14.25,18.58 14.25,17S15.5,14.14 17.06,14.14C18.62,14.14 19.88,15.42 19.88,17S18.61,19.86 17.06,19.86M22,10.5H2V12H22V10.5M15.53,2.63C15.31,2.14 14.75,1.88 14.22,2.05L12,2.79L9.77,2.05L9.72,2.04C9.19,1.89 8.63,2.17 8.43,2.68L6,9H18L15.56,2.68L15.53,2.63Z" />
</vector>