Skip to content

Commit ca8951d

Browse files
committed
#1871 feat: complete modify system setting action
1 parent 302095d commit ca8951d

File tree

9 files changed

+364
-31
lines changed

9 files changed

+364
-31
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## [4.0.0 Beta 3](https://github.com/sds100/KeyMapper/releases/tag/v4.0.0-beta.03)
2+
3+
#### TO BE RELEASED
4+
5+
## Added
6+
- #1871 action to modify any system settings
7+
18
## [4.0.0 Beta 2](https://github.com/sds100/KeyMapper/releases/tag/v4.0.0-beta.02)
29

310
#### 08 November 2025

base/src/main/assets/whats-new.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ You can now remap ALL buttons when the screen is off (including the power button
66
• Send SMS messages
77
• Force stop current app or clear from recents
88
• Mute/unmute microphone
9+
• Modify any system setting
910

1011
🆕 New Features
1112
• Redesigned Settings screen

base/src/main/java/io/github/sds100/keymapper/base/actions/ActionUiHelper.kt

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -653,17 +653,9 @@ class ActionUiHelper(
653653
ActionData.Microphone.Unmute -> getString(R.string.action_unmute_microphone)
654654

655655
is ActionData.ModifySetting -> {
656-
val typeString = when (action.settingType) {
657-
io.github.sds100.keymapper.system.settings.SettingType.SYSTEM ->
658-
getString(R.string.modify_setting_type_system)
659-
io.github.sds100.keymapper.system.settings.SettingType.SECURE ->
660-
getString(R.string.modify_setting_type_secure)
661-
io.github.sds100.keymapper.system.settings.SettingType.GLOBAL ->
662-
getString(R.string.modify_setting_type_global)
663-
}
664656
getString(
665657
R.string.modify_setting_description,
666-
arrayOf(action.settingKey, action.value, typeString),
658+
arrayOf(action.settingKey, action.value),
667659
)
668660
}
669661
}

base/src/main/java/io/github/sds100/keymapper/base/actions/CreateActionDelegate.kt

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.text.InputType
44
import androidx.compose.runtime.getValue
55
import androidx.compose.runtime.mutableStateOf
66
import androidx.compose.runtime.setValue
7+
import androidx.compose.runtime.snapshotFlow
78
import io.github.sds100.keymapper.base.R
89
import io.github.sds100.keymapper.base.actions.pinchscreen.PinchPickCoordinateResult
910
import io.github.sds100.keymapper.base.actions.swipescreen.SwipePickCoordinateResult
@@ -29,13 +30,17 @@ import io.github.sds100.keymapper.system.volume.DndMode
2930
import io.github.sds100.keymapper.system.volume.RingerMode
3031
import io.github.sds100.keymapper.system.volume.VolumeStream
3132
import kotlinx.coroutines.CoroutineScope
33+
import kotlinx.coroutines.ExperimentalCoroutinesApi
3234
import kotlinx.coroutines.flow.MutableStateFlow
3335
import kotlinx.coroutines.flow.collectLatest
36+
import kotlinx.coroutines.flow.filterNotNull
3437
import kotlinx.coroutines.flow.first
38+
import kotlinx.coroutines.flow.flatMapLatest
3539
import kotlinx.coroutines.flow.update
3640
import kotlinx.coroutines.launch
3741
import kotlinx.serialization.json.Json
3842

43+
@OptIn(ExperimentalCoroutinesApi::class)
3944
class CreateActionDelegate(
4045
private val coroutineScope: CoroutineScope,
4146
private val useCase: CreateActionUseCase,
@@ -67,6 +72,22 @@ class CreateActionDelegate(
6772
}
6873
}
6974
}
75+
76+
coroutineScope.launch {
77+
snapshotFlow { modifySettingActionBottomSheetState?.settingType }
78+
.filterNotNull()
79+
.flatMapLatest { settingType ->
80+
val permission = useCase.getRequiredPermissionForSettingType(settingType)
81+
useCase.isPermissionGrantedFlow(permission)
82+
}
83+
.collectLatest { isGranted ->
84+
modifySettingActionBottomSheetState =
85+
modifySettingActionBottomSheetState?.copy(
86+
isPermissionGranted = isGranted,
87+
testResult = null,
88+
)
89+
}
90+
}
7091
}
7192

7293
fun onDoneConfigEnableFlashlightClick() {
@@ -214,12 +235,18 @@ class CreateActionDelegate(
214235

215236
fun onSelectSettingType(settingType: SettingType) {
216237
modifySettingActionBottomSheetState =
217-
modifySettingActionBottomSheetState?.copy(settingType = settingType)
238+
modifySettingActionBottomSheetState?.copy(
239+
settingType = settingType,
240+
testResult = null,
241+
)
218242
}
219243

220244
fun onSettingKeyChange(key: String) {
221245
modifySettingActionBottomSheetState =
222-
modifySettingActionBottomSheetState?.copy(settingKey = key)
246+
modifySettingActionBottomSheetState?.copy(
247+
settingKey = key,
248+
testResult = null,
249+
)
223250
}
224251

225252
fun onChooseExistingSettingClick() {
@@ -233,6 +260,7 @@ class CreateActionDelegate(
233260
settingType = setting.settingType,
234261
settingKey = setting.key,
235262
value = setting.currentValue ?: "",
263+
testResult = null,
236264
)
237265
}
238266
}
@@ -242,6 +270,22 @@ class CreateActionDelegate(
242270
modifySettingActionBottomSheetState?.copy(value = value)
243271
}
244272

273+
fun onTestModifySettingClick() {
274+
val state = modifySettingActionBottomSheetState ?: return
275+
276+
coroutineScope.launch {
277+
val result = useCase.setSettingValue(state.settingType, state.settingKey, state.value)
278+
modifySettingActionBottomSheetState =
279+
modifySettingActionBottomSheetState?.copy(testResult = result)
280+
}
281+
}
282+
283+
fun onRequestModifySettingPermission() {
284+
val state = modifySettingActionBottomSheetState ?: return
285+
val permission = useCase.getRequiredPermissionForSettingType(state.settingType)
286+
useCase.requestPermission(permission)
287+
}
288+
245289
suspend fun editAction(oldData: ActionData) {
246290
if (!oldData.isEditable()) {
247291
throw IllegalArgumentException("This action ${oldData.javaClass.name} can't be edited!")

base/src/main/java/io/github/sds100/keymapper/base/actions/CreateActionUseCase.kt

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ import io.github.sds100.keymapper.system.permissions.Permission
1111
import io.github.sds100.keymapper.system.permissions.PermissionAdapter
1212
import io.github.sds100.keymapper.system.permissions.SystemFeatureAdapter
1313
import io.github.sds100.keymapper.system.phone.PhoneAdapter
14-
import javax.inject.Inject
14+
import io.github.sds100.keymapper.system.settings.SettingType
15+
import io.github.sds100.keymapper.system.settings.SettingsAdapter
1516
import kotlinx.coroutines.flow.Flow
1617
import kotlinx.coroutines.flow.first
1718
import kotlinx.coroutines.flow.merge
19+
import javax.inject.Inject
1820

1921
class CreateActionUseCaseImpl @Inject constructor(
2022
private val inputMethodAdapter: InputMethodAdapter,
2123
private val systemFeatureAdapter: SystemFeatureAdapter,
2224
private val cameraAdapter: CameraAdapter,
2325
private val permissionAdapter: PermissionAdapter,
2426
private val phoneAdapter: PhoneAdapter,
27+
private val settingsAdapter: SettingsAdapter,
2528
) : CreateActionUseCase,
2629
IsActionSupportedUseCase by IsActionSupportedUseCaseImpl(
2730
systemFeatureAdapter,
@@ -69,6 +72,25 @@ class CreateActionUseCaseImpl @Inject constructor(
6972

7073
return phoneAdapter.sendSms(number, message)
7174
}
75+
76+
override fun setSettingValue(
77+
settingType: SettingType,
78+
key: String,
79+
value: String,
80+
): KMResult<Unit> {
81+
return settingsAdapter.setValue(settingType, key, value)
82+
}
83+
84+
override fun getRequiredPermissionForSettingType(settingType: SettingType): Permission {
85+
return when (settingType) {
86+
SettingType.SYSTEM -> Permission.WRITE_SETTINGS
87+
SettingType.SECURE, SettingType.GLOBAL -> Permission.WRITE_SECURE_SETTINGS
88+
}
89+
}
90+
91+
override fun isPermissionGrantedFlow(permission: Permission): Flow<Boolean> {
92+
return permissionAdapter.isGrantedFlow(permission)
93+
}
7294
}
7395

7496
interface CreateActionUseCase : IsActionSupportedUseCase {
@@ -83,4 +105,7 @@ interface CreateActionUseCase : IsActionSupportedUseCase {
83105

84106
fun requestPermission(permission: Permission)
85107
suspend fun testSms(number: String, message: String): KMResult<Unit>
108+
fun setSettingValue(settingType: SettingType, key: String, value: String): KMResult<Unit>
109+
fun getRequiredPermissionForSettingType(settingType: SettingType): Permission
110+
fun isPermissionGrantedFlow(permission: Permission): Flow<Boolean>
86111
}

0 commit comments

Comments
 (0)