Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
b648682
shorten release notes
sds100 Apr 10, 2025
1f10931
shorten release notes even more
sds100 Apr 10, 2025
bd87fbe
bump version to 3.0.1
sds100 Apr 10, 2025
b4703a7
delete redundant untranslated fastlane files
sds100 Apr 13, 2025
3e7b013
update play store description to include accessibility service disclo…
sds100 Apr 14, 2025
362f63d
fix: check that indexes are in range for moving list elements
sds100 Apr 17, 2025
bab9c86
fix: check that a URL can be opened and show a toast if not
sds100 Apr 17, 2025
bf09b42
fix: wait for input events from Shizuku to processed by the applicati…
sds100 Apr 17, 2025
90d2af8
chore: bump version code
sds100 Apr 17, 2025
18afd17
show version code in about page
sds100 Apr 17, 2025
2e9db96
fix: improve how key events are inputted with Shizuku
sds100 Apr 20, 2025
0bf3bf6
Revert "#1618 The Key Mapper keyboard is no longer required for Text …
sds100 Apr 20, 2025
550c49b
chore: update changelog
sds100 Apr 20, 2025
b0adf0d
#1653 Hide the export/import menu buttons in groups
sds100 Apr 20, 2025
dd62674
#1652 feat: Bring back the menu button to show input method picker
sds100 Apr 20, 2025
da42d87
#1646 fix: disabling Bluetooth clears the list of connected devices
sds100 Apr 20, 2025
b69bdd6
update app title
sds100 Apr 20, 2025
24872b5
fix: try to fix CorruptionException in datastore by updating to 1.2.0…
sds100 Apr 20, 2025
3a09324
#1655 fix: do not crash when restoring key map groups
sds100 Apr 20, 2025
4a697b6
#1657 feat: turn on repeat by default for volume actions
sds100 Apr 20, 2025
ef92321
bump version code
sds100 Apr 20, 2025
ef8cf7f
bump version code
sds100 Apr 27, 2025
a5ac810
style: reformat
sds100 Apr 27, 2025
1af0c08
#1648 fix: revenuecat caching works
sds100 Apr 27, 2025
542045f
#1649 fix: show verification error if there is a network error when f…
sds100 Apr 27, 2025
6ddaa53
update changelog
sds100 Apr 27, 2025
5aa5d22
#1658 fix: floating buttons appear in the wrong place in portrait if …
sds100 Apr 27, 2025
3bd799d
#1659 fix: Use trigger does not work if the screen orientation change…
sds100 Apr 27, 2025
123f98e
fix missing import
sds100 Apr 27, 2025
c4c916f
Merge remote-tracking branch 'origin/develop' into develop
sds100 Apr 27, 2025
9f67f7c
#1668 fix: Crashes when floating menu does not fit in the display hei…
sds100 Apr 27, 2025
edb7b38
#1667 fix: hold down mode UI is missing from 2.8.
sds100 Apr 27, 2025
a39b793
chore: bump version code
sds100 Apr 27, 2025
fa6c77d
color behind the gesture bar on the home screen
sds100 Apr 27, 2025
7f9bd5d
#1553 fix: hide double press option for side key and fingerprint gest…
sds100 Apr 27, 2025
7a47797
fix bottom padding on key map selection bottom sheet
sds100 Apr 27, 2025
ebdf159
fix: keys with do not remap option would show dot before in key map list
sds100 Apr 27, 2025
b3da012
fix: do not allow mixing click types in a parallel trigger
sds100 Apr 28, 2025
ae43028
#1669 change tile text
sds100 Apr 28, 2025
b117301
chore: bump version code
sds100 Apr 28, 2025
5d95314
complete changelog for 3.0.1
sds100 Apr 28, 2025
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
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
## [3.0.1](https://github.com/sds100/KeyMapper/releases/tag/v3.0.1)

#### 28 April 2025

## Added

- #1652 Bring back the menu button to show input method picker.
- #1657 Turn on repeat by default for volume actions.

## Changed

- #1654 The Key Mapper keyboard is now required again for Text actions because the accessibility service API does not work in all situations.
- #1653 Hide the export/import menu buttons in groups.
- #1553 Hide double press option for side key and fingerprint gesture triggers because it is misleading. Double activations can be done with sequence triggers instead.
- #1669 Change quick settings tile text.

## Bug fixes

- Inputting key events with Shizuku does not crash the app if a Key Mapper keyboard is being used at the same time. And latency when inputting key events has been improved in some apps.
- #1646 disabling Bluetooth clears the list of connected devices.
- #1655 do not crash when restoring key map groups.
- #1649 show purchase verification failed error if no network connection.
- #1648 caching purchases works so you can use floating buttons and assistant trigger without an internet connection.
- #1658 floating buttons appear in the wrong place in portrait if saved in landscape.
- #1659 Use trigger does not work if the screen orientation changes when re-entering the app.
- #1668 Crashes when floating menu does not fit in the display height.
- #1667 Hold down mode UI is missing from 2.8.

## [3.0.0](https://github.com/sds100/KeyMapper/releases/tag/v3.0.0)

_See the changes from previous 3.0 Beta releases._
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.viewpager2:viewpager2:1.1.0"
implementation "androidx.datastore:datastore-preferences:1.1.4"
implementation "androidx.datastore:datastore-preferences:1.2.0-alpha01"
implementation "androidx.core:core-splashscreen:1.0.1"
implementation "androidx.activity:activity-compose:1.10.1"
implementation "androidx.navigation:navigation-compose:2.8.9"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class PurchasingManagerImpl(
private val coroutineScope: CoroutineScope,
) : PurchasingManager {
override val onCompleteProductPurchase: MutableSharedFlow<ProductId> = MutableSharedFlow()
override val purchases: Flow<State<Set<ProductId>>> = MutableStateFlow(State.Data(emptySet()))
override val purchases: Flow<State<Result<Set<ProductId>>>> =
MutableStateFlow(State.Data(Error.PurchasingNotImplemented))

override suspend fun launchPurchasingFlow(product: ProductId): Result<Unit> {
return Error.PurchasingNotImplemented
Expand All @@ -27,4 +28,6 @@ class PurchasingManagerImpl(
override suspend fun isPurchased(product: ProductId): Result<Boolean> {
return Error.PurchasingNotImplemented
}

override fun refresh() {}
}
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@
android:name=".system.tiles.ToggleMappingsTile"
android:exported="true"
android:icon="@drawable/ic_tile_pause"
android:label="@string/tile_pause"
android:label="@string/tile_pause_title"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
tools:targetApi="24">
<intent-filter>
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/assets/whats-new.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Key Mapper 3.0 is here! 🎉

🫧 This release introduces Floating Buttons: you can create custom on-screen buttons to trigger key maps.
🫧 Floating Buttons: you can create custom on-screen buttons to trigger key maps.

🗂️ Grouping key maps into folders with shared constraints.

🔦 You can now change the flashlight brightness. Tip: use the constraint for when the flashlight is showing to remap your volume buttons to change the brightness.
🔦 Change the flashlight brightness. Tip: use the constraint for when the flashlight is showing to remap your volume buttons to change the brightness.

🛜 Send HTTP requests with a new action.

❤️ There are also tonnes of improvements to make your key mapping experience more enjoyable.
❤️ Many improvements to make your key mapping experience more enjoyable.

See all the changes at http://changelog.keymapper.club.
5 changes: 3 additions & 2 deletions app/src/main/java/io/github/sds100/keymapper/UseCases.kt
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ object UseCases {
ServiceLocator.intentAdapter(ctx),
getActionError(ctx),
keyMapperImeMessenger(ctx, keyEventRelayService),
ShizukuInputEventInjector(),
ShizukuInputEventInjector(coroutineScope = ServiceLocator.appCoroutineScope(ctx)),
ServiceLocator.packageManagerAdapter(ctx),
ServiceLocator.appShortcutAdapter(ctx),
ServiceLocator.popupMessageAdapter(ctx),
Expand Down Expand Up @@ -179,11 +179,12 @@ object UseCases {
ServiceLocator.audioAdapter(ctx),
keyMapperImeMessenger(ctx, keyEventRelayService),
service,
ShizukuInputEventInjector(),
ShizukuInputEventInjector(ServiceLocator.appCoroutineScope(ctx)),
ServiceLocator.popupMessageAdapter(ctx),
ServiceLocator.permissionAdapter(ctx),
ServiceLocator.resourceProvider(ctx),
ServiceLocator.vibratorAdapter(ctx),
ServiceLocator.appCoroutineScope(ctx),
)

fun rerouteKeyEvents(ctx: Context, keyEventRelayService: KeyEventRelayServiceWrapper) = RerouteKeyEventsUseCaseImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class AboutFragment : Fragment() {
onBackPressed()
}

version = Constants.VERSION
version = "${Constants.VERSION} ${Constants.VERSION_CODE}"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
Expand All @@ -44,6 +45,7 @@ import io.github.sds100.keymapper.util.ui.SliderStepSizes
import io.github.sds100.keymapper.util.ui.compose.CheckBoxText
import io.github.sds100.keymapper.util.ui.compose.RadioButtonText
import io.github.sds100.keymapper.util.ui.compose.SliderOptionText
import io.github.sds100.keymapper.util.ui.compose.openUriSafe
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
Expand All @@ -63,6 +65,7 @@ fun ActionOptionsBottomSheet(
dragHandle = {},
) {
val uriHandler = LocalUriHandler.current
val ctx = LocalContext.current
val helpUrl = stringResource(R.string.url_keymap_action_options_guide)
val scope = rememberCoroutineScope()

Expand All @@ -80,7 +83,7 @@ fun ActionOptionsBottomSheet(
modifier = Modifier
.align(Alignment.TopEnd)
.padding(horizontal = 8.dp),
onClick = { uriHandler.openUri(helpUrl) },
onClick = { uriHandler.openUriSafe(ctx, helpUrl) },
) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.HelpOutline,
Expand Down Expand Up @@ -261,7 +264,36 @@ fun ActionOptionsBottomSheet(
)
}

Spacer(Modifier.height(8.dp))
if (state.showHoldDownMode) {
Spacer(Modifier.height(8.dp))

Text(
modifier = Modifier.padding(horizontal = 16.dp),
text = stringResource(R.string.hold_down_until_trigger_is_dot_dot_dot),
style = MaterialTheme.typography.titleSmall,
)

FlowRow(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
RadioButtonText(
isSelected = state.holdDownMode == HoldDownMode.TRIGGER_RELEASED,
text = stringResource(R.string.stop_holding_down_when_trigger_released),
onSelected = { callback.onSelectHoldDownMode(HoldDownMode.TRIGGER_RELEASED) },
)

RadioButtonText(
isSelected = state.holdDownMode == HoldDownMode.TRIGGER_PRESSED_AGAIN,
text = stringResource(R.string.stop_holding_down_trigger_pressed_again),
onSelected = { callback.onSelectHoldDownMode(HoldDownMode.TRIGGER_PRESSED_AGAIN) },
)

Spacer(Modifier.width(8.dp))
}
}

if (state.showHoldDown) {
Spacer(Modifier.height(8.dp))
Expand Down Expand Up @@ -352,6 +384,7 @@ interface ActionOptionsBottomSheetCallback {
fun onRepeatDelayChanged(delay: Int) = run { }
fun onHoldDownCheckedChange(checked: Boolean) = run { }
fun onHoldDownDurationChanged(duration: Int) = run { }
fun onSelectHoldDownMode(holdDownMode: HoldDownMode) = run { }
fun onDelayBeforeNextActionChanged(delay: Int) = run { }
fun onMultiplierChanged(multiplier: Int) = run { }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,8 +781,7 @@ fun ActionData.canBeHeldDown(): Boolean = when (this) {

fun ActionData.canUseImeToPerform(): Boolean = when (this) {
is ActionData.InputKeyEvent -> !useShell
// Android 13+ can use the accessibility service to input text.
is ActionData.Text -> Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
is ActionData.Text -> true
is ActionData.MoveCursorToEnd -> true
else -> false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,15 @@ class ConfigActionsViewModel(
actionOptionsUid.value?.let { uid -> config.setActionHoldDownDuration(uid, duration) }
}

override fun onSelectHoldDownMode(holdDownMode: HoldDownMode) {
actionOptionsUid.value?.let { uid ->
config.setActionStopHoldingDownWhenTriggerPressedAgain(
uid,
holdDownMode == HoldDownMode.TRIGGER_PRESSED_AGAIN,
)
}
}

override fun onDelayBeforeNextActionChanged(delay: Int) {
actionOptionsUid.value?.let { uid -> config.setDelayBeforeNextAction(uid, delay) }
}
Expand All @@ -230,7 +239,10 @@ class ConfigActionsViewModel(
override fun onSelectRepeatMode(repeatMode: RepeatMode) {
actionOptionsUid.value?.let { uid ->
when (repeatMode) {
RepeatMode.TRIGGER_RELEASED -> config.setActionStopRepeatingWhenTriggerReleased(uid)
RepeatMode.TRIGGER_RELEASED -> config.setActionStopRepeatingWhenTriggerReleased(
uid,
)

RepeatMode.LIMIT_REACHED -> config.setActionStopRepeatingWhenLimitReached(uid)
RepeatMode.TRIGGER_PRESSED_AGAIN -> config.setActionStopRepeatingWhenTriggerPressedAgain(
uid,
Expand Down Expand Up @@ -416,7 +428,8 @@ class ConfigActionsViewModel(
return ConfigActionsState.Empty(shortcuts = shortcuts)
}

val actions = createListItems(keyMap, showDeviceDescriptors, errorSnapshot, shortcuts.size)
val actions =
createListItems(keyMap, showDeviceDescriptors, errorSnapshot, shortcuts.size)

return ConfigActionsState.Loaded(
actions = actions,
Expand Down Expand Up @@ -542,7 +555,9 @@ class ConfigActionsViewModel(
holdDownDuration = action.holdDownDuration ?: defaultHoldDownDuration,
defaultHoldDownDuration = defaultHoldDownDuration,

showHoldDownMode = keyMap.isStopHoldingDownActionWhenTriggerPressedAgainAllowed(action),
showHoldDownMode = keyMap.isStopHoldingDownActionWhenTriggerPressedAgainAllowed(
action,
),
holdDownMode = if (action.stopHoldDownWhenTriggerPressedAgain) {
HoldDownMode.TRIGGER_PRESSED_AGAIN
} else {
Expand Down
Loading