Skip to content
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
## [4.0.0 Beta 5](https://github.com/sds100/KeyMapper/releases/tag/v4.0.0-beta.05)

#### TO BE RELEASED

## Added
- #1947 show tip to use expert mode where the old option for screen off remapping used to be

## Bug fixes

- #1955 step forward and step backward media actions support more apps.
- #1940 improve reliability of clicking pairing code button in Wireless Debugging settings.

## [4.0.0 Beta 4](https://github.com/sds100/KeyMapper/releases/tag/v4.0.0-beta.04)

#### 25 December 2025

Merry Christmas from the Key Mapper team! 🎄

Renamed PRO mode to Expert mode because it sounded like a paid premium feature even though it is free.
Renamed PRO mode to Expert mode because it sounded like a paid premium feature even though it is
free.

## Added

Expand Down
4 changes: 2 additions & 2 deletions app/version.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
VERSION_NAME=4.0.0-beta.04
VERSION_CODE=217
VERSION_NAME=4.0.0-beta.05
VERSION_CODE=220
Original file line number Diff line number Diff line change
Expand Up @@ -785,13 +785,22 @@ object ActionUtils {
listOf(Permission.ROOT)
}

ActionId.PLAY_PAUSE_MEDIA,
ActionId.PLAY_MEDIA,
ActionId.PAUSE_MEDIA,
ActionId.FAST_FORWARD,
ActionId.REWIND,
ActionId.STOP_MEDIA,
ActionId.NEXT_TRACK,
ActionId.PREVIOUS_TRACK,
ActionId.PLAY_PAUSE_MEDIA_PACKAGE,
ActionId.PAUSE_MEDIA_PACKAGE,
ActionId.PLAY_MEDIA_PACKAGE,
ActionId.NEXT_TRACK_PACKAGE,
ActionId.PREVIOUS_TRACK_PACKAGE,
ActionId.FAST_FORWARD_PACKAGE,
ActionId.REWIND_PACKAGE,
ActionId.STOP_MEDIA_PACKAGE,
-> return listOf(Permission.NOTIFICATION_LISTENER)

ActionId.VOLUME_UP,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ class ChooseActionViewModel @Inject constructor(
error == SystemError.PermissionDenied(
Permission.ROOT,
) -> getString(R.string.choose_action_warning_requires_root)

error != null -> error.getFullMessage(this@ChooseActionViewModel)

else -> null
}

Expand Down Expand Up @@ -200,13 +202,6 @@ class ChooseActionViewModel @Inject constructor(

val messageToShow: Int? = when (id) {
ActionId.FAST_FORWARD_PACKAGE,
ActionId.FAST_FORWARD,
-> R.string.action_fast_forward_message

ActionId.REWIND_PACKAGE,
ActionId.REWIND,
-> R.string.action_rewind_message

ActionId.TOGGLE_KEYBOARD,
ActionId.SHOW_KEYBOARD,
ActionId.HIDE_KEYBOARD,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,12 @@ class CreateActionDelegate(
showVolumeUi = state.showVolumeUi,
volumeStream = state.volumeStream,
)

ActionId.VOLUME_DOWN -> ActionData.Volume.Down(
showVolumeUi = state.showVolumeUi,
volumeStream = state.volumeStream,
)

else -> return
}

Expand Down Expand Up @@ -405,8 +407,7 @@ class CreateActionDelegate(
navigate(
"choose_app_for_media_action",
NavDestination.ChooseApp(allowHiddenApps = true),
)
?: return null
) ?: return null

val action = when (actionId) {
ActionId.PAUSE_MEDIA_PACKAGE ->
Expand Down Expand Up @@ -494,7 +495,9 @@ class CreateActionDelegate(

val action = when (actionId) {
ActionId.VOLUME_MUTE -> ActionData.Volume.Mute(showVolumeUi)

ActionId.VOLUME_UNMUTE -> ActionData.Volume.UnMute(showVolumeUi)

ActionId.VOLUME_TOGGLE_MUTE -> ActionData.Volume.ToggleMute(
showVolumeUi,
)
Expand Down Expand Up @@ -574,17 +577,15 @@ class CreateActionDelegate(

val action = when (actionId) {
ActionId.TOGGLE_DND_MODE -> ActionData.DoNotDisturb.Toggle(dndMode)

ActionId.ENABLE_DND_MODE -> ActionData.DoNotDisturb.Enable(dndMode)

else -> throw Exception("don't know how to create action for $actionId")
}

return action
}

ActionId.CYCLE_ROTATIONS -> {
val items = Orientation.values().map { orientation ->
val items = Orientation.entries.map { orientation ->
val isChecked = if (oldData is ActionData.Rotation.CycleRotations) {
oldData.orientations.contains(orientation)
} else {
Expand Down Expand Up @@ -756,11 +757,7 @@ class CreateActionDelegate(
NavDestination.PickCoordinate(oldResult),
) ?: return null

val description = if (result.description.isEmpty()) {
null
} else {
result.description
}
val description = result.description.ifEmpty { null }

return ActionData.TapScreen(
result.x,
Expand Down Expand Up @@ -789,11 +786,7 @@ class CreateActionDelegate(
NavDestination.PickSwipeCoordinate(oldResult),
) ?: return null

val description = if (result.description.isEmpty()) {
null
} else {
result.description
}
val description = result.description.ifEmpty { null }

return ActionData.SwipeScreen(
result.xStart,
Expand Down Expand Up @@ -826,11 +819,7 @@ class CreateActionDelegate(
NavDestination.PickPinchCoordinate(oldResult),
) ?: return null

val description = if (result.description.isEmpty()) {
null
} else {
result.description
}
val description = result.description.ifEmpty { null }

return ActionData.PinchScreen(
result.x,
Expand Down Expand Up @@ -964,93 +953,153 @@ class CreateActionDelegate(
}

ActionId.TOGGLE_WIFI -> return ActionData.Wifi.Toggle

ActionId.ENABLE_WIFI -> return ActionData.Wifi.Enable

ActionId.DISABLE_WIFI -> return ActionData.Wifi.Disable

ActionId.TOGGLE_BLUETOOTH -> return ActionData.Bluetooth.Toggle

ActionId.ENABLE_BLUETOOTH -> return ActionData.Bluetooth.Enable

ActionId.DISABLE_BLUETOOTH -> return ActionData.Bluetooth.Disable

ActionId.TOGGLE_MOBILE_DATA -> return ActionData.MobileData.Toggle

ActionId.ENABLE_MOBILE_DATA -> return ActionData.MobileData.Enable

ActionId.DISABLE_MOBILE_DATA -> return ActionData.MobileData.Disable

ActionId.TOGGLE_HOTSPOT -> return ActionData.Hotspot.Toggle

ActionId.ENABLE_HOTSPOT -> return ActionData.Hotspot.Enable

ActionId.DISABLE_HOTSPOT -> return ActionData.Hotspot.Disable

ActionId.TOGGLE_AUTO_BRIGHTNESS -> return ActionData.Brightness.ToggleAuto

ActionId.DISABLE_AUTO_BRIGHTNESS -> return ActionData.Brightness.DisableAuto

ActionId.ENABLE_AUTO_BRIGHTNESS -> return ActionData.Brightness.EnableAuto

ActionId.INCREASE_BRIGHTNESS -> return ActionData.Brightness.Increase

ActionId.DECREASE_BRIGHTNESS -> return ActionData.Brightness.Decrease

ActionId.TOGGLE_AUTO_ROTATE -> return ActionData.Rotation.ToggleAuto

ActionId.ENABLE_AUTO_ROTATE -> return ActionData.Rotation.EnableAuto

ActionId.DISABLE_AUTO_ROTATE -> return ActionData.Rotation.DisableAuto

ActionId.PORTRAIT_MODE -> return ActionData.Rotation.Portrait

ActionId.LANDSCAPE_MODE -> return ActionData.Rotation.Landscape

ActionId.SWITCH_ORIENTATION -> return ActionData.Rotation.SwitchOrientation

ActionId.VOLUME_SHOW_DIALOG -> return ActionData.Volume.ShowDialog

ActionId.CYCLE_RINGER_MODE -> return ActionData.Volume.CycleRingerMode

ActionId.CYCLE_VIBRATE_RING -> return ActionData.Volume.CycleVibrateRing

ActionId.EXPAND_NOTIFICATION_DRAWER -> return ActionData.StatusBar.ExpandNotifications

ActionId.TOGGLE_NOTIFICATION_DRAWER -> return ActionData.StatusBar.ToggleNotifications

ActionId.EXPAND_QUICK_SETTINGS -> return ActionData.StatusBar.ExpandQuickSettings

ActionId.TOGGLE_QUICK_SETTINGS -> return ActionData.StatusBar.ToggleQuickSettings

ActionId.COLLAPSE_STATUS_BAR -> return ActionData.StatusBar.Collapse

ActionId.PAUSE_MEDIA -> return ActionData.ControlMedia.Pause

ActionId.PLAY_MEDIA -> return ActionData.ControlMedia.Play

ActionId.PLAY_PAUSE_MEDIA -> return ActionData.ControlMedia.PlayPause

ActionId.NEXT_TRACK -> return ActionData.ControlMedia.NextTrack

ActionId.PREVIOUS_TRACK -> return ActionData.ControlMedia.PreviousTrack

ActionId.FAST_FORWARD -> return ActionData.ControlMedia.FastForward

ActionId.REWIND -> return ActionData.ControlMedia.Rewind

ActionId.STOP_MEDIA -> return ActionData.ControlMedia.Stop

ActionId.STEP_FORWARD -> return ActionData.ControlMedia.StepForward

ActionId.STEP_BACKWARD -> return ActionData.ControlMedia.StepBackward

ActionId.GO_BACK -> return ActionData.GoBack

ActionId.GO_HOME -> return ActionData.GoHome

ActionId.OPEN_RECENTS -> return ActionData.OpenRecents

ActionId.TOGGLE_SPLIT_SCREEN -> return ActionData.ToggleSplitScreen

ActionId.GO_LAST_APP -> return ActionData.GoLastApp

ActionId.OPEN_MENU -> return ActionData.OpenMenu

ActionId.ENABLE_NFC -> return ActionData.Nfc.Enable

ActionId.DISABLE_NFC -> return ActionData.Nfc.Disable

ActionId.TOGGLE_NFC -> return ActionData.Nfc.Toggle

ActionId.TOGGLE_KEYBOARD -> return ActionData.ToggleKeyboard

ActionId.SHOW_KEYBOARD -> return ActionData.ShowKeyboard

ActionId.HIDE_KEYBOARD -> return ActionData.HideKeyboard

ActionId.SHOW_KEYBOARD_PICKER -> return ActionData.ShowKeyboardPicker

ActionId.TEXT_CUT -> return ActionData.CutText

ActionId.TEXT_COPY -> return ActionData.CopyText

ActionId.TEXT_PASTE -> return ActionData.PasteText

ActionId.SELECT_WORD_AT_CURSOR -> return ActionData.SelectWordAtCursor

ActionId.TOGGLE_AIRPLANE_MODE -> return ActionData.AirplaneMode.Toggle

ActionId.ENABLE_AIRPLANE_MODE -> return ActionData.AirplaneMode.Enable

ActionId.DISABLE_AIRPLANE_MODE -> return ActionData.AirplaneMode.Disable

ActionId.SCREENSHOT -> return ActionData.Screenshot

ActionId.OPEN_VOICE_ASSISTANT -> return ActionData.VoiceAssistant

ActionId.OPEN_DEVICE_ASSISTANT -> return ActionData.DeviceAssistant

ActionId.OPEN_CAMERA -> return ActionData.OpenCamera

ActionId.LOCK_DEVICE -> return ActionData.LockDevice

ActionId.POWER_ON_OFF_DEVICE -> return ActionData.ScreenOnOff

ActionId.SECURE_LOCK_DEVICE -> return ActionData.SecureLock

ActionId.CONSUME_KEY_EVENT -> return ActionData.ConsumeKeyEvent

ActionId.OPEN_SETTINGS -> return ActionData.OpenSettings

ActionId.SHOW_POWER_MENU -> return ActionData.ShowPowerMenu

ActionId.DISABLE_DND_MODE -> return ActionData.DoNotDisturb.Disable

ActionId.DISMISS_MOST_RECENT_NOTIFICATION -> return ActionData.DismissLastNotification

ActionId.DISMISS_ALL_NOTIFICATIONS -> return ActionData.DismissAllNotifications

ActionId.CREATE_NOTIFICATION -> {
val oldAction = oldData as? ActionData.CreateNotification

Expand All @@ -1063,9 +1112,13 @@ class CreateActionDelegate(

return null
}

ActionId.ANSWER_PHONE_CALL -> return ActionData.AnswerCall

ActionId.END_PHONE_CALL -> return ActionData.EndCall

ActionId.DEVICE_CONTROLS -> return ActionData.DeviceControls

ActionId.HTTP_REQUEST -> {
if (oldData == null) {
httpRequestBottomSheetState = ActionData.HttpRequest(
Expand Down Expand Up @@ -1104,7 +1157,9 @@ class CreateActionDelegate(
}

ActionId.MOVE_CURSOR -> return createMoverCursorAction()

ActionId.FORCE_STOP_APP -> return ActionData.ForceStopApp

ActionId.CLEAR_RECENT_APP -> return ActionData.ClearRecentApp

ActionId.MODIFY_SETTING -> {
Expand Down
Loading
Loading