Skip to content

Commit fc3c605

Browse files
committed
feat: convert more dialog messages into trigger tips
1 parent 8c34f14 commit fc3c605

5 files changed

Lines changed: 125 additions & 86 deletions

File tree

base/src/main/java/io/github/sds100/keymapper/base/keymaps/DisplayKeyMapUseCase.kt

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,22 +111,9 @@ class DisplayKeyMapUseCaseImpl @Inject constructor(
111111
)
112112
}
113113

114-
override val showTriggerKeyboardIconExplanation: Flow<Boolean> =
115-
settingsRepository.get(Keys.neverShowTriggerKeyboardIconExplanation).map { neverShow ->
116-
if (neverShow == null) {
117-
true
118-
} else {
119-
!neverShow
120-
}
121-
}
122-
123114
override val showDeviceDescriptors: Flow<Boolean> =
124115
settingsRepository.get(Keys.showDeviceDescriptors).map { it == true }
125116

126-
override fun neverShowTriggerKeyboardIconExplanation() {
127-
settingsRepository.set(Keys.neverShowTriggerKeyboardIconExplanation, true)
128-
}
129-
130117
override fun neverShowDpadImeSetupError() {
131118
settingsRepository.set(Keys.neverShowDpadImeTriggerError, true)
132119
}
@@ -230,8 +217,6 @@ interface DisplayKeyMapUseCase :
230217
val triggerErrorSnapshot: Flow<TriggerErrorSnapshot>
231218
suspend fun isFloatingButtonsPurchased(): Boolean
232219
suspend fun fixTriggerError(error: TriggerError)
233-
val showTriggerKeyboardIconExplanation: Flow<Boolean>
234-
fun neverShowTriggerKeyboardIconExplanation()
235220
override val showDeviceDescriptors: Flow<Boolean>
236221

237222
fun neverShowDpadImeSetupError()

base/src/main/java/io/github/sds100/keymapper/base/onboarding/OnboardingTipDelegate.kt

Lines changed: 113 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package io.github.sds100.keymapper.base.onboarding
22

33
import dagger.hilt.android.scopes.ViewModelScoped
44
import io.github.sds100.keymapper.base.R
5+
import io.github.sds100.keymapper.base.keymaps.DisplayKeyMapUseCase
56
import io.github.sds100.keymapper.base.trigger.ConfigTriggerUseCase
67
import io.github.sds100.keymapper.base.trigger.KeyCodeTriggerKey
8+
import io.github.sds100.keymapper.base.trigger.KeyEventTriggerKey
79
import io.github.sds100.keymapper.base.trigger.Trigger
810
import io.github.sds100.keymapper.base.trigger.TriggerMode
911
import io.github.sds100.keymapper.base.utils.ui.ResourceProvider
@@ -26,6 +28,7 @@ class OnboardingTipDelegateImpl @Inject constructor(
2628
private val viewModelScope: CoroutineScope,
2729
private val preferenceRepository: PreferenceRepository,
2830
private val configTriggerUseCase: ConfigTriggerUseCase,
31+
private val displayKeyMap: DisplayKeyMapUseCase,
2932
resourceProvider: ResourceProvider
3033
) : OnboardingTipDelegate, PreferenceRepository by preferenceRepository,
3134
ResourceProvider by resourceProvider {
@@ -35,6 +38,9 @@ class OnboardingTipDelegateImpl @Inject constructor(
3538
private const val PARALLEL_TRIGGER_TIP_ID = "parallel_trigger_tip"
3639
private const val SEQUENCE_TRIGGER_TIP_ID = "sequence_trigger_tip"
3740
private const val TRIGGER_CONSTRAINTS_TIP_ID = "trigger_constraints_tip"
41+
const val CAPS_LOCK_TIP_ID = "caps_lock_tip"
42+
const val SCREEN_PINNING_TIP_ID = "screen_pinning_tip"
43+
const val IME_DETECTION_TIP_ID = "ime_detection_tip"
3844
}
3945

4046
override val triggerTip: MutableStateFlow<OnboardingTipModel?> = MutableStateFlow(null)
@@ -54,6 +60,21 @@ class OnboardingTipDelegateImpl @Inject constructor(
5460
false,
5561
)
5662

63+
private var shownCapsLockTip: Boolean by PrefDelegate(
64+
Keys.shownCapsLockTip,
65+
false,
66+
)
67+
68+
private var shownScreenPinningTip: Boolean by PrefDelegate(
69+
Keys.shownScreenPinningTip,
70+
false,
71+
)
72+
73+
private var shownImeDetectionTip: Boolean by PrefDelegate(
74+
Keys.shownTriggerKeyboardIconExplanation,
75+
false,
76+
)
77+
5778
init {
5879
viewModelScope.launch {
5980
configTriggerUseCase.keyMap
@@ -79,58 +100,119 @@ class OnboardingTipDelegateImpl @Inject constructor(
79100
TRIGGER_CONSTRAINTS_TIP_ID -> {
80101
shownTriggerConstraintsTip = true
81102
}
103+
104+
CAPS_LOCK_TIP_ID -> {
105+
shownCapsLockTip = true
106+
}
107+
108+
SCREEN_PINNING_TIP_ID -> {
109+
shownScreenPinningTip = true
110+
}
111+
112+
IME_DETECTION_TIP_ID -> {
113+
shownImeDetectionTip = true
114+
}
115+
82116
// POWER_BUTTON_EMERGENCY_TIP_ID doesn't need preference setting as it's non-dismissable
83117
}
84118

85119
triggerTip.value = null
86120
}
87121

88-
private fun onCollectTrigger(trigger: Trigger) {
122+
private suspend fun onCollectTrigger(trigger: Trigger) {
89123
val showPowerButtonEmergencyTip = trigger.keys.any {
90124
it is KeyCodeTriggerKey && KeyEventUtils.isPowerButtonKey(
91125
it.keyCode,
92126
it.scanCode ?: -1,
93127
)
94128
}
95129

96-
if (showPowerButtonEmergencyTip) {
97-
val tipModel = OnboardingTipModel(
98-
id = POWER_BUTTON_EMERGENCY_TIP_ID,
99-
title = getString(R.string.pro_mode_emergency_tip_title),
100-
message = getString(R.string.pro_mode_emergency_tip_text),
101-
isDismissable = false
102-
)
130+
val hasCapsLockKey =
131+
trigger.keys.any { it is KeyEventTriggerKey && it.keyCode == android.view.KeyEvent.KEYCODE_CAPS_LOCK }
132+
val hasBackKey =
133+
trigger.keys.any { it is KeyEventTriggerKey && it.keyCode == android.view.KeyEvent.KEYCODE_BACK }
134+
val hasImeKey = trigger.keys.any { it is KeyEventTriggerKey && it.requiresIme }
103135

104-
triggerTip.value = tipModel
136+
when {
137+
showPowerButtonEmergencyTip -> {
138+
val tipModel = OnboardingTipModel(
139+
id = POWER_BUTTON_EMERGENCY_TIP_ID,
140+
title = getString(R.string.pro_mode_emergency_tip_title),
141+
message = getString(R.string.pro_mode_emergency_tip_text),
142+
isDismissable = false
143+
)
144+
145+
triggerTip.value = tipModel
105146

106-
} else if (trigger.mode is TriggerMode.Parallel) {
107-
if (shownParallelTriggerOrderExplanation) {
108-
return
109147
}
110148

111-
val tipModel = OnboardingTipModel(
112-
id = PARALLEL_TRIGGER_TIP_ID,
113-
title = getString(R.string.tip_parallel_trigger_title),
114-
message = getString(R.string.dialog_message_parallel_trigger_order),
115-
isDismissable = true
116-
)
149+
trigger.mode is TriggerMode.Parallel && !shownParallelTriggerOrderExplanation -> {
150+
val tipModel = OnboardingTipModel(
151+
id = PARALLEL_TRIGGER_TIP_ID,
152+
title = getString(R.string.tip_parallel_trigger_title),
153+
message = getString(R.string.dialog_message_parallel_trigger_order),
154+
isDismissable = true
155+
)
117156

118-
triggerTip.value = tipModel
119-
} else if (trigger.mode is TriggerMode.Sequence) {
120-
if (shownSequenceTriggerExplanation) {
121-
return
157+
triggerTip.value = tipModel
122158
}
123159

124-
val tipModel = OnboardingTipModel(
125-
id = SEQUENCE_TRIGGER_TIP_ID,
126-
title = getString(R.string.tip_sequence_trigger_title),
127-
message = getString(R.string.dialog_message_sequence_trigger_explanation),
128-
isDismissable = true
129-
)
160+
trigger.mode is TriggerMode.Sequence && !shownSequenceTriggerExplanation -> {
161+
162+
val tipModel = OnboardingTipModel(
163+
id = SEQUENCE_TRIGGER_TIP_ID,
164+
title = getString(R.string.tip_sequence_trigger_title),
165+
message = getString(R.string.dialog_message_sequence_trigger_explanation),
166+
isDismissable = true
167+
)
168+
169+
triggerTip.value = tipModel
170+
}
171+
172+
trigger.keys.isNotEmpty() && !shownTriggerConstraintsTip -> {
173+
val tipModel = OnboardingTipModel(
174+
id = TRIGGER_CONSTRAINTS_TIP_ID,
175+
title = getString(R.string.trigger_constraints_tip_title),
176+
message = getString(R.string.trigger_constraints_tip_text),
177+
isDismissable = true
178+
)
179+
180+
triggerTip.value = tipModel
181+
}
182+
183+
hasCapsLockKey && !shownCapsLockTip -> {
184+
val tip = OnboardingTipModel(
185+
id = CAPS_LOCK_TIP_ID,
186+
title = getString(R.string.tip_caps_lock_title),
187+
message = getString(R.string.tip_caps_lock_text),
188+
isDismissable = true,
189+
)
190+
triggerTip.value = tip
191+
}
192+
193+
hasBackKey && !shownScreenPinningTip -> {
194+
val tip = OnboardingTipModel(
195+
id = SCREEN_PINNING_TIP_ID,
196+
title = getString(R.string.tip_screen_pinning_title),
197+
message = getString(R.string.tip_screen_pinning_text),
198+
isDismissable = true,
199+
)
200+
triggerTip.value = tip
201+
}
202+
203+
hasImeKey && !shownImeDetectionTip -> {
204+
val tip = OnboardingTipModel(
205+
id = IME_DETECTION_TIP_ID,
206+
title = getString(R.string.tip_ime_detection_title),
207+
message = getString(R.string.tip_ime_detection_text),
208+
isDismissable = true,
209+
)
210+
triggerTip.value = tip
211+
}
130212

131-
triggerTip.value = tipModel
132-
} else {
133-
triggerTip.value = null
213+
else -> {
214+
triggerTip.value = null
215+
}
134216
}
135217
}
136218
}

base/src/main/java/io/github/sds100/keymapper/base/trigger/BaseConfigTriggerViewModel.kt

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.github.sds100.keymapper.base.trigger
22

3-
import android.view.KeyEvent
43
import androidx.compose.runtime.getValue
54
import androidx.compose.runtime.mutableStateOf
65
import androidx.compose.runtime.setValue
@@ -19,13 +18,10 @@ import io.github.sds100.keymapper.base.shortcuts.CreateKeyMapShortcutUseCase
1918
import io.github.sds100.keymapper.base.system.accessibility.FingerprintGestureType
2019
import io.github.sds100.keymapper.base.utils.navigation.NavigationProvider
2120
import io.github.sds100.keymapper.base.utils.ui.CheckBoxListItem
22-
import io.github.sds100.keymapper.base.utils.ui.DialogModel
2321
import io.github.sds100.keymapper.base.utils.ui.DialogProvider
24-
import io.github.sds100.keymapper.base.utils.ui.DialogResponse
2522
import io.github.sds100.keymapper.base.utils.ui.LinkType
2623
import io.github.sds100.keymapper.base.utils.ui.ResourceProvider
2724
import io.github.sds100.keymapper.base.utils.ui.ViewModelHelper
28-
import io.github.sds100.keymapper.base.utils.ui.showDialog
2925
import io.github.sds100.keymapper.common.models.EvdevDeviceInfo
3026
import io.github.sds100.keymapper.common.utils.InputDeviceUtils
3127
import io.github.sds100.keymapper.common.utils.KMError
@@ -357,40 +353,6 @@ abstract class BaseConfigTriggerViewModel(
357353
triggerDevice,
358354
key.detectionSource != InputEventDetectionSource.ACCESSIBILITY_SERVICE,
359355
)
360-
361-
if (key.keyCode == KeyEvent.KEYCODE_CAPS_LOCK) {
362-
val dialog = DialogModel.Ok(
363-
message = getString(R.string.dialog_message_enable_physical_keyboard_caps_lock_a_keyboard_layout),
364-
)
365-
366-
showDialog("caps_lock_message", dialog)
367-
}
368-
369-
if (key.keyCode == KeyEvent.KEYCODE_BACK) {
370-
val dialog = DialogModel.Ok(
371-
message = getString(R.string.dialog_message_screen_pinning_warning),
372-
)
373-
374-
showDialog("screen_pinning_message", dialog)
375-
}
376-
377-
// Issue #491. Some key codes can only be detected through an input method. This will
378-
// be shown to the user by showing a keyboard icon next to the trigger key name so
379-
// explain this to the user.
380-
if (key.detectionSource == InputEventDetectionSource.INPUT_METHOD && displayKeyMap.showTriggerKeyboardIconExplanation.first()) {
381-
val dialog = DialogModel.Alert(
382-
title = getString(R.string.dialog_title_keyboard_icon_means_ime_detection),
383-
message = getString(R.string.dialog_message_keyboard_icon_means_ime_detection),
384-
negativeButtonText = getString(R.string.neg_dont_show_again),
385-
positiveButtonText = getString(R.string.pos_ok),
386-
)
387-
388-
val response = showDialog("keyboard_icon_explanation", dialog)
389-
390-
if (response == DialogResponse.NEGATIVE) {
391-
displayKeyMap.neverShowTriggerKeyboardIconExplanation()
392-
}
393-
}
394356
}
395357

396358
private suspend fun onRecordEvdevEvent(key: RecordedKey.EvdevEvent) {

base/src/main/res/values/strings.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,12 @@
13481348
<string name="floating_buttons_product_description">Floating buttons display over the apps you want. They work just like real buttons, and you can place, style, and map them however you like.</string>
13491349
<string name="floating_button_text_key_map_list_item">Floating button %s (%s)</string>
13501350
<string name="deleted_floating_button_text_key_map_list_item">Deleted floating button</string>
1351+
<string name="tip_caps_lock_title">Caps lock remapping</string>
1352+
<string name="tip_caps_lock_text">To remap Caps Lock, change your physical keyboard layout in settings to \'Caps Lock to camera\', then re-record this trigger.</string>
1353+
<string name="tip_screen_pinning_title">App pinning warning</string>
1354+
<string name="tip_screen_pinning_text">Using the back button as a trigger may conflict with app pinning, causing a black screen on unlock. A reboot will fix it.</string>
1355+
<string name="tip_ime_detection_title">Keyboard icon</string>
1356+
<string name="tip_ime_detection_text">The ⌨ symbol means you must use a Key Mapper keyboard for this trigger to work due to an Android restriction.</string>
13511357
<string name="trigger_constraints_tip_title">Limit to specific apps?</string>
13521358
<string name="trigger_constraints_tip_text">Add constraints in the Constraints tab.</string>
13531359
<string name="choose_floating_layout_title">Choose a layout</string>

data/src/main/java/io/github/sds100/keymapper/data/Keys.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ object Keys {
5454
booleanPreferencesKey("key_shown_sequence_trigger_explanation_dialog")
5555
val shownTriggerConstraintsTip =
5656
booleanPreferencesKey("key_shown_trigger_constraints_tip")
57+
val shownCapsLockTip =
58+
booleanPreferencesKey("key_shown_caps_lock_tip")
59+
val shownScreenPinningTip =
60+
booleanPreferencesKey("key_shown_screen_pinning_tip")
5761
val lastInstalledVersionCodeHomeScreen =
5862
intPreferencesKey("last_installed_version_home_screen")
5963
val lastInstalledVersionCodeBackground =
@@ -70,8 +74,8 @@ object Keys {
7074
val savedWifiSSIDs = stringSetPreferencesKey("key_saved_wifi_ssids")
7175

7276
val neverShowDndAccessError = booleanPreferencesKey("key_never_show_dnd_error")
73-
val neverShowTriggerKeyboardIconExplanation =
74-
booleanPreferencesKey("key_never_show_keyboard_icon_explanation")
77+
val shownTriggerKeyboardIconExplanation =
78+
booleanPreferencesKey("key_shown_keyboard_icon_explanation")
7579

7680
val neverShowDpadImeTriggerError =
7781
booleanPreferencesKey("key_never_show_dpad_ime_trigger_error")

0 commit comments

Comments
 (0)