package navigation import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import auth.presentation.LoginScreen import auth.presentation.RegisterScreen import auth.presentation.AuthViewModel import core.presentation.settings.SettingsScreen import core.presentation.settings.SettingsViewModel import chats.presentation.chat_list.ChatListScreen import chats.presentation.chat_list.ChatListViewModel import chats.presentation.chat_detail.ChatDetailScreen import chats.presentation.chat_detail.ChatDetailViewModel import contacts.presentation.ContactListScreen import contacts.presentation.ContactListViewModel import core.presentation.components.GlassNavigationBar import profiles.presentation.ProfileScreen import profiles.presentation.EditProfileScreen import profiles.presentation.viewmodel.ProfileViewModel import stories.presentation.StoryViewModel sealed class Screen(val route: String) { object Login : Screen("login") object Register : Screen("register") object ChatList : Screen("chat_list") object ChatDetail : Screen("chat_detail/{chatId}/{chatName}") { fun createRoute(chatId: String, chatName: String) = "chat_detail/$chatId/$chatName" } object Profile : Screen("profile?profileId={profileId}") { fun createRoute(profileId: String? = null) = if (profileId != null) "profile?profileId=$profileId" else "profile" } object EditProfile : Screen("edit_profile") object Settings : Screen("settings") object Contacts : Screen("contacts") } @Composable fun AppNavigation( navController: NavHostController = rememberNavController(), navigationManager: core.utils.NavigationManager? = null ) { val authViewModel: AuthViewModel = hiltViewModel() val authState by authViewModel.state.collectAsState() val startDestination = if (authState.isAuthenticated) Screen.ChatList.route else Screen.Login.route androidx.compose.runtime.LaunchedEffect(navigationManager) { navigationManager?.events?.collect { event -> when (event) { is core.utils.NavEvent.OpenChat -> { if (authState.isAuthenticated) { navController.navigate(Screen.ChatDetail.createRoute(event.chatId, "Chat")) { launchSingleTop = true } } } core.utils.NavEvent.Logout -> { navController.navigate(Screen.Login.route) { popUpTo(0) { inclusive = true } } } } } } val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route // Определяем, нужно ли показывать нижнюю панель val showBottomBar = currentRoute in listOf( Screen.ChatList.route, Screen.Contacts.route, Screen.Settings.route, Screen.Profile.route ) val profileViewModel: ProfileViewModel = hiltViewModel() val profileState by profileViewModel.state.collectAsState() androidx.compose.runtime.LaunchedEffect(authState.isAuthenticated) { if (authState.isAuthenticated) { profileViewModel.loadProfile() } } Scaffold( bottomBar = { if (showBottomBar) { GlassNavigationBar( currentRoute = currentRoute ?: "", onNavigate = { route -> navController.navigate(route) { popUpTo(Screen.ChatList.route) { saveState = true } launchSingleTop = true restoreState = true } }, userAvatarUrl = profileState.profile?.avatarUrl, username = profileState.profile?.displayName ?: profileState.profile?.username ?: "" ) } } ) { paddingValues -> Box(modifier = Modifier.padding(if (showBottomBar) paddingValues else PaddingValues(0.dp))) { NavHost( navController = navController, startDestination = startDestination ) { composable(Screen.Login.route) { val viewModel: AuthViewModel = hiltViewModel() LoginScreen( viewModel = viewModel, onNavigateToRegister = { navController.navigate(Screen.Register.route) }, onNavigateToSettings = { navController.navigate(Screen.Settings.route) }, onLoginSuccess = { navController.navigate(Screen.ChatList.route) { popUpTo(Screen.Login.route) { inclusive = true } } } ) } composable(Screen.Register.route) { val viewModel: AuthViewModel = hiltViewModel() RegisterScreen( viewModel = viewModel, onNavigateToLogin = { navController.popBackStack() }, onRegisterSuccess = { navController.navigate(Screen.ChatList.route) { popUpTo(Screen.Login.route) { inclusive = true } } } ) } composable(Screen.ChatList.route) { val viewModel: ChatListViewModel = hiltViewModel() val storyViewModel: StoryViewModel = hiltViewModel() ChatListScreen( viewModel = viewModel, storyViewModel = storyViewModel, onChatClick = { chatId -> navController.navigate(Screen.ChatDetail.createRoute(chatId, "Chat")) }, onStoryClick = { /* Story click logic */ } ) } composable( route = Screen.ChatDetail.route, arguments = listOf( navArgument("chatId") { type = NavType.StringType }, navArgument("chatName") { type = NavType.StringType } ) ) { backStackEntry -> val chatId = backStackEntry.arguments?.getString("chatId") ?: "" val chatName = backStackEntry.arguments?.getString("chatName") ?: "Chat" val viewModel: ChatDetailViewModel = hiltViewModel() ChatDetailScreen( chatId = chatId, chatName = chatName, viewModel = viewModel, onBack = { navController.popBackStack() } ) } composable(Screen.Contacts.route) { val viewModel: ContactListViewModel = hiltViewModel() val state by viewModel.state.collectAsState() ContactListScreen( contacts = state.contacts, requests = state.requests, isLoading = state.isLoading, onContactClick = { id -> navController.navigate(Screen.Profile.createRoute(id)) }, onSearchChange = { viewModel.onSearchChange(it) }, onAddContact = { id -> viewModel.addContact(id) }, onStartChat = { id -> viewModel.startChat(id) }, onAcceptRequest = { id -> viewModel.acceptRequest(id) }, onDeclineRequest = { id -> viewModel.declineRequest(id) } ) } composable( route = Screen.Profile.route, arguments = listOf( navArgument("profileId") { type = NavType.StringType nullable = true } ) ) { backStackEntry -> val profileId = backStackEntry.arguments?.getString("profileId") val viewModel: ProfileViewModel = hiltViewModel() ProfileScreen( profileId = profileId, viewModel = viewModel, onEditProfile = { navController.navigate(Screen.EditProfile.route) }, onBack = { navController.popBackStack() }, onSendMessage = { id -> navController.navigate(Screen.ChatDetail.createRoute(id, "Chat")) } ) } composable(Screen.EditProfile.route) { // Используем ViewModel от предыдущего экрана (Profile), чтобы данные не терялись val profileEntry = remember(it) { navController.getBackStackEntry(Screen.Profile.route) } val viewModel: ProfileViewModel = hiltViewModel(profileEntry) val state by viewModel.state.collectAsState() // Получаем profileId из родительского backStackEntry val profileId = profileEntry.arguments?.getString("profileId") androidx.compose.runtime.LaunchedEffect(state.profile) { // Если профиль загружен (или обновился), мы можем инициализировать/обновить поля } val isSaving = state.isSaving val error = state.error // Автоматически возвращаемся назад после успешного сохранения var wasSaving by remember { mutableStateOf(false) } androidx.compose.runtime.LaunchedEffect(isSaving) { if (isSaving) wasSaving = true if (wasSaving && !isSaving && error == null) { // Перезагружаем профиль перед возвратом viewModel.loadProfile(profileId) // Небольшая задержка чтобы данные обновились kotlinx.coroutines.delay(300) navController.popBackStack() } } EditProfileScreen( currentDisplayName = state.profile?.displayName, currentUsername = state.profile?.username ?: "", currentBio = state.profile?.bio, currentBirthday = state.profile?.birthday, currentAvatarUrl = state.profile?.avatarUrl, isSaving = isSaving, error = error, onSave = { name, bio, birthday, uri -> viewModel.updateProfile(name, bio, birthday, uri) }, onBack = { navController.popBackStack() } ) } composable(Screen.Settings.route) { val viewModel: SettingsViewModel = hiltViewModel() SettingsScreen( viewModel = viewModel, onBack = { navController.popBackStack() }, onLogout = { navController.navigate(Screen.Login.route) { popUpTo(0) { inclusive = true } } } ) } } } } }