feat: Add VerifiedBadge and online status to user profile header

This commit is contained in:
k1ngsterr1
2026-01-25 18:43:40 +05:00
parent efd666ee41
commit 37acbfeef6
3 changed files with 74 additions and 14 deletions

View File

@@ -613,6 +613,22 @@ class MessageRepository private constructor(private val context: Context) {
}
/**
* Наблюдать за онлайн статусом пользователя
*/
fun observeUserOnlineStatus(publicKey: String): Flow<Pair<Boolean, Long>> {
val account = currentAccount ?: return flowOf(false to 0L)
return dialogDao.observeOnlineStatus(account, publicKey)
.map { info ->
if (info != null) {
(info.isOnline == 1) to info.lastSeen
} else {
false to 0L
}
}
}
/**
* Обновить информацию о пользователе в диалоге (имя, username, verified)
* Вызывается когда приходит ответ на PacketSearch

View File

@@ -478,6 +478,22 @@ interface DialogDao {
""")
suspend fun updateOnlineStatus(account: String, opponentKey: String, isOnline: Int, lastSeen: Long)
/**
* Получить онлайн статус пользователя
*/
@Query("""
SELECT is_online, last_seen
FROM dialogs
WHERE account = :account AND opponent_key = :opponentKey
LIMIT 1
""")
fun observeOnlineStatus(account: String, opponentKey: String): Flow<OnlineStatusInfo?>
data class OnlineStatusInfo(
@ColumnInfo(name = "is_online") val isOnline: Int,
@ColumnInfo(name = "last_seen") val lastSeen: Long
)
/**
* Удалить диалог
*/

View File

@@ -15,7 +15,9 @@ import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.Block
import androidx.compose.material3.*
import androidx.compose.runtime.*
import com.rosetta.messenger.data.MessageRepository
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import com.rosetta.messenger.ui.components.VerifiedBadge
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -60,6 +62,13 @@ fun OtherProfileScreen(
val avatarColors = getAvatarColor(user.publicKey, isDarkTheme)
val context = LocalContext.current
// 🟢 Наблюдаем за онлайн статусом пользователя в реальном времени
val messageRepository = remember { MessageRepository.getInstance(context) }
val onlineStatus by messageRepository.observeUserOnlineStatus(user.publicKey)
.collectAsState(initial = false to 0L)
val isOnline = onlineStatus.first
val lastSeen = onlineStatus.second
// Scroll state for collapsing header animation
val density = LocalDensity.current
val statusBarHeight = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
@@ -153,6 +162,9 @@ fun OtherProfileScreen(
name = user.title.ifEmpty { "Unknown User" },
username = user.username,
publicKey = user.publicKey,
verified = user.verified,
isOnline = isOnline,
lastSeen = lastSeen,
avatarColors = avatarColors,
collapseProgress = collapseProgress,
onBack = onBack,
@@ -172,6 +184,9 @@ private fun CollapsingOtherProfileHeader(
name: String,
username: String,
publicKey: String,
verified: Int,
isOnline: Boolean,
lastSeen: Long,
avatarColors: AvatarColors,
collapseProgress: Float,
onBack: () -> Unit,
@@ -309,7 +324,7 @@ private fun CollapsingOtherProfileHeader(
}
// ═══════════════════════════════════════════════════════════
// 📝 TEXT BLOCK - Name + Online, always centered
// 📝 TEXT BLOCK - Name + Verified + Online, always centered
// ═══════════════════════════════════════════════════════════
Column(
modifier = Modifier
@@ -323,24 +338,37 @@ private fun CollapsingOtherProfileHeader(
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = name,
fontSize = nameFontSize,
fontWeight = FontWeight.SemiBold,
color = Color.White,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.widthIn(max = 220.dp),
textAlign = TextAlign.Center
)
// Name + Verified Badge
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Text(
text = name,
fontSize = nameFontSize,
fontWeight = FontWeight.SemiBold,
color = Color.White,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
if (verified > 0) {
Spacer(modifier = Modifier.width(4.dp))
VerifiedBadge(
verified = verified,
size = (nameFontSize.value * 0.8f).toInt()
)
}
}
Spacer(modifier = Modifier.height(2.dp))
// Online text - always centered
// Online/Offline status
Text(
text = "online",
text = if (isOnline) "online" else "offline",
fontSize = onlineFontSize,
color = Color(0xFF4CAF50)
color = if (isOnline) Color(0xFF4CAF50) else Color.White.copy(alpha = 0.6f)
)
}
}