fix: 用通知前快照精确显示红点(区分首页/非首页场景)
问题:非首页返回时,onViewCreated已覆盖lastStats, 导致diffStats对比不出差异,红点要么全显要么不显。 修复: 1. NotificationManager新增preNotificationStats - 首条通知到达时保存当前lastStats快照 - consumeAll时清除 - 不会被onViewCreated的fetchStatistics覆盖 2. HomeFragment.onResume用preNotificationStats做精确diffStats - 有快照→fetchStatisticsForDots(baseline, acknowledged) - 只给变化且未查看的分类显示红点 - 无快照→降级为全显(未查看的) 场景验证: - 首页收到通知→当场diffStats→红点精确 ✅ - 首页点红点→对应消除,其他保留 ✅ - 首页点通知→consumeAll→返回后全部消除 ✅ - 非首页返回→preNotificationStats对比→红点精确 ✅ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,10 @@ class NotificationManager @Inject constructor(
|
|||||||
/** 上次统计数据(对比红点用) */
|
/** 上次统计数据(对比红点用) */
|
||||||
var lastStats: TaskStatistics? = null
|
var lastStats: TaskStatistics? = null
|
||||||
|
|
||||||
|
/** 通知到达前的统计快照(用于非首页返回后精确 diffStats) */
|
||||||
|
var preNotificationStats: TaskStatistics? = null
|
||||||
|
private set
|
||||||
|
|
||||||
/** 协程作用域 */
|
/** 协程作用域 */
|
||||||
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||||
|
|
||||||
@@ -111,6 +115,11 @@ class NotificationManager @Inject constructor(
|
|||||||
val taskIds = parseTaskIds(rawJson)
|
val taskIds = parseTaskIds(rawJson)
|
||||||
if (taskIds.isEmpty()) return
|
if (taskIds.isEmpty()) return
|
||||||
|
|
||||||
|
// 保存通知到达前的统计快照(只在首次通知时保存,后续累积不覆盖)
|
||||||
|
if (preNotificationStats == null) {
|
||||||
|
preNotificationStats = lastStats?.copy()
|
||||||
|
}
|
||||||
|
|
||||||
addTaskIds(taskIds)
|
addTaskIds(taskIds)
|
||||||
|
|
||||||
// 震动 + 亮屏(只在首条时触发,暂存的合并后不重复震动)
|
// 震动 + 亮屏(只在首条时触发,暂存的合并后不重复震动)
|
||||||
@@ -152,6 +161,7 @@ class NotificationManager @Inject constructor(
|
|||||||
_pendingTaskIds.clear()
|
_pendingTaskIds.clear()
|
||||||
acknowledgedCards.clear()
|
acknowledgedCards.clear()
|
||||||
_cardIncrements.clear()
|
_cardIncrements.clear()
|
||||||
|
preNotificationStats = null
|
||||||
Timber.d("通知: 已清空全部未读")
|
Timber.d("通知: 已清空全部未读")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,19 +130,59 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
// 从其他页面返回时,只恢复未查看分类的红点
|
if (notificationManager.pendingCount <= 0) {
|
||||||
if (notificationManager.pendingCount > 0) {
|
|
||||||
val ack = notificationManager.acknowledgedCards
|
|
||||||
if (2 !in ack) dotPool.visibility = View.VISIBLE
|
|
||||||
if (3 !in ack) dotPunch.visibility = View.VISIBLE
|
|
||||||
if (4 !in ack) dotComplete.visibility = View.VISIBLE
|
|
||||||
updateNewTaskHint()
|
|
||||||
} else {
|
|
||||||
// 全部已查看 → 清除所有提示
|
// 全部已查看 → 清除所有提示
|
||||||
dotPool.visibility = View.GONE
|
dotPool.visibility = View.GONE
|
||||||
dotPunch.visibility = View.GONE
|
dotPunch.visibility = View.GONE
|
||||||
dotComplete.visibility = View.GONE
|
dotComplete.visibility = View.GONE
|
||||||
tvNewTaskHint.visibility = View.GONE
|
tvNewTaskHint.visibility = View.GONE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有未读通知 → 用 preNotificationStats 精确对比红点
|
||||||
|
// (preNotificationStats 是通知到达前的快照,不会被 onViewCreated 的 fetchStatistics 覆盖)
|
||||||
|
val ack = notificationManager.acknowledgedCards
|
||||||
|
val baseline = notificationManager.preNotificationStats
|
||||||
|
if (baseline != null) {
|
||||||
|
// 精确模式:对比快照和当前统计,只给变化的分类显示红点
|
||||||
|
fetchStatisticsForDots(baseline, ack)
|
||||||
|
} else {
|
||||||
|
// 无快照(首次加载等):已查看的不显示,未查看的显示
|
||||||
|
if (2 !in ack) dotPool.visibility = View.VISIBLE
|
||||||
|
if (3 !in ack) dotPunch.visibility = View.VISIBLE
|
||||||
|
if (4 !in ack) dotComplete.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
updateNewTaskHint()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用通知前快照精确对比红点(非首页返回时调用)
|
||||||
|
* @param baseline 通知到达前的统计快照
|
||||||
|
* @param acknowledged 已查看的分类集合
|
||||||
|
*/
|
||||||
|
private fun fetchStatisticsForDots(baseline: com.xiaoqu.watch.data.task.TaskStatistics, acknowledged: Set<Int>) {
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
val result = safeApiCall { taskApi.getStatistics() }
|
||||||
|
if (result is ApiResult.Success && result.data != null) {
|
||||||
|
val data = result.data
|
||||||
|
val changed = notificationManager.diffStats(baseline, data)
|
||||||
|
|
||||||
|
// 只给变化且未查看的分类显示红点
|
||||||
|
dotPool.visibility = if (2 in changed && 2 !in acknowledged) View.VISIBLE else View.GONE
|
||||||
|
dotPunch.visibility = if (3 in changed && 3 !in acknowledged) View.VISIBLE else View.GONE
|
||||||
|
dotComplete.visibility = if (4 in changed && 4 !in acknowledged) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
|
// 记录增量(供 acknowledgeCard 扣减用)
|
||||||
|
if (2 in changed) notificationManager.recordCardIncrement(2, data.waitForTask - baseline.waitForTask)
|
||||||
|
if (3 in changed) notificationManager.recordCardIncrement(3, data.treatTask - baseline.treatTask)
|
||||||
|
if (4 in changed) notificationManager.recordCardIncrement(4, data.incompleteTask - baseline.incompleteTask)
|
||||||
|
|
||||||
|
// 更新数字
|
||||||
|
tvPoolNum.text = data.waitForTask.toString()
|
||||||
|
tvPunchNum.text = data.treatTask.toString()
|
||||||
|
tvCompleteNum.text = data.incompleteTask.toString()
|
||||||
|
notificationManager.lastStats = data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user