mirror of
https://github.com/gkd-kit/gkd.git
synced 2024-11-16 11:42:22 +08:00
feat: 缓慢查询
This commit is contained in:
parent
3f91b7fcb6
commit
3034c6aed9
|
@ -173,7 +173,7 @@ data class RawSubscription(
|
|||
}
|
||||
|
||||
val allSelectorStrings by lazy {
|
||||
rules.map { r -> r.matches + (r.excludeMatches ?: emptyList()) }.flatten().distinct()
|
||||
rules.map { r -> r.matches + (r.excludeMatches ?: emptyList()) }.flatten()
|
||||
}
|
||||
|
||||
val allSelector by lazy {
|
||||
|
@ -257,7 +257,7 @@ data class RawSubscription(
|
|||
) : RawGroupProps, RawAppRuleProps {
|
||||
|
||||
val allSelectorStrings by lazy {
|
||||
rules.map { r -> r.matches + (r.excludeMatches ?: emptyList()) }.flatten().distinct()
|
||||
rules.map { r -> r.matches + (r.excludeMatches ?: emptyList()) }.flatten()
|
||||
}
|
||||
|
||||
val allSelector by lazy {
|
||||
|
|
|
@ -16,7 +16,8 @@ sealed class ResolvedRule(
|
|||
) {
|
||||
val key = rule.key
|
||||
val index = group.rules.indexOf(rule)
|
||||
val preKeys = (rule.preKeys ?: emptyList()).toSet()
|
||||
val othersKeys = group.rules.filter { r -> r.key != rule.key }.mapNotNull { r -> r.key }.toSet()
|
||||
val preKeys = (rule.preKeys ?: emptyList()).filter { r -> othersKeys.contains(r) }.toSet()
|
||||
val resetMatch = rule.resetMatch ?: group.resetMatch
|
||||
val matches = rule.matches.map { s -> Selector.parse(s) }
|
||||
val excludeMatches = (rule.excludeMatches ?: emptyList()).map { s -> Selector.parse(s) }
|
||||
|
@ -41,6 +42,16 @@ sealed class ResolvedRule(
|
|||
|
||||
val order = rule.order ?: group.order ?: 0
|
||||
|
||||
val slowSelectors by lazy {
|
||||
(matches + excludeMatches).filterNot { s ->
|
||||
((quickFind && s.canQf) || s.isMatchRoot) && !s.connectKeys.contains(
|
||||
"<<"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val isSlow by lazy { preKeys.isEmpty() && slowSelectors.isNotEmpty() && (matchTime == null || matchTime > 30_000L) }
|
||||
|
||||
var groupToRules: Map<out RawSubscription.RawGroupProps, List<ResolvedRule>> = emptyMap()
|
||||
set(value) {
|
||||
field = value
|
||||
|
|
146
app/src/main/kotlin/li/songe/gkd/ui/SlowGroupPage.kt
Normal file
146
app/src/main/kotlin/li/songe/gkd/ui/SlowGroupPage.kt
Normal file
|
@ -0,0 +1,146 @@
|
|||
package li.songe.gkd.ui
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.annotation.RootNavGraph
|
||||
import li.songe.gkd.ui.destinations.AppItemPageDestination
|
||||
import li.songe.gkd.ui.destinations.GlobalRulePageDestination
|
||||
import li.songe.gkd.util.LocalNavController
|
||||
import li.songe.gkd.util.ProfileTransitions
|
||||
import li.songe.gkd.util.appInfoCacheFlow
|
||||
import li.songe.gkd.util.navigate
|
||||
import li.songe.gkd.util.ruleSummaryFlow
|
||||
|
||||
@RootNavGraph
|
||||
@Destination(style = ProfileTransitions::class)
|
||||
@Composable
|
||||
fun SlowGroupPage() {
|
||||
val navController = LocalNavController.current
|
||||
val ruleSummary by ruleSummaryFlow.collectAsState()
|
||||
val appInfoCache by appInfoCacheFlow.collectAsState()
|
||||
|
||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
scrollBehavior = scrollBehavior,
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
navController.popBackStack()
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
title = { Text(text = if (ruleSummary.slowGroupCount > 0) "缓慢查询-${ruleSummary.slowGroupCount}" else "缓慢查询") },
|
||||
actions = {}
|
||||
)
|
||||
}
|
||||
) { padding ->
|
||||
LazyColumn(modifier = Modifier.padding(padding)) {
|
||||
items(ruleSummary.slowGlobalGroups) { (group, rule) ->
|
||||
SlowGroupCard(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
navController.navigate(
|
||||
GlobalRulePageDestination(
|
||||
rule.subsItem.id,
|
||||
group.key
|
||||
)
|
||||
)
|
||||
}
|
||||
.padding(10.dp, 5.dp),
|
||||
title = group.name,
|
||||
desc = "${rule.rawSubs.name}-全局规则"
|
||||
)
|
||||
}
|
||||
items(ruleSummary.slowAppGroups) { (group, rule) ->
|
||||
SlowGroupCard(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
navController.navigate(
|
||||
AppItemPageDestination(
|
||||
rule.subsItem.id,
|
||||
rule.app.id,
|
||||
group.key
|
||||
)
|
||||
)
|
||||
}
|
||||
.padding(10.dp, 5.dp),
|
||||
title = group.name,
|
||||
desc = "${rule.rawSubs.name}-应用规则-${appInfoCache[rule.app.id]?.name ?: rule.app.name ?: rule.app.id}"
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
if (ruleSummary.slowGroupCount == 0) {
|
||||
Text(
|
||||
text = "暂无规则",
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SlowGroupCard(title: String, desc: String, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = modifier,
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = title, fontSize = 18.sp,
|
||||
maxLines = 1,
|
||||
softWrap = false,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Text(
|
||||
text = desc, fontSize = 14.sp,
|
||||
maxLines = 1,
|
||||
softWrap = false,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
|
@ -39,11 +39,13 @@ import li.songe.gkd.service.ManageService
|
|||
import li.songe.gkd.ui.component.AuthCard
|
||||
import li.songe.gkd.ui.component.TextSwitch
|
||||
import li.songe.gkd.ui.destinations.ClickLogPageDestination
|
||||
import li.songe.gkd.ui.destinations.SlowGroupPageDestination
|
||||
import li.songe.gkd.util.HOME_PAGE_URL
|
||||
import li.songe.gkd.util.LocalNavController
|
||||
import li.songe.gkd.util.checkOrRequestNotifPermission
|
||||
import li.songe.gkd.util.launchTry
|
||||
import li.songe.gkd.util.navigate
|
||||
import li.songe.gkd.util.ruleSummaryFlow
|
||||
import li.songe.gkd.util.storeFlow
|
||||
import li.songe.gkd.util.updateStorage
|
||||
import li.songe.gkd.util.usePollState
|
||||
|
@ -58,6 +60,7 @@ fun useControlPage(): ScaffoldExt {
|
|||
val latestRecordDesc by vm.latestRecordDescFlow.collectAsState()
|
||||
val subsStatus by vm.subsStatusFlow.collectAsState()
|
||||
val store by storeFlow.collectAsState()
|
||||
val ruleSummary by ruleSummaryFlow.collectAsState()
|
||||
|
||||
val gkdAccessRunning by GkdAbService.isRunning.collectAsState()
|
||||
val manageRunning by ManageService.isRunning.collectAsState()
|
||||
|
@ -216,6 +219,34 @@ fun useControlPage(): ScaffoldExt {
|
|||
}
|
||||
HorizontalDivider()
|
||||
|
||||
if (ruleSummary.slowGroupCount > 0) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
navController.navigate(SlowGroupPageDestination)
|
||||
}
|
||||
.padding(10.dp, 5.dp),
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = "耗时查询", fontSize = 18.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Text(
|
||||
text = "存在${ruleSummary.slowGroupCount}规则组,可能导致触发缓慢或更多耗电",
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
HorizontalDivider()
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
@ -102,6 +102,13 @@ data class RuleSummary(
|
|||
} else {
|
||||
"暂无规则"
|
||||
}
|
||||
|
||||
val slowGlobalGroups =
|
||||
globalRules.filter { r -> r.isSlow }.distinctBy { r -> r.group }.map { r -> r.group to r }
|
||||
val slowAppGroups =
|
||||
appIdToRules.values.flatten().filter { r -> r.isSlow }.distinctBy { r -> r.group }
|
||||
.map { r -> r.group to r }
|
||||
val slowGroupCount = slowGlobalGroups.size + slowAppGroups.size
|
||||
}
|
||||
|
||||
val ruleSummaryFlow by lazy {
|
||||
|
|
|
@ -27,8 +27,9 @@ class Selector internal constructor(private val propertyWrapper: PropertyWrapper
|
|||
var c = propertyWrapper.to
|
||||
val keys = mutableListOf<String>()
|
||||
while (c != null) {
|
||||
c!!.connectSegment.connectExpression
|
||||
keys.add(c!!.connectSegment.operator.key)
|
||||
c?.apply {
|
||||
keys.add(connectSegment.operator.key)
|
||||
}
|
||||
c = c?.to?.to
|
||||
}
|
||||
keys.toTypedArray()
|
||||
|
|
Loading…
Reference in New Issue
Block a user