feat: Add FCM token display and copy functionality in ChatsListScreen

This commit is contained in:
2026-02-25 21:16:14 +05:00
parent dd5bee5e42
commit dd473db8ff
3 changed files with 71 additions and 0 deletions

View File

@@ -420,6 +420,8 @@ class MainActivity : FragmentActivity() {
com.rosetta.messenger.push.RosettaFirebaseMessagingService.isAppInForeground = true com.rosetta.messenger.push.RosettaFirebaseMessagingService.isAppInForeground = true
// ⚡ На возврате в приложение пробуем мгновенный reconnect без ожидания backoff. // ⚡ На возврате в приложение пробуем мгновенный reconnect без ожидания backoff.
ProtocolManager.reconnectNowIfNeeded("activity_onResume") ProtocolManager.reconnectNowIfNeeded("activity_onResume")
// 🔄 Desktop parity: синхронизация при каждом заходе в приложение
ProtocolManager.syncOnForeground()
} }
override fun onPause() { override fun onPause() {

View File

@@ -69,6 +69,7 @@ object ProtocolManager {
private val _syncInProgress = MutableStateFlow(false) private val _syncInProgress = MutableStateFlow(false)
val syncInProgress: StateFlow<Boolean> = _syncInProgress.asStateFlow() val syncInProgress: StateFlow<Boolean> = _syncInProgress.asStateFlow()
@Volatile private var resyncRequiredAfterAccountInit = false @Volatile private var resyncRequiredAfterAccountInit = false
@Volatile private var lastForegroundSyncTime = 0L
// Desktop parity: sequential task queue matching dialogQueue.ts (promise chain). // Desktop parity: sequential task queue matching dialogQueue.ts (promise chain).
// Uses Channel to guarantee strict FIFO ordering (Mutex+lastInboundJob had a race // Uses Channel to guarantee strict FIFO ordering (Mutex+lastInboundJob had a race
// condition: Dispatchers.IO doesn't guarantee FIFO, so the last-launched job could // condition: Dispatchers.IO doesn't guarantee FIFO, so the last-launched job could
@@ -561,6 +562,22 @@ object ProtocolManager {
fun reconnectNowIfNeeded(reason: String = "foreground_resume") { fun reconnectNowIfNeeded(reason: String = "foreground_resume") {
getProtocol().reconnectNowIfNeeded(reason) getProtocol().reconnectNowIfNeeded(reason)
} }
/**
* Desktop parity: синхронизация при каждом заходе в приложение.
* Desktop вызывает trySync() на каждый handshakeExchangeComplete.
* На Android — вызываем из onResume(), если уже AUTHENTICATED и не идёт sync.
* Дебаунс 5 секунд чтобы не спамить при быстром alt-tab.
*/
fun syncOnForeground() {
if (!isAuthenticated()) return
if (syncBatchInProgress) return
val now = System.currentTimeMillis()
if (now - lastForegroundSyncTime < 5_000) return
lastForegroundSyncTime = now
addLog("🔄 SYNC on foreground resume")
requestSynchronize()
}
/** /**
* Authenticate with server * Authenticate with server

View File

@@ -1148,6 +1148,58 @@ fun ChatsListScreen(
} }
) )
// 🔔 FCM Token
DrawerDivider(isDarkTheme)
run {
var fcmToken by remember { mutableStateOf<String?>(null) }
LaunchedEffect(Unit) {
fcmToken = context.getSharedPreferences("rosetta_prefs", Context.MODE_PRIVATE)
.getString("fcm_token", null)
}
val clipboardManager = androidx.compose.ui.platform.LocalClipboardManager.current
val tokenValue = fcmToken
if (!tokenValue.isNullOrEmpty()) {
Column(
modifier = Modifier
.fillMaxWidth()
.clickable {
clipboardManager.setText(
androidx.compose.ui.text.AnnotatedString(tokenValue)
)
android.widget.Toast.makeText(
context,
"FCM token copied",
android.widget.Toast.LENGTH_SHORT
).show()
}
.padding(horizontal = 20.dp, vertical = 10.dp)
) {
Text(
text = "FCM Token (tap to copy)",
fontSize = 11.sp,
fontWeight = FontWeight.Medium,
color = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF8E8E93)
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = tokenValue,
fontSize = 9.sp,
color = if (isDarkTheme) Color(0xFF555555) else Color(0xFFAAAAAA),
maxLines = 3,
overflow = TextOverflow.Ellipsis,
fontFamily = FontFamily.Monospace
)
}
} else {
Text(
text = "FCM Token: not available",
fontSize = 11.sp,
color = if (isDarkTheme) Color(0xFF555555) else Color(0xFFAAAAAA),
modifier = Modifier.padding(horizontal = 20.dp, vertical = 10.dp)
)
}
}
} }
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════