Skip to content

Commit c1b908b

Browse files
committed
perf: sync status
1 parent ffa832e commit c1b908b

File tree

5 files changed

+96
-33
lines changed

5 files changed

+96
-33
lines changed

app/src/main/kotlin/li/songe/gkd/MainViewModel.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import li.songe.gkd.ui.component.RuleGroupState
4040
import li.songe.gkd.ui.component.UploadOptions
4141
import li.songe.gkd.ui.home.BottomNavItem
4242
import li.songe.gkd.util.LOCAL_SUBS_ID
43+
import li.songe.gkd.util.OnSimpleLife
4344
import li.songe.gkd.util.UpdateStatus
4445
import li.songe.gkd.util.appIconMapFlow
4546
import li.songe.gkd.util.clearCache
@@ -58,7 +59,7 @@ import kotlin.reflect.jvm.jvmName
5859

5960
private var tempTermsAccepted = false
6061

61-
class MainViewModel : ViewModel() {
62+
class MainViewModel : ViewModel(), OnSimpleLife {
6263

6364
private lateinit var navController: NavHostController
6465
fun updateNavController(navController: NavHostController) {
@@ -328,5 +329,9 @@ class MainViewModel : ViewModel() {
328329
// preload
329330
githubCookieFlow.value
330331
}
332+
333+
// for OnSimpleLife
334+
onCreated()
335+
addCloseable { onDestroyed() }
331336
}
332337
}

app/src/main/kotlin/li/songe/gkd/a11y/A11yExt.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ import android.provider.Settings
1111
import android.view.Display
1212
import android.view.accessibility.AccessibilityEvent
1313
import android.view.accessibility.AccessibilityNodeInfo
14-
import androidx.lifecycle.ViewModel
1514
import kotlinx.coroutines.flow.MutableStateFlow
1615
import kotlinx.coroutines.flow.StateFlow
1716
import li.songe.gkd.app
1817
import li.songe.gkd.service.A11yService
18+
import li.songe.gkd.util.OnSimpleLife
1919
import li.songe.selector.initDefaultTypeInfo
2020
import kotlin.coroutines.resume
2121
import kotlin.coroutines.suspendCoroutine
2222

23-
context(vm: ViewModel)
23+
context(context: OnSimpleLife)
2424
fun useA11yServiceEnabledFlow(): StateFlow<Boolean> {
2525
val stateFlow = MutableStateFlow(getA11yServiceEnabled())
2626
val contextObserver = object : ContentObserver(null) {
@@ -33,7 +33,7 @@ fun useA11yServiceEnabledFlow(): StateFlow<Boolean> {
3333
false,
3434
contextObserver
3535
)
36-
vm.addCloseable {
36+
context.onDestroyed {
3737
app.contentResolver.unregisterContentObserver(contextObserver)
3838
}
3939
return stateFlow

app/src/main/kotlin/li/songe/gkd/service/StatusService.kt

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@ import kotlinx.coroutines.flow.MutableStateFlow
66
import kotlinx.coroutines.flow.SharingStarted
77
import kotlinx.coroutines.flow.combine
88
import kotlinx.coroutines.flow.debounce
9+
import kotlinx.coroutines.flow.map
910
import kotlinx.coroutines.flow.stateIn
1011
import kotlinx.coroutines.launch
1112
import li.songe.gkd.META
13+
import li.songe.gkd.a11y.useA11yServiceEnabledFlow
1214
import li.songe.gkd.app
1315
import li.songe.gkd.notif.abNotif
1416
import li.songe.gkd.permission.foregroundServiceSpecialUseState
1517
import li.songe.gkd.permission.notificationState
18+
import li.songe.gkd.permission.shizukuOkState
19+
import li.songe.gkd.permission.writeSecureSettingsState
1620
import li.songe.gkd.store.actionCountFlow
1721
import li.songe.gkd.store.storeFlow
1822
import li.songe.gkd.util.OnSimpleLife
23+
import li.songe.gkd.util.RuleSummary
1924
import li.songe.gkd.util.getSubsStatus
2025
import li.songe.gkd.util.ruleSummaryFlow
2126
import li.songe.gkd.util.startForegroundServiceByClass
@@ -28,6 +33,50 @@ class StatusService : Service(), OnSimpleLife {
2833

2934
val scope = useScope()
3035

36+
val shizukuWarnFlow = combine(
37+
shizukuOkState.stateFlow,
38+
storeFlow.map { it.enableShizuku },
39+
) { a, b ->
40+
!a && b
41+
}.stateIn(scope, SharingStarted.Eagerly, false)
42+
43+
val a11yServiceEnabledFlow = useA11yServiceEnabledFlow()
44+
45+
fun statusTriple(): Triple<String, String, String?> {
46+
val abRunning = A11yService.isRunning.value
47+
val store = storeFlow.value
48+
val ruleSummary = ruleSummaryFlow.value
49+
val count = actionCountFlow.value
50+
val shizukuWarn = shizukuWarnFlow.value
51+
val title = if (store.useCustomNotifText) {
52+
store.customNotifTitle.replaceTemplate(ruleSummary, count)
53+
} else {
54+
META.appName
55+
}
56+
return if (!abRunning) {
57+
val text = if (a11yServiceEnabledFlow.value) {
58+
"无障碍服务发生故障"
59+
} else if (writeSecureSettingsState.updateAndGet()) {
60+
"无障碍服务已关闭"
61+
} else {
62+
"无障碍服务未授权"
63+
}
64+
Triple(title, text, abNotif.uri)
65+
} else if (!store.enableMatch) {
66+
Triple(title, "暂停规则匹配", "gkd://page?tab=1")
67+
} else if (shizukuWarn) {
68+
Triple(title, "Shizuku 未连接,请授权或关闭优化", "gkd://page/1")
69+
} else if (store.useCustomNotifText) {
70+
Triple(
71+
title,
72+
store.customNotifText.replaceTemplate(ruleSummary, count),
73+
abNotif.uri
74+
)
75+
} else {
76+
Triple(title, getSubsStatus(ruleSummary, count), abNotif.uri)
77+
}
78+
}
79+
3180
init {
3281
useAliveFlow(isRunning)
3382
useAliveToast(
@@ -42,30 +91,23 @@ class StatusService : Service(), OnSimpleLife {
4291
A11yService.isRunning,
4392
storeFlow,
4493
ruleSummaryFlow,
45-
actionCountFlow,
46-
) { abRunning, store, ruleSummary, count ->
47-
if (!abRunning) {
48-
META.appName to "无障碍未授权"
49-
} else if (!store.enableMatch) {
50-
META.appName to "暂停规则匹配"
51-
} else if (store.useCustomNotifText) {
52-
listOf(store.customNotifTitle, store.customNotifText).map {
53-
it.replace("\${i}", ruleSummary.globalGroups.size.toString())
54-
.replace("\${k}", ruleSummary.appSize.toString())
55-
.replace("\${u}", ruleSummary.appGroupSize.toString())
56-
.replace("\${n}", count.toString())
57-
}.run {
58-
first() to last()
59-
}
60-
} else {
61-
META.appName to getSubsStatus(ruleSummary, count)
62-
}
63-
}.debounce(1000L)
64-
.stateIn(scope, SharingStarted.Eagerly, "" to "")
65-
.collect { (title, text) ->
94+
shizukuWarnFlow,
95+
a11yServiceEnabledFlow,
96+
writeSecureSettingsState.stateFlow,
97+
actionCountFlow.debounce(1000L),
98+
) {
99+
statusTriple()
100+
}
101+
.stateIn(
102+
scope,
103+
SharingStarted.Eagerly,
104+
Triple(abNotif.title, abNotif.text, abNotif.uri)
105+
)
106+
.collect {
66107
abNotif.copy(
67-
title = title,
68-
text = text
108+
title = it.first,
109+
text = it.second,
110+
uri = it.third,
69111
).notifyService()
70112
}
71113
}
@@ -93,3 +135,10 @@ class StatusService : Service(), OnSimpleLife {
93135
}
94136
}
95137
}
138+
139+
private fun String.replaceTemplate(ruleSummary: RuleSummary, count: Long): String {
140+
return replace("\${i}", ruleSummary.globalGroups.size.toString())
141+
.replace("\${k}", ruleSummary.appSize.toString())
142+
.replace("\${u}", ruleSummary.appGroupSize.toString())
143+
.replace("\${n}", count.toString())
144+
}

app/src/main/kotlin/li/songe/gkd/ui/AdvancedPage.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import li.songe.gkd.service.HttpService
7171
import li.songe.gkd.service.RecordService
7272
import li.songe.gkd.service.ScreenshotService
7373
import li.songe.gkd.shizuku.shizukuContextFlow
74+
import li.songe.gkd.shizuku.updateBinderMutex
7475
import li.songe.gkd.store.storeFlow
7576
import li.songe.gkd.ui.component.AuthCard
7677
import li.songe.gkd.ui.component.SettingItem
@@ -247,6 +248,10 @@ fun AdvancedPage() {
247248
onSuffixClick = { mainVm.navigateWebPage(ShortUrlSet.URL14) },
248249
checked = store.enableShizuku,
249250
) {
251+
if (updateBinderMutex.mutex.isLocked) {
252+
toast("正在连接中,请稍后")
253+
return@TextSwitch
254+
}
250255
if (it && !shizukuOk) {
251256
toast("未授权")
252257
}

app/src/main/kotlin/li/songe/gkd/ui/home/ControlPage.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ fun useControlPage(): ScaffoldExt {
7878
val vm = viewModel<HomeVm>()
7979
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
8080
val scrollState = rememberScrollState()
81-
val writeSecureSettings by writeSecureSettingsState.stateFlow.collectAsState()
8281
return ScaffoldExt(
8382
navItem = BottomNavItem.Control,
8483
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
@@ -103,10 +102,7 @@ fun useControlPage(): ScaffoldExt {
103102

104103
val a11yRunning by A11yService.isRunning.collectAsState()
105104
val manageRunning by StatusService.isRunning.collectAsState()
106-
val a11yServiceEnabled by mainVm.a11yServiceEnabledFlow.collectAsState()
107-
108-
// 无障碍故障: 设置中无障碍开启, 但是实际 service 没有运行
109-
val a11yBroken = !a11yRunning && a11yServiceEnabled
105+
val writeSecureSettings by writeSecureSettingsState.stateFlow.collectAsState()
110106

111107
Column(
112108
modifier = Modifier
@@ -116,7 +112,15 @@ fun useControlPage(): ScaffoldExt {
116112
PageItemCard(
117113
imageVector = Icons.Default.Memory,
118114
title = "服务状态",
119-
subtitle = if (a11yRunning) "无障碍服务正在运行" else if (a11yBroken) "无障碍服务发生故障" else if (writeSecureSettings) "无障碍服务已关闭" else "无障碍服务未授权",
115+
subtitle = if (a11yRunning) {
116+
"无障碍服务正在运行"
117+
} else if (mainVm.a11yServiceEnabledFlow.collectAsState().value) {
118+
"无障碍服务发生故障"
119+
} else if (writeSecureSettings) {
120+
"无障碍服务已关闭"
121+
} else {
122+
"无障碍服务未授权"
123+
},
120124
rightContent = {
121125
Switch(
122126
checked = a11yRunning,

0 commit comments

Comments
 (0)