diff --git a/app/src/main/kotlin/top/yeij/cyrene/app/CyreneApp.kt b/app/src/main/kotlin/top/yeij/cyrene/app/CyreneApp.kt index 01508ee..5e48f71 100644 --- a/app/src/main/kotlin/top/yeij/cyrene/app/CyreneApp.kt +++ b/app/src/main/kotlin/top/yeij/cyrene/app/CyreneApp.kt @@ -40,7 +40,10 @@ fun CyreneApp(container: AppContainer) { * 而授权变化只有两条路——本端刚申请完(设置页那次写入会连带把这里重跑一遍)、或用户在系统 * 设置里改过(下次启动必然重跑)。 */ - LaunchedEffect(prefs.keepAliveEnabled, state) { + // ⚠️ key 里必须有「回到前台」这一位(W53S 登记的那一格):通知权限是**现读**的,而用户在系统 + // 设置里授权后回到 App 时,只有这个状态会变 —— 少了它,UI 会说「已开」而服务其实没起。 + val appInForeground by container.appPresence.appInForegroundFlow.collectAsState() + LaunchedEffect(prefs.keepAliveEnabled, state, appInForeground) { when ( keepAliveAction( enabled = prefs.keepAliveEnabled, diff --git a/app/src/main/kotlin/top/yeij/cyrene/core/notify/AppPresence.kt b/app/src/main/kotlin/top/yeij/cyrene/core/notify/AppPresence.kt index 6e18050..1964dc4 100644 --- a/app/src/main/kotlin/top/yeij/cyrene/core/notify/AppPresence.kt +++ b/app/src/main/kotlin/top/yeij/cyrene/core/notify/AppPresence.kt @@ -2,6 +2,9 @@ package top.yeij.cyrene.core.notify import java.util.Collections import java.util.concurrent.ConcurrentHashMap +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow /** * 进程级的两个「我此刻在哪儿」的事实(W53N):**App 在不在前台**、**聊天页正显示哪个会话**。 @@ -44,9 +47,23 @@ class AppPresence { val appInForeground: Boolean get() = startedActivities.isNotEmpty() + private val _appInForeground = MutableStateFlow(false) + + /** + * [appInForeground] 的**可订阅**形态(W53S 登记的那一格要它)。 + * + * 为什么需要第二条出口:`CyreneApp` 那个「起 / 停前台服务」的 `LaunchedEffect` 的 key 里没有 + * 通知权限,于是**用户在系统设置里授权后回到 App** 时它不会重跑 —— UI 已经显示「已开」, + * 服务却没起。权限本身必须**现读**(不该缓存成状态),能当 key 的是「刚好会在这件事发生时变化」 + * 的信号:**回到前台**(从系统设置返回必经 `onStart`)。所以这里把「在不在前台」补成一条流。 + * 判据本身仍然只读 [appInForeground] 那个布尔——两条出口算的是**同一份事实**(同一个集合)。 + */ + val appInForegroundFlow: StateFlow = _appInForeground.asStateFlow() + /** 一个 Activity 进入「可见」这一档(`onStart`)。 */ fun onActivityStarted(owner: Any) { startedActivities.add(owner) + _appInForeground.value = appInForeground } /** @@ -57,6 +74,7 @@ class AppPresence { */ fun onActivityStopped(owner: Any) { startedActivities.remove(owner) + _appInForeground.value = appInForeground } /** 聊天页刚显示(或刚换成)[sessionId];`null` = 它离开了屏幕。 */