Skip to content

Commit

Permalink
feat: 规则新增 matchDelay+matchTime+actionMaximum 参数
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Oct 25, 2023
1 parent 3439e95 commit 0ef8cd3
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 202 deletions.
26 changes: 19 additions & 7 deletions app/src/main/java/li/songe/gkd/data/Rule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ data class Rule(
* 任意一个元素是上次点击过的
*/
val preRules: Set<Rule> = emptySet(),
val cd: Long = defaultMiniCd,
val delay: Long = 0,
val actionCd: Long = defaultMiniCd,
val actionDelay: Long = 0,
val matchLauncher: Boolean = false,
val quickFind: Boolean = false,

val matchDelay: Long?,
val matchTime: Long?,
val actionMaximum: Int?,

val appId: String,
val activityIds: Set<String> = emptySet(),
val excludeActivityIds: Set<String> = emptySet(),
Expand All @@ -41,22 +45,30 @@ data class Rule(
val app: SubscriptionRaw.AppRaw,
val subsItem: SubsItem,
) {
var delayTriggerTime = 0L
var actionDelayTriggerTime = 0L
fun triggerDelay() {
// 触发延迟, 一段时间内此规则不可利用
delayTriggerTime = System.currentTimeMillis()
actionDelayTriggerTime = System.currentTimeMillis()
}

private var triggerTime = 0L
fun trigger() {
triggerTime = System.currentTimeMillis()
// 重置延迟点
delayTriggerTime = 0L
actionDelayTriggerTime = 0L
actionCount++
lastTriggerRuleFlow.value = this
}

val active: Boolean
get() = triggerTime + cd < System.currentTimeMillis()
val notInCd: Boolean
get() = triggerTime + actionCd < System.currentTimeMillis()

var actionCount = 0

var activityIdChangeTime = 0L

val matchAllTime = (matchTime ?: 0) + (matchDelay ?: 0)


fun query(nodeInfo: AccessibilityNodeInfo?): AccessibilityNodeInfo? {
if (nodeInfo == null) return null
Expand Down
135 changes: 39 additions & 96 deletions app/src/main/java/li/songe/gkd/data/SubscriptionRaw.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package li.songe.gkd.data

import android.os.Parcelable
import blue.endless.jankson.Jankson
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.*
import li.songe.gkd.util.Singleton
import li.songe.selector.Selector


@Parcelize
@Serializable
data class SubscriptionRaw(
val id: Long,
Expand All @@ -21,98 +18,53 @@ data class SubscriptionRaw(
val updateUrl: String? = null,
val supportUri: String? = null,
val apps: List<AppRaw> = emptyList(),
) : Parcelable {

@Parcelize
@Serializable
data class NumberFilter(
val enum: List<Int>? = null,
val minimum: Int? = null,
val maximum: Int? = null,
) : Parcelable

@Parcelize
@Serializable
data class StringFilter(
val enum: List<String>? = null,
val minLength: Int? = null,
val maxLength: Int? = null,
val pattern: String? = null,
) : Parcelable {

@IgnoredOnParcel
val patternRegex by lazy {
if (pattern != null) try {
Regex(pattern)
} catch (e: Exception) {
null
} else null
}
}

@Parcelize
@Serializable
data class AppFilter(
val name: StringFilter? = null,
val versionName: StringFilter? = null,
val versionCode: NumberFilter? = null,
) : Parcelable

@Parcelize
@Serializable
data class DeviceFilter(
val device: StringFilter? = null,
val model: StringFilter? = null,
val manufacturer: StringFilter? = null,
val brand: StringFilter? = null,
val sdkInt: NumberFilter? = null,
val release: StringFilter? = null,
) : Parcelable
) {

interface CommonProps {
val activityIds: List<String>?
val excludeActivityIds: List<String>?
val cd: Long?
val delay: Long?
val actionCd: Long?
val actionDelay: Long?
val matchLauncher: Boolean?
val quickFind: Boolean?
val appFilter: AppFilter?
val deviceFilter: DeviceFilter?
val matchDelay: Long?
val matchTime: Long?
val actionMaximum: Int?
}

@Parcelize
@Serializable
data class AppRaw(
val id: String,
val name: String? = null,
override val cd: Long? = null,
override val delay: Long? = null,
override val actionCd: Long? = null,
override val actionDelay: Long? = null,
override val matchLauncher: Boolean? = null,
override val quickFind: Boolean? = null,
override val actionMaximum: Int?,
override val matchDelay: Long?,
override val matchTime: Long?,
override val activityIds: List<String>? = null,
override val excludeActivityIds: List<String>? = null,
val groups: List<GroupRaw> = emptyList(),
override val appFilter: AppFilter? = null,
override val deviceFilter: DeviceFilter? = null,
) : Parcelable, CommonProps
) : CommonProps

@Parcelize
@Serializable
data class GroupRaw(
val name: String,
val desc: String? = null,
val enable: Boolean? = null,
val key: Int,
override val cd: Long? = null,
override val delay: Long? = null,
override val actionCd: Long? = null,
override val actionDelay: Long? = null,
override val matchLauncher: Boolean? = null,
override val quickFind: Boolean? = null,
override val actionMaximum: Int?,
override val matchDelay: Long?,
override val matchTime: Long?,
override val activityIds: List<String>? = null,
override val excludeActivityIds: List<String>? = null,
val rules: List<RuleRaw> = emptyList(),
override val appFilter: AppFilter? = null,
override val deviceFilter: DeviceFilter? = null,
) : Parcelable, CommonProps {
) : CommonProps {

@IgnoredOnParcel
val valid by lazy {
Expand All @@ -126,24 +78,24 @@ data class SubscriptionRaw(
}
}

@Parcelize
@Serializable
data class RuleRaw(
val name: String? = null,
val key: Int? = null,
val preKeys: List<Int> = emptyList(),
val action: String? = null,
override val cd: Long? = null,
override val delay: Long? = null,
override val actionCd: Long? = null,
override val actionDelay: Long? = null,
override val matchLauncher: Boolean? = null,
override val quickFind: Boolean? = null,
override val actionMaximum: Int?,
override val matchDelay: Long?,
override val matchTime: Long?,
override val activityIds: List<String>? = null,
override val excludeActivityIds: List<String>? = null,
val matches: List<String> = emptyList(),
val excludeMatches: List<String> = emptyList(),
override val appFilter: AppFilter? = null,
override val deviceFilter: DeviceFilter? = null,
) : Parcelable, CommonProps
) : CommonProps

companion object {

Expand Down Expand Up @@ -233,8 +185,8 @@ data class SubscriptionRaw(
return RuleRaw(
activityIds = getStringIArray(rulesJson, "activityIds"),
excludeActivityIds = getStringIArray(rulesJson, "excludeActivityIds"),
cd = getLong(rulesJson, "cd"),
delay = getLong(rulesJson, "delay"),
actionCd = getLong(rulesJson, "actionCd") ?: getLong(rulesJson, "cd"),
actionDelay = getLong(rulesJson, "actionDelay") ?: getLong(rulesJson, "delay"),
matches = (getStringIArray(
rulesJson, "matches"
) ?: emptyList()),
Expand All @@ -244,15 +196,12 @@ data class SubscriptionRaw(
key = getInt(rulesJson, "key"),
name = getString(rulesJson, "name"),
preKeys = getIntIArray(rulesJson, "preKeys") ?: emptyList(),
deviceFilter = rulesJson["deviceFilter"]?.let {
Singleton.json.decodeFromJsonElement(it)
},
appFilter = rulesJson["appFilter"]?.let {
Singleton.json.decodeFromJsonElement(it)
},
action = getString(rulesJson, "action"),
matchLauncher = getBoolean(rulesJson, "matchLauncher"),
quickFind = getBoolean(rulesJson, "quickFind"),
actionMaximum = getInt(rulesJson, "actionMaximum"),
matchDelay = getLong(rulesJson, "matchDelay"),
matchTime = getLong(rulesJson, "matchTime")
)
}

Expand All @@ -266,8 +215,8 @@ data class SubscriptionRaw(
return GroupRaw(
activityIds = getStringIArray(groupsJson, "activityIds"),
excludeActivityIds = getStringIArray(groupsJson, "excludeActivityIds"),
cd = getLong(groupsJson, "cd"),
delay = getLong(groupsJson, "delay"),
actionCd = getLong(groupsJson, "actionCd") ?: getLong(groupsJson, "cd"),
actionDelay = getLong(groupsJson, "actionDelay") ?: getLong(groupsJson, "delay"),
name = getString(groupsJson, "name") ?: error("miss group name"),
desc = getString(groupsJson, "desc"),
enable = getBoolean(groupsJson, "enable"),
Expand All @@ -279,23 +228,20 @@ data class SubscriptionRaw(
}.map {
jsonToRuleRaw(it)
},
deviceFilter = groupsJson["deviceFilter"]?.let {
Singleton.json.decodeFromJsonElement(it)
},
appFilter = groupsJson["appFilter"]?.let {
Singleton.json.decodeFromJsonElement(it)
},
matchLauncher = getBoolean(groupsJson, "matchLauncher"),
quickFind = getBoolean(groupsJson, "quickFind"),
actionMaximum = getInt(groupsJson, "actionMaximum"),
matchDelay = getLong(groupsJson, "matchDelay"),
matchTime = getLong(groupsJson, "matchTime")
)
}

private fun jsonToAppRaw(appsJson: JsonObject, appIndex: Int): AppRaw {
return AppRaw(
activityIds = getStringIArray(appsJson, "activityIds"),
excludeActivityIds = getStringIArray(appsJson, "excludeActivityIds"),
cd = getLong(appsJson, "cd"),
delay = getLong(appsJson, "delay"),
actionCd = getLong(appsJson, "actionCd") ?: getLong(appsJson, "cd"),
actionDelay = getLong(appsJson, "actionDelay") ?: getLong(appsJson, "delay"),
id = getString(appsJson, "id") ?: error("miss subscription.apps[$appIndex].id"),
name = getString(appsJson, "name"),
groups = (when (val groupsJson = appsJson["groups"]) {
Expand All @@ -305,14 +251,11 @@ data class SubscriptionRaw(
}).mapIndexed { index, jsonElement ->
jsonToGroupRaw(jsonElement, index)
},
deviceFilter = appsJson["deviceFilter"]?.let {
Singleton.json.decodeFromJsonElement(it)
},
appFilter = appsJson["appFilter"]?.let {
Singleton.json.decodeFromJsonElement(it)
},
matchLauncher = getBoolean(appsJson, "matchLauncher"),
quickFind = getBoolean(appsJson, "quickFind"),
actionMaximum = getInt(appsJson, "actionMaximum"),
matchDelay = getLong(appsJson, "matchDelay"),
matchTime = getLong(appsJson, "matchTime")
)
}

Expand Down
30 changes: 25 additions & 5 deletions app/src/main/java/li/songe/gkd/service/AbState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.appScope
import li.songe.gkd.data.Rule
import li.songe.gkd.util.appIdToRulesFlow
import li.songe.gkd.util.map

val launcherActivityIdFlow by lazy {
MutableStateFlow<String?>(null)
Expand All @@ -15,7 +16,6 @@ val launcherActivityIdFlow by lazy {
data class TopActivity(
val appId: String,
val activityId: String? = null,
val sourceId: String? = null,
)

val topActivityFlow by lazy {
Expand All @@ -25,7 +25,7 @@ val topActivityFlow by lazy {
val currentRulesFlow by lazy {
combine(appIdToRulesFlow, topActivityFlow) { appIdToRules, topActivity ->
(appIdToRules[topActivity?.appId] ?: emptyList()).filter { rule ->
rule.matchActivityId(topActivity?.activityId) || rule.matchActivityId(topActivity?.sourceId)
rule.matchActivityId(topActivity?.activityId)
}
}.stateIn(appScope, SharingStarted.Eagerly, emptyList())
}
Expand All @@ -34,18 +34,38 @@ val lastTriggerRuleFlow by lazy {
MutableStateFlow<Rule?>(null)
}

private val activityIdChangeTimeFlow by lazy { topActivityFlow.map(appScope) { System.currentTimeMillis() } }

fun isAvailableRule(rule: Rule): Boolean {
if (!rule.active) return false // 处于冷却时间
if (rule.actionMaximum != null) {
if (activityIdChangeTimeFlow.value != rule.activityIdChangeTime) {
// 当 界面 改变时, 重置点击次数
rule.actionCount = 0
rule.activityIdChangeTime = activityIdChangeTimeFlow.value
}
if (rule.actionCount >= rule.actionMaximum) {
return false // 达到最大执行次数
}
}
val t = System.currentTimeMillis()
if (rule.matchDelay != null && t - activityIdChangeTimeFlow.value < rule.matchDelay) {
return false // 处于匹配延迟中
}
if (rule.matchTime != null && t - activityIdChangeTimeFlow.value > rule.matchAllTime) {
return false // 超出了匹配时间
}
if (!rule.notInCd) return false // 处于冷却时间
if (rule.preRules.isNotEmpty()) { // 需要提前点击某个规则
lastTriggerRuleFlow.value ?: return false
// 上一个点击的规则不在当前需要点击的列表
return rule.preRules.any { it === lastTriggerRuleFlow.value }
}
if (rule.delayTriggerTime > 0) {
if (rule.delayTriggerTime + rule.delay > System.currentTimeMillis()) {
if (rule.actionDelayTriggerTime > 0) {
if (rule.actionDelayTriggerTime + rule.actionDelay > t) {
return false // 没有延迟完毕
}
}
return true
}


Loading

0 comments on commit 0ef8cd3

Please sign in to comment.