feat: dark mode background fixes, chat bubble long-press menu, notification dedup, biometric auth for clear

- Fix: dark mode white backgrounds via transparent windowBackground, decorView color, and explicit Surface backgrounds on IoT/Profile/MainScreen
- Fix: dark mode text colors in ProfileScreen (nickname, account info, assistant status)
- Feat: long-press chat bubble to copy message text via DropdownMenu
- Feat: notification deduplication — track notified message IDs, clear on foreground
- Feat: cancel all notifications when app enters foreground
- Feat: biometric/device-credential verification before clearing local messages

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 20:22:28 +08:00
parent 5247eef0fc
commit 9295fe8021
12 changed files with 147 additions and 21 deletions
@@ -25,6 +25,8 @@ class CyreneApplication : Application() {
private val initScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val activityCount = AtomicInteger(0)
@Volatile
private var notificationHelper: NotificationHelper? = null
override fun onCreate() {
super.onCreate()
@@ -40,6 +42,7 @@ class CyreneApplication : Application() {
override fun onActivityStarted(activity: Activity) {
if (activityCount.incrementAndGet() == 1) {
RuntimeLog.general("app", "App in foreground")
notificationHelper?.cancelAll()
getRepo()?.onAppForeground()
}
}
@@ -60,10 +63,11 @@ class CyreneApplication : Application() {
// Set up background notification callback once Koin is ready
initScope.launch {
val notificationHelper = NotificationHelper(this@CyreneApplication)
val helper = NotificationHelper(this@CyreneApplication)
notificationHelper = helper
val repo = getRepo()
repo?.setNotificationCallback { message ->
notificationHelper.showMessageNotification(message)
helper.showMessageNotification(message)
}
}