Refactor code structure for improved readability and maintainability

This commit is contained in:
k1ngsterr1
2026-01-19 17:20:35 +05:00
parent 19a89ea00e
commit b7cbc35868
6 changed files with 5547 additions and 2390 deletions

View File

@@ -1,7 +1,6 @@
package com.rosetta.messenger
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
@@ -11,110 +10,115 @@ import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import androidx.compose.animation.*
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.FastOutLinearInEasing
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.google.firebase.FirebaseApp
import com.google.firebase.messaging.FirebaseMessaging
import com.rosetta.messenger.crypto.CryptoManager
import com.rosetta.messenger.data.AccountManager
import com.rosetta.messenger.data.DecryptedAccount
import com.rosetta.messenger.data.PreferencesManager
import com.rosetta.messenger.data.RecentSearchesManager
import com.rosetta.messenger.network.PacketPushNotification
import com.rosetta.messenger.network.PushNotificationAction
import com.rosetta.messenger.network.ProtocolManager
import com.rosetta.messenger.network.ProtocolState
import com.rosetta.messenger.network.PushNotificationAction
import com.rosetta.messenger.network.SearchUser
import com.rosetta.messenger.ui.auth.AccountInfo
import com.rosetta.messenger.ui.auth.AuthFlow
import com.rosetta.messenger.ui.chats.ChatsListScreen
import com.rosetta.messenger.ui.chats.ChatDetailScreen
import com.rosetta.messenger.ui.chats.ChatsListScreen
import com.rosetta.messenger.ui.chats.SearchScreen
import com.rosetta.messenger.network.SearchUser
import com.rosetta.messenger.ui.components.EmojiCache
import com.rosetta.messenger.ui.components.OptimizedEmojiCache
import com.rosetta.messenger.ui.onboarding.OnboardingScreen
import com.rosetta.messenger.ui.splash.SplashScreen
import com.rosetta.messenger.ui.theme.RosettaAndroidTheme
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
private lateinit var preferencesManager: PreferencesManager
private lateinit var accountManager: AccountManager
companion object {
private const val TAG = "MainActivity"
// 🔔 FCM Логи для отображения в UI
private val _fcmLogs = mutableStateListOf<String>()
val fcmLogs: List<String>
get() = _fcmLogs
fun addFcmLog(message: String) {
val timestamp = SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(Date())
_fcmLogs.add(0, "[$timestamp] $message") // Добавляем в начало списка
// Ограничиваем количество логов
if (_fcmLogs.size > 20) {
_fcmLogs.removeAt(_fcmLogs.size - 1)
}
Log.d(TAG, "FCM: $message")
}
fun clearFcmLogs() {
_fcmLogs.clear()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
preferencesManager = PreferencesManager(this)
accountManager = AccountManager(this)
RecentSearchesManager.init(this)
// 🔥 Инициализируем ProtocolManager для обработки онлайн статусов
ProtocolManager.initialize(this)
// 🔔 Инициализируем Firebase для push-уведомлений
initializeFirebase()
// 🔥 Помечаем что приложение в foreground
com.rosetta.messenger.push.RosettaFirebaseMessagingService.isAppInForeground = true
// 📱 Предзагружаем эмодзи в фоне для мгновенного открытия пикера
// Используем новый оптимизированный кэш
OptimizedEmojiCache.preload(this)
setContent { // 🔔 Запрос разрешения на уведомления для Android 13+
val notificationPermissionLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
onResult = { isGranted ->
}
)
setContent { // 🔔 Запрос разрешения на уведомления для Android 13+
val notificationPermissionLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
onResult = { isGranted -> }
)
// Запрашиваем разрешение при первом запуске (Android 13+)
LaunchedEffect(Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val hasPermission = ContextCompat.checkSelfPermission(
this@MainActivity,
Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
val hasPermission =
ContextCompat.checkSelfPermission(
this@MainActivity,
Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
if (!hasPermission) {
notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
notificationPermissionLauncher.launch(
Manifest.permission.POST_NOTIFICATIONS
)
}
}
}
val scope = rememberCoroutineScope()
val isDarkTheme by preferencesManager.isDarkTheme.collectAsState(initial = true)
val isLoggedIn by accountManager.isLoggedIn.collectAsState(initial = null)
@@ -123,152 +127,179 @@ class MainActivity : ComponentActivity() {
var hasExistingAccount by remember { mutableStateOf<Boolean?>(null) }
var currentAccount by remember { mutableStateOf<DecryptedAccount?>(null) }
var accountInfoList by remember { mutableStateOf<List<AccountInfo>>(emptyList()) }
// Check for existing accounts and build AccountInfo list
// Also force logout so user always sees unlock screen on app restart
LaunchedEffect(Unit) {
accountManager.logout() // Always start logged out
val accounts = accountManager.getAllAccounts()
hasExistingAccount = accounts.isNotEmpty()
accountInfoList = accounts.map { account ->
val shortKey = account.publicKey.take(7)
val displayName = account.name ?: shortKey
val initials = displayName.trim().split(Regex("\\s+"))
.filter { it.isNotEmpty() }
.let { words ->
when {
words.isEmpty() -> "??"
words.size == 1 -> words[0].take(2).uppercase()
else -> "${words[0].first()}${words[1].first()}".uppercase()
}
accountInfoList =
accounts.map { account ->
val shortKey = account.publicKey.take(7)
val displayName = account.name ?: shortKey
val initials =
displayName
.trim()
.split(Regex("\\s+"))
.filter { it.isNotEmpty() }
.let { words ->
when {
words.isEmpty() -> "??"
words.size == 1 -> words[0].take(2).uppercase()
else ->
"${words[0].first()}${words[1].first()}".uppercase()
}
}
AccountInfo(
id = account.publicKey,
name = displayName,
initials = initials,
publicKey = account.publicKey
)
}
AccountInfo(
id = account.publicKey,
name = displayName,
initials = initials,
publicKey = account.publicKey
)
}
}
// Wait for initial load
if (hasExistingAccount == null) {
Box(
modifier = Modifier
.fillMaxSize()
.background(if (isDarkTheme) Color(0xFF1B1B1B) else Color.White)
modifier =
Modifier.fillMaxSize()
.background(
if (isDarkTheme) Color(0xFF1B1B1B) else Color.White
)
)
return@setContent
}
RosettaAndroidTheme(
darkTheme = isDarkTheme,
animated = true
) {
RosettaAndroidTheme(darkTheme = isDarkTheme, animated = true) {
Surface(
modifier = Modifier.fillMaxSize(),
color = if (isDarkTheme) Color(0xFF1B1B1B) else Color.White
modifier = Modifier.fillMaxSize(),
color = if (isDarkTheme) Color(0xFF1B1B1B) else Color.White
) {
AnimatedContent(
targetState = when {
showSplash -> "splash"
showOnboarding && hasExistingAccount == false -> "onboarding"
isLoggedIn != true && hasExistingAccount == false -> "auth_new"
isLoggedIn != true && hasExistingAccount == true -> "auth_unlock"
else -> "main"
},
transitionSpec = {
fadeIn(animationSpec = tween(600)) togetherWith
fadeOut(animationSpec = tween(600))
},
label = "screenTransition"
targetState =
when {
showSplash -> "splash"
showOnboarding && hasExistingAccount == false ->
"onboarding"
isLoggedIn != true && hasExistingAccount == false ->
"auth_new"
isLoggedIn != true && hasExistingAccount == true ->
"auth_unlock"
else -> "main"
},
transitionSpec = {
fadeIn(animationSpec = tween(600)) togetherWith
fadeOut(animationSpec = tween(600))
},
label = "screenTransition"
) { screen ->
when (screen) {
"splash" -> {
SplashScreen(
isDarkTheme = isDarkTheme,
onSplashComplete = { showSplash = false }
isDarkTheme = isDarkTheme,
onSplashComplete = { showSplash = false }
)
}
"onboarding" -> {
OnboardingScreen(
isDarkTheme = isDarkTheme,
onThemeToggle = {
scope.launch {
preferencesManager.setDarkTheme(!isDarkTheme)
}
},
onStartMessaging = {
showOnboarding = false
}
isDarkTheme = isDarkTheme,
onThemeToggle = {
scope.launch {
preferencesManager.setDarkTheme(!isDarkTheme)
}
},
onStartMessaging = { showOnboarding = false }
)
}
"auth_new", "auth_unlock" -> {
AuthFlow(
isDarkTheme = isDarkTheme,
hasExistingAccount = screen == "auth_unlock",
accounts = accountInfoList,
accountManager = accountManager,
onAuthComplete = { account ->
currentAccount = account
hasExistingAccount = true
// Save as last logged account
account?.let { accountManager.setLastLoggedPublicKey(it.publicKey) }
// 📤 Отправляем FCM токен на сервер после успешной аутентификации
account?.let { sendFcmTokenToServer(it) }
// Reload accounts list
scope.launch {
val accounts = accountManager.getAllAccounts()
accountInfoList = accounts.map { acc ->
val shortKey = acc.publicKey.take(7)
val displayName = acc.name ?: shortKey
val initials = displayName.trim().split(Regex("\\s+"))
.filter { it.isNotEmpty() }
.let { words ->
when {
words.isEmpty() -> "??"
words.size == 1 -> words[0].take(2).uppercase()
else -> "${words[0].first()}${words[1].first()}".uppercase()
isDarkTheme = isDarkTheme,
hasExistingAccount = screen == "auth_unlock",
accounts = accountInfoList,
accountManager = accountManager,
onAuthComplete = { account ->
currentAccount = account
hasExistingAccount = true
// Save as last logged account
account?.let {
accountManager.setLastLoggedPublicKey(it.publicKey)
}
// 📤 Отправляем FCM токен на сервер после успешной
// аутентификации
account?.let { sendFcmTokenToServer(it) }
// Reload accounts list
scope.launch {
val accounts = accountManager.getAllAccounts()
accountInfoList =
accounts.map { acc ->
val shortKey = acc.publicKey.take(7)
val displayName = acc.name ?: shortKey
val initials =
displayName
.trim()
.split(Regex("\\s+"))
.filter {
it.isNotEmpty()
}
.let { words ->
when {
words.isEmpty() ->
"??"
words.size ==
1 ->
words[0]
.take(
2
)
.uppercase()
else ->
"${words[0].first()}${words[1].first()}".uppercase()
}
}
AccountInfo(
id = acc.publicKey,
name = displayName,
initials = initials,
publicKey = acc.publicKey
)
}
}
AccountInfo(
id = acc.publicKey,
name = displayName,
initials = initials,
publicKey = acc.publicKey
)
}
},
onLogout = {
// Set currentAccount to null immediately to prevent UI
// lag
currentAccount = null
scope.launch {
com.rosetta.messenger.network.ProtocolManager
.disconnect()
accountManager.logout()
}
}
},
onLogout = {
// Set currentAccount to null immediately to prevent UI lag
currentAccount = null
scope.launch {
com.rosetta.messenger.network.ProtocolManager.disconnect()
accountManager.logout()
}
}
)
}
"main" -> {
MainScreen(
account = currentAccount,
isDarkTheme = isDarkTheme,
onToggleTheme = {
scope.launch {
preferencesManager.setDarkTheme(!isDarkTheme)
account = currentAccount,
isDarkTheme = isDarkTheme,
onToggleTheme = {
scope.launch {
preferencesManager.setDarkTheme(!isDarkTheme)
}
},
onLogout = {
// Set currentAccount to null immediately to prevent UI
// lag
currentAccount = null
scope.launch {
com.rosetta.messenger.network.ProtocolManager
.disconnect()
accountManager.logout()
}
}
},
onLogout = {
// Set currentAccount to null immediately to prevent UI lag
currentAccount = null
scope.launch {
com.rosetta.messenger.network.ProtocolManager.disconnect()
accountManager.logout()
}
}
)
}
}
@@ -277,86 +308,107 @@ class MainActivity : ComponentActivity() {
}
}
}
override fun onResume() {
super.onResume()
// 🔥 Приложение стало видимым - отключаем уведомления
com.rosetta.messenger.push.RosettaFirebaseMessagingService.isAppInForeground = true
}
override fun onPause() {
super.onPause()
// 🔥 Приложение ушло в background - включаем уведомления
com.rosetta.messenger.push.RosettaFirebaseMessagingService.isAppInForeground = false
}
/**
* 🔔 Инициализация Firebase Cloud Messaging
*/
/** 🔔 Инициализация Firebase Cloud Messaging */
private fun initializeFirebase() {
try {
addFcmLog("🔔 Инициализация Firebase...")
// Инициализируем Firebase
FirebaseApp.initializeApp(this)
addFcmLog("✅ Firebase инициализирован")
// Получаем FCM токен
addFcmLog("📲 Запрос FCM токена...")
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (!task.isSuccessful) {
addFcmLog("❌ Ошибка получения токена: ${task.exception?.message}")
return@addOnCompleteListener
}
val token = task.result
// Сохраняем токен локально
token?.let { saveFcmToken(it) }
if (token != null) {
val shortToken = "${token.take(12)}...${token.takeLast(8)}"
addFcmLog("✅ FCM токен получен: $shortToken")
// Сохраняем токен локально
saveFcmToken(token)
addFcmLog("💾 Токен сохранен локально")
} else {
addFcmLog("⚠️ Токен пустой")
}
// Токен будет отправлен на сервер после успешной аутентификации
// (см. вызов sendFcmTokenToServer в onAccountLogin)
}
} catch (e: Exception) {
addFcmLog("❌ Ошибка Firebase: ${e.message}")
}
}
/**
* Сохранить FCM токен в SharedPreferences
*/
/** Сохранить FCM токен в SharedPreferences */
private fun saveFcmToken(token: String) {
val prefs = getSharedPreferences("rosetta_prefs", MODE_PRIVATE)
prefs.edit().putString("fcm_token", token).apply()
}
/**
* Отправить FCM токен на сервер
* Вызывается после успешной аутентификации, когда аккаунт уже расшифрован
* Отправить FCM токен на сервер Вызывается после успешной аутентификации, когда аккаунт уже
* расшифрован
*/
private fun sendFcmTokenToServer(account: DecryptedAccount) {
lifecycleScope.launch {
try {
val prefs = getSharedPreferences("rosetta_prefs", MODE_PRIVATE)
val token = prefs.getString("fcm_token", null)
if (token == null) {
addFcmLog("⚠️ Нет сохраненного токена для отправки")
return@launch
}
val shortToken = "${token.take(12)}...${token.takeLast(8)}"
addFcmLog("📤 Подготовка к отправке токена на сервер")
addFcmLog("⏳ Ожидание аутентификации...")
// 🔥 КРИТИЧНО: Ждем пока протокол станет AUTHENTICATED
var waitAttempts = 0
while (ProtocolManager.state.value != ProtocolState.AUTHENTICATED && waitAttempts < 50) {
while (ProtocolManager.state.value != ProtocolState.AUTHENTICATED &&
waitAttempts < 50) {
delay(100) // Ждем 100ms
waitAttempts++
}
if (ProtocolManager.state.value != ProtocolState.AUTHENTICATED) {
addFcmLog("❌ Таймаут аутентификации (${waitAttempts * 100}ms)")
return@launch
}
val packet = PacketPushNotification().apply {
this.notificationsToken = token
this.action = PushNotificationAction.SUBSCRIBE
}
addFcmLog("✅ Аутентификация успешна")
addFcmLog("📨 Отправка токена: $shortToken")
val packet =
PacketPushNotification().apply {
this.notificationsToken = token
this.action = PushNotificationAction.SUBSCRIBE
}
ProtocolManager.send(packet)
addFcmLog("✅ Пакет отправлен на сервер (ID: 0x10)")
addFcmLog("🎉 FCM токен успешно зарегистрирован!")
} catch (e: Exception) {
addFcmLog("❌ Ошибка отправки: ${e.message}")
}
}
}
@@ -364,177 +416,162 @@ class MainActivity : ComponentActivity() {
@Composable
fun MainScreen(
account: DecryptedAccount? = null,
isDarkTheme: Boolean = true,
onToggleTheme: () -> Unit = {},
onLogout: () -> Unit = {}
account: DecryptedAccount? = null,
isDarkTheme: Boolean = true,
onToggleTheme: () -> Unit = {},
onLogout: () -> Unit = {}
) {
val accountName = account?.name ?: "Account"
val accountPhone = account?.publicKey?.take(16)?.let {
"+${it.take(1)} ${it.substring(1, 4)} ${it.substring(4, 7)}${it.substring(7)}"
} ?: "+7 775 9932587"
val accountPhone =
account?.publicKey?.take(16)?.let {
"+${it.take(1)} ${it.substring(1, 4)} ${it.substring(4, 7)}${it.substring(7)}"
}
?: "+7 775 9932587"
val accountPublicKey = account?.publicKey ?: "04c266b98ae5"
val accountPrivateKey = account?.privateKey ?: ""
val privateKeyHash = account?.privateKeyHash ?: ""
// Состояние протокола для передачи в SearchScreen
val protocolState by ProtocolManager.state.collectAsState()
// Навигация между экранами
var selectedUser by remember { mutableStateOf<SearchUser?>(null) }
var showSearchScreen by remember { mutableStateOf(false) }
// 🔥 TELEGRAM-STYLE анимация - чистый slide БЕЗ прозрачности
AnimatedContent(
targetState = Triple(selectedUser, showSearchScreen, Unit),
transitionSpec = {
val isEnteringChat = targetState.first != null && initialState.first == null
val isExitingChat = targetState.first == null && initialState.first != null
val isEnteringSearch = targetState.second && !initialState.second
val isExitingSearch = !targetState.second && initialState.second
when {
// 🚀 Вход в чат - плавный fade
isEnteringChat -> {
fadeIn(
animationSpec = tween(200)
) togetherWith fadeOut(
animationSpec = tween(150)
)
targetState = Triple(selectedUser, showSearchScreen, Unit),
transitionSpec = {
val isEnteringChat = targetState.first != null && initialState.first == null
val isExitingChat = targetState.first == null && initialState.first != null
val isEnteringSearch = targetState.second && !initialState.second
val isExitingSearch = !targetState.second && initialState.second
when {
// 🚀 Вход в чат - плавный fade
isEnteringChat -> {
fadeIn(animationSpec = tween(200)) togetherWith
fadeOut(animationSpec = tween(150))
}
// 🔙 Выход из чата - плавный fade
isExitingChat -> {
fadeIn(animationSpec = tween(200)) togetherWith
fadeOut(animationSpec = tween(150))
}
// 🔍 Вход в Search - плавный fade
isEnteringSearch -> {
fadeIn(animationSpec = tween(200)) togetherWith
fadeOut(animationSpec = tween(150))
}
// 🔙 Выход из Search - плавный fade
isEnteringSearch -> {
fadeIn(animationSpec = tween(200)) togetherWith
fadeOut(animationSpec = tween(150))
}
// 🔙 Выход из Search - плавный fade
isExitingSearch -> {
fadeIn(animationSpec = tween(200)) togetherWith
fadeOut(animationSpec = tween(150))
}
// Default - мгновенный переход
else -> {
EnterTransition.None togetherWith ExitTransition.None
}
}
// 🔙 Выход из чата - плавный fade
isExitingChat -> {
fadeIn(
animationSpec = tween(200)
) togetherWith fadeOut(
animationSpec = tween(150)
)
}
// 🔍 Вход в Search - плавный fade
isEnteringSearch -> {
fadeIn(
animationSpec = tween(200)
) togetherWith fadeOut(
animationSpec = tween(150)
)
}
// 🔙 Выход из Search - плавный fade
isEnteringSearch -> {
fadeIn(
animationSpec = tween(200)
) togetherWith fadeOut(
animationSpec = tween(150)
)
}
// 🔙 Выход из Search - плавный fade
isExitingSearch -> {
fadeIn(
animationSpec = tween(200)
) togetherWith fadeOut(
animationSpec = tween(150)
)
}
// Default - мгновенный переход
else -> {
EnterTransition.None togetherWith ExitTransition.None
}
}
},
label = "screenNavigation"
},
label = "screenNavigation"
) { (currentUser, isSearchOpen, _) ->
when {
currentUser != null -> {
// Экран чата
ChatDetailScreen(
user = currentUser,
currentUserPublicKey = accountPublicKey,
currentUserPrivateKey = accountPrivateKey,
isDarkTheme = isDarkTheme,
onBack = { selectedUser = null },
onNavigateToChat = { publicKey ->
// 📨 Forward: переход в выбранный чат
// Нужно получить SearchUser из публичного ключа
// Используем минимальные данные - остальное подгрузится в ChatDetailScreen
selectedUser = SearchUser(
title = "",
username = "",
publicKey = publicKey,
verified = 0,
online = 0
)
}
user = currentUser,
currentUserPublicKey = accountPublicKey,
currentUserPrivateKey = accountPrivateKey,
isDarkTheme = isDarkTheme,
onBack = { selectedUser = null },
onNavigateToChat = { publicKey ->
// 📨 Forward: переход в выбранный чат
// Нужно получить SearchUser из публичного ключа
// Используем минимальные данные - остальное подгрузится в
// ChatDetailScreen
selectedUser =
SearchUser(
title = "",
username = "",
publicKey = publicKey,
verified = 0,
online = 0
)
}
)
}
isSearchOpen -> {
// Экран поиска
SearchScreen(
privateKeyHash = privateKeyHash,
currentUserPublicKey = accountPublicKey,
isDarkTheme = isDarkTheme,
protocolState = protocolState,
onBackClick = { showSearchScreen = false },
onUserSelect = { selectedSearchUser ->
showSearchScreen = false
selectedUser = selectedSearchUser
}
privateKeyHash = privateKeyHash,
currentUserPublicKey = accountPublicKey,
isDarkTheme = isDarkTheme,
protocolState = protocolState,
onBackClick = { showSearchScreen = false },
onUserSelect = { selectedSearchUser ->
showSearchScreen = false
selectedUser = selectedSearchUser
}
)
}
else -> {
// Список чатов
ChatsListScreen(
isDarkTheme = isDarkTheme,
accountName = accountName,
accountPhone = accountPhone,
accountPublicKey = accountPublicKey,
accountPrivateKey = accountPrivateKey,
privateKeyHash = privateKeyHash,
onToggleTheme = onToggleTheme,
onProfileClick = {
// TODO: Navigate to profile
},
onNewGroupClick = {
// TODO: Navigate to new group
},
onContactsClick = {
// TODO: Navigate to contacts
},
onCallsClick = {
// TODO: Navigate to calls
},
onSavedMessagesClick = {
// Открываем чат с самим собой (Saved Messages)
selectedUser = SearchUser(
title = "Saved Messages",
username = "",
publicKey = accountPublicKey,
verified = 0,
online = 1
)
},
onSettingsClick = {
// TODO: Navigate to settings
},
onInviteFriendsClick = {
// TODO: Share invite link
},
onSearchClick = {
showSearchScreen = true
},
onNewChat = {
// TODO: Show new chat screen
},
onUserSelect = { selectedChatUser ->
selectedUser = selectedChatUser
},
onLogout = onLogout
isDarkTheme = isDarkTheme,
accountName = accountName,
accountPhone = accountPhone,
accountPublicKey = accountPublicKey,
accountPrivateKey = accountPrivateKey,
privateKeyHash = privateKeyHash,
onToggleTheme = onToggleTheme,
onProfileClick = {
// TODO: Navigate to profile
},
onNewGroupClick = {
// TODO: Navigate to new group
},
onContactsClick = {
// TODO: Navigate to contacts
},
onCallsClick = {
// TODO: Navigate to calls
},
onSavedMessagesClick = {
// Открываем чат с самим собой (Saved Messages)
selectedUser =
SearchUser(
title = "Saved Messages",
username = "",
publicKey = accountPublicKey,
verified = 0,
online = 1
)
},
onSettingsClick = {
// TODO: Navigate to settings
},
onInviteFriendsClick = {
// TODO: Share invite link
},
onSearchClick = { showSearchScreen = true },
onNewChat = {
// TODO: Show new chat screen
},
onUserSelect = { selectedChatUser -> selectedUser = selectedChatUser },
onLogout = onLogout
)
}
}
}
}