Skip to content
Merged
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
24 changes: 0 additions & 24 deletions .github/workflows/build-mkdocs.yml

This file was deleted.

6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,8 @@ Gemfile.lock
app/play-service-account-key.json

app/.env
.venv/
.venv/
/.idea/appInsightsSettings.xml
/.idea/AndroidProjectSystem.xml
/.idea/runConfigurations.xml
/.idea/studiobot.xml
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

1 change: 0 additions & 1 deletion .idea/runConfigurations/app.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions 404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Redirecting to https://docs.keymapper.club/</title>
<meta content="0; URL=https://docs.keymapper.club/" http-equiv="refresh">
<link href="https://docs.keymapper.club/" rel="canonical">
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
## [3.0.0](https://github.com/sds100/KeyMapper/releases/tag/v3.0.0)

_See the changes from previous 3.0 Beta releases._

#### 10 April 2025

- #1635 do not crash if the URL for the HTTP action is malformed

## [3.0 Beta 5](https://github.com/sds100/KeyMapper/releases/tag/v3.0.0-beta.5)

_See the changes from previous 3.0 Beta releases as well._

#### 6 April 2025

- #1625 HTTP Request action.

###

## Bug fixes

- #1627 open camera app action does not work when device is locked
Expand Down
62 changes: 44 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
**UPDATE**: I miss working on this project and Key Mapper still has so much potential so I am back! 😊
>
> Well, working on this project was a fun ride 🎢! This project has taught me so much about Android, software development and how to collaborate with an online community. It has been my dream to lead a big FOSS project with people from all over the world so a **huge** thank you goes to everyone that spread the word and helped on GitHub along the way ☺.
>
> ~~Unfortunately, I do not have any more time to work on this project - I'm now studying Computer Science at university and I have landed software-dev side jobs, which has taken up any free-time I did have to code on the side.~~
>
> A special thank you goes to everyone in the [Team](https://docs.keymapper.club/#our-team) for their long-term
> commitment to the project and for being so engaged with the community 👏 🎉.
> The Discord server, website and app store listing will still be up! So don't worry, you can still map your keys to your heart's content. ❤
![GitHub release](https://img.shields.io/github/release/keymapperorg/KeyMapper.svg)
![fdroid release](https://img.shields.io/f-droid/v/io.github.sds100.keymapper.svg)

<p align="center">
<img width="200" height="auto" src="https://github.com/sds100/KeyMapper/blob/master/app/src/main/ic_launcher-web.png">
<br/>

Key Mapper is a free and open source Android app that can remap your buttons and fingerprint reader gestures. The aim of this project is to allow anyone to remap their buttons with (almost) infinite flexibility.
</b>
</p>

Expand All @@ -25,11 +17,47 @@ Key Mapper is a free and open source Android app that can remap your buttons and
<noscript><a href="https://buy.stripe.com/00g16L9YEabldDWdQQ"><img alt="Donate using Stripe" src="https://img.shields.io/badge/Donate-Stripe-blueviolet?style=for-the-badge&logo=stripe"></a></noscript>
</p>

![GitHub release](https://img.shields.io/github/release/keymapperorg/KeyMapper.svg)
![fdroid release](https://img.shields.io/f-droid/v/io.github.sds100.keymapper.svg)
## Unleash your keys!

Make custom macros on your keyboard or gamepad, make on-screen buttons in any app, and unlock new functionality from your volume buttons!

Key Mapper supports a huge variety of buttons and keys:

- ALL your phone buttons (volume AND side key)
- Game controllers (D-pad, ABXY, and most others)
- Keyboards
- Headsets and headphones
- Fingerprint sensor

Most devices are already supported, with new devices being added over time. Let us know if it's not working for you and we can prioritize your device.

Not currently supported:
- Mouse buttons
- Joysticks and triggers (LT,RT) on gamepads

Not enough keys? Design your own on-screen button layouts and remap those just like real keys!

## What shortcuts can I make?

🎉 Check out the [website](https://docs.keymapper.club) for more information and help! 🎉
With over 100 individual actions, the sky is the limit.

Build complex macros with screen taps and gestures, keyboard inputs, open apps, control media, and even send intents directly to other apps.


## How much control do I have?

TRIGGERS: You decide how to trigger a key map. Long press, double press, press as many times as you like! Combine keys on different devices, and even include your on-screen buttons.

ACTIONS: Design specific macros for what you want to do. Combine over 100 actions, and choose the delay between each one. Set repeating actions to automate and speed up slow tasks.

CONSTRAINTS: You choose when key maps should run and when they shouldn't. Only need it in one specific app? Or when media is playing? On your lockscreen? Constrain your key maps for maximum control.


## Links

Come say hi in our [Discord community!](http://keymapper.club)

Read the [documentation!](https://docs.keymapper.club/?utm_source=github)

## Translations

Expand All @@ -41,11 +69,9 @@ Key Mapper is a free and open source Android app that can remap your buttons and
[![sk proofreading](https://img.shields.io/badge/dynamic/json?color=green&label=sk&style=flat&logo=crowdin&query=%24.progress.11.data.approvalProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-13864667-360045-update.json)](https://crowdin.com/project/key-mapper)
[![zh-CN proofreading](https://img.shields.io/badge/dynamic/json?color=green&label=zh-CN&style=flat&logo=crowdin&query=%24.progress.15.data.approvalProgress&url=https%3A%2F%2Fbadges.awesome-crowdin.com%2Fstats-13864667-360045-update.json)](https://crowdin.com/project/key-mapper)


## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=keymapperorg/KeyMapper&type=Date)](https://star-history.com/#keymapperorg/KeyMapper&Date)

### How do I contribute?
[![Star History Chart](https://api.star-history.com/svg?repos=keymapperorg/KeyMapper&type=Date)](https://www.star-history.com/#keymapperorg/KeyMapper&Date)
## Contributing
There are many ways to help with this project. 😃
Check out the contributing guide in the [documentation](https://docs.keymapper.club).
Check out the contributing guide in the [documentation.](https://docs.keymapper.club/contributing/introduction/?utm_source=github)
1 change: 1 addition & 0 deletions app/src/main/assets/whats-new.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Key Mapper 3.0 is here! 🎉
🗂️ 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.

🛜 Send HTTP requests with a new action.

❤️ There are also tonnes of improvements to make your key mapping experience more enjoyable.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ class CreateActionDelegate(
httpRequestBottomSheetState = ActionData.HttpRequest(
description = "",
method = HttpMethod.GET,
url = "",
url = "http://",
body = "",
authorizationHeader = "",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import io.github.sds100.keymapper.system.network.HttpMethod
import io.github.sds100.keymapper.util.ui.compose.KeyMapperDropdownMenu
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -106,6 +107,7 @@ private fun HttpRequestBottomSheet(
val descriptionEmptyErrorString =
stringResource(R.string.action_http_request_description_empty_error)
val urlEmptyErrorString = stringResource(R.string.action_http_request_url_empty_error)
val malformedUrlErrorString = stringResource(R.string.action_http_request_malformed_url_error)

var descriptionError: String? by rememberSaveable { mutableStateOf(null) }
var urlError: String? by rememberSaveable { mutableStateOf(null) }
Expand Down Expand Up @@ -272,6 +274,10 @@ private fun HttpRequestBottomSheet(
urlError = urlEmptyErrorString
}

if (state.url.toHttpUrlOrNull() == null) {
urlError = malformedUrlErrorString
}

if (descriptionError == null && urlError == null) {
onDoneClick()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ fun KeyMapListAppBar(
actions = {
AppBarActions(
onHelpClick,
onSortClick,
onSettingsClick,
onAboutClick,
onExportClick,
Expand Down Expand Up @@ -253,11 +254,13 @@ fun KeyMapListAppBar(
AnimatedVisibility(!state.isEditingGroupName) {
AppBarActions(
onHelpClick,
onSortClick,
onSettingsClick,
onAboutClick,
onExportClick,
onImportClick,
showDeleteGroup = true,
showSort = true,
onDeleteGroupClick = {
showDeleteGroupDialog = true
},
Expand Down Expand Up @@ -529,11 +532,13 @@ private fun SelectingAppBar(
@Composable
private fun AppBarActions(
onHelpClick: () -> Unit,
onSortClick: () -> Unit,
onSettingsClick: () -> Unit,
onAboutClick: () -> Unit,
onExportClick: () -> Unit,
onImportClick: () -> Unit,
showDeleteGroup: Boolean = false,
showSort: Boolean = false,
onDeleteGroupClick: () -> Unit = {},
) {
var expandedDropdown by rememberSaveable { mutableStateOf(false) }
Expand All @@ -555,6 +560,10 @@ private fun AppBarActions(

AppBarDropdownMenu(
expanded = expandedDropdown,
onSortClick = {
expandedDropdown = false
onSortClick()
},
onSettingsClick = {
expandedDropdown = false
onSettingsClick()
Expand All @@ -573,6 +582,7 @@ private fun AppBarActions(
},
onDismissRequest = { expandedDropdown = false },
showDeleteGroup = showDeleteGroup,
showSort = showSort,
onDeleteGroupClick = {
expandedDropdown = false
onDeleteGroupClick()
Expand Down Expand Up @@ -810,12 +820,14 @@ private fun selectedTextTransition(
@Composable
private fun AppBarDropdownMenu(
expanded: Boolean,
onSortClick: () -> Unit = {},
onSettingsClick: () -> Unit = {},
onAboutClick: () -> Unit = {},
onExportClick: () -> Unit = {},
onImportClick: () -> Unit = {},
onDismissRequest: () -> Unit = {},
showDeleteGroup: Boolean = false,
showSort: Boolean = false,
onDeleteGroupClick: () -> Unit = {},
) {
DropdownMenu(
Expand All @@ -830,6 +842,14 @@ private fun AppBarDropdownMenu(
)
}

if (showSort) {
DropdownMenuItem(
leadingIcon = { Icon(Icons.AutoMirrored.Rounded.Sort, contentDescription = null) },
text = { Text(stringResource(R.string.home_app_bar_sort)) },
onClick = onSortClick,
)
}

DropdownMenuItem(
leadingIcon = { Icon(Icons.Rounded.Settings, contentDescription = null) },
text = { Text(stringResource(R.string.home_menu_settings)) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ class AndroidNetworkAdapter(
} catch (e: IOException) {
Timber.e(e)
return Error.UnknownIOError
} catch (e: IllegalArgumentException) {
return Error.MalformedUrl
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ fun Error.getFullMessage(resourceProvider: ResourceProvider): String = when (thi
Error.PurchasingNotImplemented -> resourceProvider.getString(R.string.purchasing_error_not_implemented)
Error.DpadTriggerImeNotSelected -> resourceProvider.getString(R.string.trigger_error_dpad_ime_not_selected)
Error.InvalidBackup -> resourceProvider.getString(R.string.error_invalid_backup)
Error.MalformedUrl -> resourceProvider.getString(R.string.error_malformed_url)
}

val Error.isFixable: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ sealed class Error : Result<Nothing>() {
* DPAD triggers require a Key Mapper keyboard to be selected.
*/
data object DpadTriggerImeNotSelected : Error()
data object MalformedUrl : Error()
}

inline fun <T> Result<T>.onSuccess(f: (T) -> Unit): Result<T> {
Expand Down
Loading