Skip to content

Commit

Permalink
#378 option to repeat until swiped again
Browse files Browse the repository at this point in the history
  • Loading branch information
sds100 committed Dec 14, 2020
1 parent d9d8b10 commit 4139d2c
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,11 @@ data class Action(

val uid by it.json.byNullableString(NAME_UID)

Action(type, data, extraList.toMutableList(), flags, uid ?: UUID.randomUUID().toString())
Action(type, data, extraList.toMutableList(), flags, uid
?: UUID.randomUUID().toString())
}
}

constructor(type: ActionType, data: String, extra: Extra) : this(type, data, mutableListOf(extra))
constructor(type: ActionType, data: String, extra: Extra
) : this(type, data, mutableListOf(extra))
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ class FingerprintActionOptions(
private val showVolumeUi: BoolOption,
private val showPerformingActionToast: BoolOption,
private val delayBeforeNextAction: IntOption,
private val multiplier: IntOption
private val multiplier: IntOption,
private val repeatUntilSwipedAgain: BoolOption,
private val repeatRate: IntOption

) : BaseOptions<Action> {

Expand All @@ -25,6 +27,8 @@ class FingerprintActionOptions(
const val ID_SHOW_PERFORMING_ACTION_TOAST = "show_performing_action_toast"
const val ID_MULTIPLIER = "multiplier"
const val ID_DELAY_BEFORE_NEXT_ACTION = "delay_before_next_action"
const val ID_REPEAT_UNTIL_SWIPED_AGAIN = "repeat_until_swiped_again"
const val ID_REPEAT_RATE = "repeat_rate"
}

constructor(action: Action,
Expand Down Expand Up @@ -53,21 +57,36 @@ class FingerprintActionOptions(
id = ID_DELAY_BEFORE_NEXT_ACTION,
value = action.delayBeforeNextAction ?: IntOption.DEFAULT,
isAllowed = actionCount > 0
),

repeatUntilSwipedAgain = BoolOption(
id = ID_REPEAT_UNTIL_SWIPED_AGAIN,
value = action.repeat,
isAllowed = actionCount > 0
),

repeatRate = IntOption(
id = ID_REPEAT_RATE,
value = action.repeatRate ?: IntOption.DEFAULT,
isAllowed = action.repeat
)
)

override val intOptions = listOf(
delayBeforeNextAction,
multiplier
multiplier,
repeatRate
)

override val boolOptions = listOf(
showPerformingActionToast,
showVolumeUi
showVolumeUi,
repeatUntilSwipedAgain
)

override fun setValue(id: String, value: Int): BaseOptions<Action> {
when (id) {
ID_REPEAT_RATE -> repeatRate.value = value
ID_MULTIPLIER -> multiplier.value = value
ID_DELAY_BEFORE_NEXT_ACTION -> delayBeforeNextAction.value = value
}
Expand All @@ -77,6 +96,10 @@ class FingerprintActionOptions(

override fun setValue(id: String, value: Boolean): BaseOptions<Action> {
when (id) {
ID_REPEAT_UNTIL_SWIPED_AGAIN -> {
repeatUntilSwipedAgain.value = value
repeatRate.isAllowed = value
}

ID_SHOW_VOLUME_UI -> showVolumeUi.value = value
ID_SHOW_PERFORMING_ACTION_TOAST -> showPerformingActionToast.value = value
Expand All @@ -90,10 +113,12 @@ class FingerprintActionOptions(
.saveBoolOption(showVolumeUi, Action.ACTION_FLAG_SHOW_VOLUME_UI)
.saveBoolOption(showPerformingActionToast,
Action.ACTION_FLAG_SHOW_PERFORMING_ACTION_TOAST)
.saveBoolOption(repeatUntilSwipedAgain, Action.ACTION_FLAG_REPEAT)

val newExtras = old.extras
.saveIntOption(multiplier, Action.EXTRA_MULTIPLIER)
.saveIntOption(delayBeforeNextAction, Action.EXTRA_DELAY_BEFORE_NEXT_ACTION)
.saveIntOption(repeatRate, Action.EXTRA_REPEAT_RATE)

newExtras.removeAll {
it.id in arrayOf(Action.EXTRA_CUSTOM_STOP_REPEAT_BEHAVIOUR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ class FingerprintActionOptionsViewModel : BaseOptionsDialogViewModel<Fingerprint
)
)
}

FingerprintActionOptions.ID_REPEAT_RATE -> {
SliderListItemModel(
id = option.id,
label = R.string.extra_label_repeat_rate,
sliderModel = SliderModel(
value = option.value.nullIfDefault,
isDefaultStepEnabled = true,
min = R.integer.repeat_rate_min,
maxSlider = R.integer.repeat_rate_max,
stepSize = R.integer.repeat_rate_step_size
)
)
}
else -> throw Exception(
"Don't know how to create a SliderListItemModel for this option $option.id")
}
Expand All @@ -71,6 +85,14 @@ class FingerprintActionOptionsViewModel : BaseOptionsDialogViewModel<Fingerprint
)
}

FingerprintActionOptions.ID_REPEAT_UNTIL_SWIPED_AGAIN -> {
CheckBoxListItemModel(
id = option.id,
label = R.string.flag_repeat_until_swiped_again,
isChecked = option.value
)
}

else -> throw Exception(
"Don't know how to create a SliderListItemModel for this option $option.id")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class MyAccessibilityService : AccessibilityService(),
private lateinit var mConstraintDelegate: ConstraintDelegate

@RequiresApi(VERSION_CODES.O)
private var mFingerprintMapManager: FingerprintMapManager? = null
private var mFingerprintGestureMapController: FingerprintGestureMapController? = null

override val currentTime: Long
get() = SystemClock.elapsedRealtime()
Expand Down Expand Up @@ -362,7 +362,7 @@ class MyAccessibilityService : AccessibilityService(),

mFingerprintMapRepository = (application as MyApplication).fingerprintMapRepository

mFingerprintMapManager = FingerprintMapManager(
mFingerprintGestureMapController = FingerprintGestureMapController(
lifecycleScope,
iConstraintDelegate = mConstraintDelegate,
iActionError = this
Expand All @@ -374,7 +374,7 @@ class MyAccessibilityService : AccessibilityService(),
override fun onGestureDetected(gesture: Int) {
super.onGestureDetected(gesture)

mFingerprintMapManager?.onGesture(gesture)
mFingerprintGestureMapController?.onGesture(gesture)
}
}

Expand Down Expand Up @@ -405,7 +405,7 @@ class MyAccessibilityService : AccessibilityService(),
}

if (VERSION.SDK_INT >= VERSION_CODES.O) {
mFingerprintMapManager?.let { manager ->
mFingerprintGestureMapController?.let { manager ->
addSource(manager.vibrate) {
value = it
}
Expand Down Expand Up @@ -433,7 +433,7 @@ class MyAccessibilityService : AccessibilityService(),
}

if (VERSION.SDK_INT >= VERSION_CODES.O) {
mFingerprintMapManager?.let { manager ->
mFingerprintGestureMapController?.let { manager ->
addSource(manager.performAction) {
value = it
}
Expand Down Expand Up @@ -465,6 +465,8 @@ class MyAccessibilityService : AccessibilityService(),
if (VERSION.SDK_INT >= VERSION_CODES.O) {
fingerprintGestureController
.unregisterFingerprintGestureCallback(mFingerprintGestureCallback)

mFingerprintGestureMapController?.stopJobs()
}

super.onDestroy()
Expand Down Expand Up @@ -608,7 +610,7 @@ class MyAccessibilityService : AccessibilityService(),
private fun observeFingerprintMaps(repository: FingerprintMapRepository) {
repository.fingerprintGestureMapsLiveData.observe(this, Observer { maps ->

mFingerprintMapManager?.fingerprintMaps = maps
mFingerprintGestureMapController?.fingerprintMaps = maps

if (maps.any { it.value.isEnabled && it.value.actionList.isNotEmpty() }
&& !AppPreferences.keymapsPaused) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,28 @@ import io.github.sds100.keymapper.data.model.getData
import io.github.sds100.keymapper.util.*
import io.github.sds100.keymapper.util.result.isFailure
import io.github.sds100.keymapper.util.result.valueOrNull
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.*
import splitties.bitflags.hasFlag

/**
* Created by sds100 on 11/12/20.
*/
@RequiresApi(Build.VERSION_CODES.O)
class FingerprintMapManager(
class FingerprintGestureMapController(
private val mCoroutineScope: CoroutineScope,
iConstraintDelegate: IConstraintDelegate,
iActionError: IActionError
) : IActionError by iActionError, IConstraintDelegate by iConstraintDelegate {

private val mRepeatJobs = mutableMapOf<String, List<RepeatJob>>()
private val mPerformActionJobs = mutableMapOf<String, Job>()

var fingerprintMaps: Map<String, FingerprintMap> = emptyMap()
set(value) {
stopJobs()

field = value
}

val performAction = LiveEvent<PerformAction>()
val vibrate: LiveEvent<Vibrate> = LiveEvent()
Expand All @@ -40,18 +46,40 @@ class FingerprintMapManager(
if (actionList.isEmpty()) return
if (!constraintList.toTypedArray().constraintsSatisfied(constraintMode)) return

mCoroutineScope.launch {
mRepeatJobs[keyMapperId]?.forEach { it.cancel() }

mPerformActionJobs[keyMapperId]?.cancel()

mPerformActionJobs[keyMapperId] = mCoroutineScope.launch {
val repeatJobs = mutableListOf<RepeatJob>()

actionList.forEach {
if (canActionBePerformed(it).isFailure) return@forEach

performAction(
action = it,
it.showPerformingActionToast,
it.multiplier ?: 1
)
if (it.repeat) {
var alreadyRepeating = false

for (job in mRepeatJobs[keyMapperId] ?: emptyList()) {
if (job.actionUuid == it.uid) {
alreadyRepeating = true
job.cancel()
break
}
}

if (!alreadyRepeating) {
val job = RepeatJob(it.uid) { repeatAction(it) }
repeatJobs.add(job)
job.start()
}
} else {
performAction(it)
}

delay(it.delayBeforeNextAction?.toLong() ?: 0)
}

mRepeatJobs[keyMapperId] = repeatJobs
}

if (flags.hasFlag(FingerprintMap.FLAG_VIBRATE)) {
Expand All @@ -66,17 +94,41 @@ class FingerprintMapManager(
@MainThread
private fun performAction(
action: Action,
showPerformingActionToast: Boolean,
multiplier: Int,
keyEventAction: KeyEventAction = KeyEventAction.DOWN_UP
) {
repeat(multiplier) {
repeat(action.multiplier ?: 1) {
performAction.value = PerformAction(
action,
showPerformingActionToast,
action.showPerformingActionToast,
0,
keyEventAction
)
}
}

private fun repeatAction(action: Action) = mCoroutineScope.async(start = CoroutineStart.LAZY) {
val repeatRate = action.repeatRate ?: AppPreferences.repeatRate

while (true) {
performAction(action)

delay(repeatRate.toLong())
}
}

fun stopJobs() {
mRepeatJobs.values.forEach { jobs ->
jobs.forEach { it.cancel() }
}

mRepeatJobs.clear()

mPerformActionJobs.values.forEach {
it.cancel()
}

mPerformActionJobs.clear()
}

private class RepeatJob(val actionUuid: String, launch: () -> Job) : Job by launch.invoke()
}
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@
<string name="flag_repeat_actions">Repeat</string>
<string name="flag_hold_down">Hold down</string>
<string name="flag_dont_override_default_action">Do Not Override Default Action</string>
<string name="flag_repeat_until_swiped_again">Repeat Until Swiped Again</string>
<!--flags-->

<!-- Showcase -->
Expand Down

0 comments on commit 4139d2c

Please sign in to comment.