Skip to content

Commit

Permalink
Added ghost key functionality. (#961)
Browse files Browse the repository at this point in the history
* Added ghost key functionality. This lets you swipe symbol keys which are not visible, but exist in the corresponding location in the numerical view.

* Added comments and descriptions, simplified key composition logic, ran linter
  • Loading branch information
matthew-sirman authored Jul 7, 2024
1 parent 09dec63 commit eb252a5
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 4 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ Enabling `Backspace: Allow normal swipes to work with slide gestures`, in keyboa
- You can type the opposite-case letter by dragging away from, then back to the original key.
- Clockwise and counter-clockwise drags can be configured to type the opposite-case letter, or the equivalent center key on the numeric layout.

### Ghost keys

Enabling `Ghost keys` in keyboard settings will enable swiping hidden symbol keys without switching to the numeric layout.

### Coming from MessagEase Keyboard Tips

- For those use to tapping on the hand key to hide the MessagEase Keyboard and make more screen real estate available, this can be done by using the Android back key or on Android 10 and higher using the guesture navigation for back.
Expand Down
20 changes: 19 additions & 1 deletion app/src/main/java/com/dessalines/thumbkey/db/AppDb.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const val DEFAULT_DRAG_RETURN_ENABLED = 1
const val DEFAULT_CIRCULAR_DRAG_ENABLED = 1
const val DEFAULT_CLOCKWISE_DRAG_ACTION = 0
const val DEFAULT_COUNTERCLOCKWISE_DRAG_ACTION = 1
const val DEFAULT_GHOST_KEYS_ENABLED = 0

@Entity
data class AppSettings(
Expand Down Expand Up @@ -226,6 +227,11 @@ data class AppSettings(
defaultValue = DEFAULT_COUNTERCLOCKWISE_DRAG_ACTION.toString(),
)
val counterclockwiseDragAction: Int,
@ColumnInfo(
name = "ghost_keys_enabled",
defaultValue = DEFAULT_GHOST_KEYS_ENABLED.toString(),
)
val ghostKeysEnabled: Int,
)

data class LayoutsUpdate(
Expand Down Expand Up @@ -334,6 +340,8 @@ data class BehaviorUpdate(
val clockwiseDragAction: Int,
@ColumnInfo(name = "counterclockwise_drag_action")
val counterclockwiseDragAction: Int,
@ColumnInfo(name = "ghost_keys_enabled")
val ghostKeysEnabled: Int,
)

@Dao
Expand Down Expand Up @@ -565,8 +573,17 @@ val MIGRATION_14_15 =
}
}

val MIGRATION_15_16 =
object : Migration(15, 16) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL(
"alter table AppSettings add column ghost_keys_enabled INTEGER NOT NULL default $DEFAULT_GHOST_KEYS_ENABLED",
)
}
}

@Database(
version = 15,
version = 16,
entities = [AppSettings::class],
exportSchema = true,
)
Expand Down Expand Up @@ -603,6 +620,7 @@ abstract class AppDB : RoomDatabase() {
MIGRATION_12_13,
MIGRATION_13_14,
MIGRATION_14_15,
MIGRATION_15_16,
)
// Necessary because it can't insert data on creation
.addCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import com.dessalines.thumbkey.utils.KeyboardDefinitionSettings
import com.dessalines.thumbkey.utils.Selection
import com.dessalines.thumbkey.utils.SlideType
import com.dessalines.thumbkey.utils.SwipeDirection
import com.dessalines.thumbkey.utils.SwipeNWay
import com.dessalines.thumbkey.utils.buildTapActions
import com.dessalines.thumbkey.utils.circularDirection
import com.dessalines.thumbkey.utils.colorVariantToColor
Expand All @@ -80,6 +81,10 @@ import kotlin.math.min
@Composable
fun KeyboardKey(
key: KeyItemC,
// Hidden background key to detect swipes for. When a swipe isn't captured by the key, the ghost
// key will attempt to capture it instead. This is derived automatically from the keyboard
// layout, and should not be set directly in the keyboard definition.
ghostKey: KeyItemC? = null,
lastAction: MutableState<KeyAction?>,
animationHelperSpeed: Int,
animationSpeed: Int,
Expand Down Expand Up @@ -120,7 +125,7 @@ fun KeyboardKey(
) {
// Necessary for swipe settings to get updated correctly
val id =
key.toString() + animationHelperSpeed + animationSpeed + autoCapitalize +
key.toString() + ghostKey.toString() + animationHelperSpeed + animationSpeed + autoCapitalize +
vibrateOnTap + soundOnTap + legendHeight + legendWidth + minSwipeLength + slideSensitivity +
slideEnabled + slideCursorMovementMode + slideSpacebarDeadzoneEnabled +
slideBackspaceDeadzoneEnabled + dragReturnEnabled + circularDragEnabled +
Expand Down Expand Up @@ -469,8 +474,15 @@ fun KeyboardKey(
)
} else {
val swipeDirection =
swipeDirection(offsetX, offsetY, minSwipeLength, key.swipeType)
key.swipes?.get(swipeDirection)?.action
swipeDirection(
offsetX,
offsetY,
minSwipeLength,
if (ghostKey == null) key.swipeType else SwipeNWay.EIGHT_WAY,
)
key.swipes?.get(swipeDirection)?.action ?: (
ghostKey?.swipes?.get(swipeDirection)?.action
)
}
) ?: key.center.action

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import com.dessalines.thumbkey.db.DEFAULT_CIRCULAR_DRAG_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_CLOCKWISE_DRAG_ACTION
import com.dessalines.thumbkey.db.DEFAULT_COUNTERCLOCKWISE_DRAG_ACTION
import com.dessalines.thumbkey.db.DEFAULT_DRAG_RETURN_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_GHOST_KEYS_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_HIDE_LETTERS
import com.dessalines.thumbkey.db.DEFAULT_HIDE_SYMBOLS
import com.dessalines.thumbkey.db.DEFAULT_KEYBOARD_LAYOUT
Expand Down Expand Up @@ -143,6 +144,7 @@ fun KeyboardScreen(
val clockwiseDragAction = CircularDragAction.entries[settings?.clockwiseDragAction ?: DEFAULT_CLOCKWISE_DRAG_ACTION]
val counterclockwiseDragAction =
CircularDragAction.entries[settings?.counterclockwiseDragAction ?: DEFAULT_COUNTERCLOCKWISE_DRAG_ACTION]
val ghostKeysEnabled = (settings?.ghostKeysEnabled ?: DEFAULT_GHOST_KEYS_ENABLED).toBool()

val keyBorderWidthFloat = keyBorderWidth / 10.0f
val keyBorderColour = MaterialTheme.colorScheme.outline
Expand Down Expand Up @@ -362,8 +364,19 @@ fun KeyboardScreen(
Row {
row.forEachIndexed { j, key ->
Column {
val ghostKey =
if (ghostKeysEnabled) {
when (mode) {
KeyboardMode.MAIN -> keyboardDefinition.modes.numeric
KeyboardMode.SHIFTED -> keyboardDefinition.modes.numeric
else -> null
}?.arr?.getOrNull(i)?.getOrNull(j)
} else {
null
}
KeyboardKey(
key = key,
ghostKey = ghostKey,
lastAction = lastAction,
legendHeight = legendHeight,
legendWidth = legendWidth,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import com.dessalines.thumbkey.db.DEFAULT_CIRCULAR_DRAG_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_CLOCKWISE_DRAG_ACTION
import com.dessalines.thumbkey.db.DEFAULT_COUNTERCLOCKWISE_DRAG_ACTION
import com.dessalines.thumbkey.db.DEFAULT_DRAG_RETURN_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_GHOST_KEYS_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_HIDE_LETTERS
import com.dessalines.thumbkey.db.DEFAULT_HIDE_SYMBOLS
import com.dessalines.thumbkey.db.DEFAULT_KEYBOARD_LAYOUT
Expand Down Expand Up @@ -306,6 +307,7 @@ private fun resetAppSettingsToDefault(appSettingsViewModel: AppSettingsViewModel
circularDragEnabled = DEFAULT_CIRCULAR_DRAG_ENABLED,
clockwiseDragAction = DEFAULT_CLOCKWISE_DRAG_ACTION,
counterclockwiseDragAction = DEFAULT_COUNTERCLOCKWISE_DRAG_ACTION,
ghostKeysEnabled = DEFAULT_GHOST_KEYS_ENABLED,
),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.compose.material.icons.automirrored.outlined.Backspace
import androidx.compose.material.icons.automirrored.outlined.RotateLeft
import androidx.compose.material.icons.automirrored.outlined.RotateRight
import androidx.compose.material.icons.outlined.Abc
import androidx.compose.material.icons.outlined.BorderInner
import androidx.compose.material.icons.outlined.Circle
import androidx.compose.material.icons.outlined.SpaceBar
import androidx.compose.material.icons.outlined.SwapHoriz
Expand Down Expand Up @@ -43,6 +44,7 @@ import com.dessalines.thumbkey.db.DEFAULT_CIRCULAR_DRAG_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_CLOCKWISE_DRAG_ACTION
import com.dessalines.thumbkey.db.DEFAULT_COUNTERCLOCKWISE_DRAG_ACTION
import com.dessalines.thumbkey.db.DEFAULT_DRAG_RETURN_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_GHOST_KEYS_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_MIN_SWIPE_LENGTH
import com.dessalines.thumbkey.db.DEFAULT_SLIDE_BACKSPACE_DEADZONE_ENABLED
import com.dessalines.thumbkey.db.DEFAULT_SLIDE_CURSOR_MOVEMENT_MODE
Expand Down Expand Up @@ -94,6 +96,7 @@ fun BehaviorActivity(
var clockwiseDragActionState = CircularDragAction.entries[settings?.clockwiseDragAction ?: DEFAULT_CLOCKWISE_DRAG_ACTION]
var counterclockwiseDragActionState =
CircularDragAction.entries[settings?.counterclockwiseDragAction ?: DEFAULT_COUNTERCLOCKWISE_DRAG_ACTION]
var ghostKeysEnabledState = (settings?.ghostKeysEnabled ?: DEFAULT_GHOST_KEYS_ENABLED).toBool()

val snackbarHostState = remember { SnackbarHostState() }

Expand All @@ -117,6 +120,7 @@ fun BehaviorActivity(
circularDragEnabled = circularDragEnabledState.toInt(),
clockwiseDragAction = clockwiseDragActionState.ordinal,
counterclockwiseDragAction = counterclockwiseDragActionState.ordinal,
ghostKeysEnabled = ghostKeysEnabledState.toInt(),
),
)
}
Expand Down Expand Up @@ -381,6 +385,25 @@ fun BehaviorActivity(
)
},
)
SwitchPreference(
value = ghostKeysEnabledState,
onValueChange = {
ghostKeysEnabledState = it
updateBehavior()
},
title = {
Text(stringResource(R.string.ghost_keys_enable))
},
summary = {
Text(stringResource(R.string.ghost_keys_description))
},
icon = {
Icon(
imageVector = Icons.Outlined.BorderInner,
contentDescription = stringResource(R.string.ghost_keys_enable),
)
},
)
SettingsDivider()
TestOutTextField()
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,6 @@
<string name="send_oppsite_case">Opposite case letter</string>
<string name="send_numeric">Number key</string>
<string name="circular_drag_enable">Circular drag</string>
<string name="ghost_keys_enable">Ghost keys</string>
<string name="ghost_keys_description">Access hidden symbol keys without switching to numeric view</string>
</resources>

0 comments on commit eb252a5

Please sign in to comment.