package com.shaarit.presentation.nav import android.app.Activity import android.content.Intent import android.net.Uri import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.core.net.toUri import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import androidx.navigation.navDeepLink import java.net.URLEncoder sealed class Screen(val route: String) { object Login : Screen("login") object Feed : Screen("feed?tag={tag}&collectionId={collectionId}") { fun createRoute(tag: String? = null, collectionId: Long? = null): String { val params = mutableListOf() if (tag != null) { val encoded = URLEncoder.encode(tag, "UTF-8") params.add("tag=$encoded") } if (collectionId != null) { params.add("collectionId=$collectionId") } return if (params.isEmpty()) { "feed" } else { "feed?" + params.joinToString("&") } } } object Add : Screen("add?url={url}&title={title}&isShare={isShare}") object Edit : Screen("edit/{linkId}") { fun createRoute(linkId: Int): String = "edit/$linkId" } object Tags : Screen("tags") object Collections : Screen("collections") object Dashboard : Screen("dashboard") object Settings : Screen("settings") object Help : Screen("help") object DeadLinks : Screen("dead_links") object Pinned : Screen("pinned") object Reader : Screen("reader/{linkId}") { fun createRoute(linkId: Int): String = "reader/$linkId" } object Reminders : Screen("reminders") object Todo : Screen("todo") object TodoDetail : Screen("todoDetail/{linkId}") { fun createRoute(linkId: Int): String = "todoDetail/$linkId" } } @Composable fun AppNavGraph( startDestination: String = Screen.Login.route, shareUrl: String? = null, shareTitle: String? = null, shareDescription: String? = null, shareTags: List? = null, isFileShare: Boolean = false, initialDeepLink: String? = null, onPlayAudio: ((com.shaarit.domain.model.ShaarliLink) -> Unit)? = null ) { val navController = rememberNavController() val context = LocalContext.current // If user is already logged in and has share data, navigate directly to Add screen val hasShareData = shareUrl != null || (isFileShare && shareTitle != null) androidx.compose.runtime.LaunchedEffect(hasShareData) { if (hasShareData && startDestination != Screen.Login.route) { val route = if (isFileShare && shareTitle != null) { val encodedTitle = URLEncoder.encode(shareTitle, "UTF-8") val encodedDesc = if (shareDescription != null) URLEncoder.encode(shareDescription, "UTF-8") else "" val encodedTags = shareTags?.joinToString(",") { URLEncoder.encode(it, "UTF-8") } ?: "" "add?url=&title=$encodedTitle&isShare=true&isFileShare=true&description=$encodedDesc&tags=$encodedTags" } else if (shareUrl != null) { val encodedUrl = URLEncoder.encode(shareUrl, "UTF-8") val encodedTitle = if (shareTitle != null) URLEncoder.encode(shareTitle, "UTF-8") else "" "add?url=$encodedUrl&title=$encodedTitle&isShare=true&isFileShare=false&description=&tags=" } else null route?.let { navController.navigate(it) { popUpTo(startDestination) { inclusive = true } } } } } NavHost(navController = navController, startDestination = startDestination) { composable(Screen.Login.route) { com.shaarit.presentation.auth.LoginScreen( onLoginSuccess = { if (isFileShare && shareTitle != null) { // File share - navigate to add screen with file data val encodedTitle = URLEncoder.encode(shareTitle, "UTF-8") val encodedDesc = if (shareDescription != null) URLEncoder.encode(shareDescription, "UTF-8") else "" val encodedTags = shareTags?.joinToString(",") { URLEncoder.encode(it, "UTF-8") } ?: "" navController.navigate("add?url=&title=$encodedTitle&isShare=true&isFileShare=true&description=$encodedDesc&tags=$encodedTags") { popUpTo(Screen.Login.route) { inclusive = true } } } else if (shareUrl != null) { // Use proper URL encoding that handles spaces correctly val encodedUrl = URLEncoder.encode(shareUrl, "UTF-8") val encodedTitle = if (shareTitle != null) { URLEncoder.encode(shareTitle, "UTF-8") } else "" navController.navigate("add?url=$encodedUrl&title=$encodedTitle&isShare=true&isFileShare=false&description=&tags=") { popUpTo(Screen.Login.route) { inclusive = true } } } else if (initialDeepLink != null) { // Handle deep link after login navController.navigate(initialDeepLink) { popUpTo(Screen.Login.route) { inclusive = true } } } else { navController.navigate(Screen.Feed.createRoute()) { popUpTo(Screen.Login.route) { inclusive = true } } } } ) } composable( route = "feed?tag={tag}&collectionId={collectionId}", arguments = listOf( navArgument("tag") { type = NavType.StringType nullable = true defaultValue = null }, navArgument("collectionId") { type = NavType.LongType nullable = false defaultValue = -1L } ), deepLinks = listOf( navDeepLink { uriPattern = "shaarit://feed" }, navDeepLink { uriPattern = "shaarit://search" } ) ) { backStackEntry -> val tag = backStackEntry.arguments?.getString("tag") val collectionId = backStackEntry.arguments ?.getLong("collectionId") ?.takeIf { it != -1L } com.shaarit.presentation.feed.FeedScreen( onNavigateToAdd = { navController.navigate("add?url=&title=&isShare=false") }, onNavigateToEdit = { linkId -> navController.navigate(Screen.Edit.createRoute(linkId)) }, onNavigateToTags = { navController.navigate(Screen.Tags.route) }, onNavigateToCollections = { navController.navigate(Screen.Collections.route) }, onNavigateToSettings = { navController.navigate(Screen.Settings.route) }, onNavigateToHelp = { navController.navigate(Screen.Help.route) }, onNavigateToDeadLinks = { navController.navigate(Screen.DeadLinks.route) }, onNavigateToPinned = { navController.navigate(Screen.Pinned.route) }, onNavigateToReader = { linkId -> navController.navigate(Screen.Reader.createRoute(linkId)) }, onNavigateToReminders = { navController.navigate(Screen.Reminders.route) }, onNavigateToTodo = { navController.navigate(Screen.Todo.route) }, onNavigateToTodoDetail = { linkId -> navController.navigate(Screen.TodoDetail.createRoute(linkId)) }, onPlayAudio = onPlayAudio, initialTagFilter = tag, initialCollectionId = collectionId ) } composable( route = "add?url={url}&title={title}&isShare={isShare}&isFileShare={isFileShare}&description={description}&tags={tags}", arguments = listOf( navArgument("url") { type = NavType.StringType defaultValue = "" nullable = true }, navArgument("title") { type = NavType.StringType defaultValue = "" nullable = true }, navArgument("isShare") { type = NavType.BoolType defaultValue = false }, navArgument("isFileShare") { type = NavType.BoolType defaultValue = false }, navArgument("description") { type = NavType.StringType defaultValue = "" nullable = true }, navArgument("tags") { type = NavType.StringType defaultValue = "" nullable = true } ), deepLinks = listOf( navDeepLink { uriPattern = "shaarit://add" } ) ) { backStackEntry -> val isShare = backStackEntry.arguments?.getBoolean("isShare") ?: false com.shaarit.presentation.add.AddLinkScreen( onNavigateBack = { navController.popBackStack() }, onShareSuccess = if (isShare) { { (context as? Activity)?.finish() } } else null ) } composable( route = "edit/{linkId}", arguments = listOf( navArgument("linkId") { type = NavType.IntType } ) ) { com.shaarit.presentation.edit.EditLinkScreen( onNavigateBack = { navController.popBackStack() } ) } composable( route = Screen.Tags.route, deepLinks = listOf( navDeepLink { uriPattern = "shaarit://tags" } ) ) { com.shaarit.presentation.tags.TagsScreen( onNavigateBack = { navController.popBackStack() }, onNavigateToFeedWithTag = { tag -> navController.navigate(Screen.Feed.createRoute(tag)) { popUpTo(Screen.Tags.route) { inclusive = true } } } ) } composable( route = Screen.Collections.route, deepLinks = listOf( navDeepLink { uriPattern = "shaarit://collections" } ) ) { com.shaarit.presentation.collections.CollectionsScreen( onNavigateBack = { navController.popBackStack() }, onCollectionClick = { collectionId, isSmart, query -> navController.navigate( if (isSmart) { Screen.Feed.createRoute(tag = query) } else { Screen.Feed.createRoute(collectionId = collectionId) } ) { popUpTo(Screen.Collections.route) { inclusive = true } } } ) } composable( route = Screen.Dashboard.route, deepLinks = listOf( navDeepLink { uriPattern = "shaarit://dashboard" } ) ) { com.shaarit.presentation.dashboard.DashboardScreen( onNavigateBack = { navController.popBackStack() } ) } composable( route = Screen.Settings.route ) { com.shaarit.presentation.settings.SettingsScreen( onNavigateBack = { navController.popBackStack() }, onNavigateToDashboard = { navController.navigate(Screen.Dashboard.route) } ) } composable( route = Screen.Help.route, deepLinks = listOf( navDeepLink { uriPattern = "shaarit://help" } ) ) { com.shaarit.presentation.help.HelpScreen( onNavigateBack = { navController.popBackStack() } ) } composable( route = Screen.DeadLinks.route ) { com.shaarit.presentation.deadlinks.DeadLinksScreen( onNavigateBack = { navController.popBackStack() }, onNavigateToEdit = { linkId -> navController.navigate(Screen.Edit.createRoute(linkId)) } ) } composable( route = Screen.Pinned.route ) { com.shaarit.presentation.pinned.PinnedScreen( onNavigateBack = { navController.popBackStack() }, onNavigateToEdit = { linkId -> navController.navigate(Screen.Edit.createRoute(linkId)) } ) } composable( route = "reader/{linkId}", arguments = listOf( navArgument("linkId") { type = NavType.IntType } ), deepLinks = listOf( navDeepLink { uriPattern = "shaarit://reader/{linkId}" } ) ) { com.shaarit.presentation.reader.ReaderModeScreen( onNavigateBack = { navController.popBackStack() } ) } composable( route = Screen.Reminders.route ) { com.shaarit.presentation.reminders.RemindersScreen( onNavigateBack = { navController.popBackStack() }, onNavigateToReader = { linkId -> navController.navigate(Screen.Reader.createRoute(linkId)) } ) } composable( route = Screen.Todo.route, deepLinks = listOf( navDeepLink { uriPattern = "shaarit://todo" } ) ) { com.shaarit.presentation.todo.TodoScreen( onNavigateBack = { navController.popBackStack() } ) } composable( route = Screen.TodoDetail.route, arguments = listOf( navArgument("linkId") { type = NavType.IntType } ) ) { backStackEntry -> val linkId = backStackEntry.arguments?.getInt("linkId") ?: 0 com.shaarit.presentation.todo.TodoDetailScreen( linkId = linkId, onNavigateBack = { navController.popBackStack() } ) } } }