Files
rider-pro-android-app/app/src/main/java/com/aiosman/ravenow/ui/Navi.kt

701 lines
26 KiB
Kotlin
Raw Normal View History

2024-11-17 20:07:42 +08:00
package com.aiosman.ravenow.ui
2024-07-23 15:25:00 +08:00
2024-08-13 22:32:27 +08:00
import ChangePasswordScreen
2024-08-03 15:58:19 +08:00
import ImageViewer
2024-07-23 15:25:00 +08:00
import ModificationListScreen
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
2024-08-24 21:59:16 +08:00
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.FastOutSlowInEasing
2024-08-24 21:59:16 +08:00
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
2024-07-23 15:25:00 +08:00
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
2024-09-05 22:04:41 +08:00
import androidx.compose.runtime.LaunchedEffect
2024-07-23 15:25:00 +08:00
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
2024-11-17 20:07:42 +08:00
import com.aiosman.ravenow.LocalAnimatedContentScope
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.LocalSharedTransitionScope
2024-12-07 17:14:45 +08:00
import com.aiosman.ravenow.ui.about.AboutScreen
2024-11-17 20:07:42 +08:00
import com.aiosman.ravenow.ui.account.AccountEditScreen2
2024-12-07 17:14:45 +08:00
import com.aiosman.ravenow.ui.account.AccountSetting
2025-08-28 14:30:47 +08:00
import com.aiosman.ravenow.ui.account.RemoveAccountScreen
2024-11-17 20:07:42 +08:00
import com.aiosman.ravenow.ui.account.ResetPasswordScreen
import com.aiosman.ravenow.ui.agent.AddAgentScreen
import com.aiosman.ravenow.ui.agent.AgentImageCropScreen
import com.aiosman.ravenow.ui.group.CreateGroupChatScreen
2025-08-07 19:03:05 +08:00
import com.aiosman.ravenow.ui.chat.ChatAiScreen
import com.aiosman.ravenow.ui.chat.ChatSettingScreen
2024-11-17 20:07:42 +08:00
import com.aiosman.ravenow.ui.chat.ChatScreen
2025-08-18 19:02:11 +08:00
import com.aiosman.ravenow.ui.chat.GroupChatScreen
2024-11-17 20:07:42 +08:00
import com.aiosman.ravenow.ui.comment.CommentsScreen
import com.aiosman.ravenow.ui.comment.notice.CommentNoticeScreen
import com.aiosman.ravenow.ui.composables.AgentCreatedSuccessIndicator
2024-11-17 20:07:42 +08:00
import com.aiosman.ravenow.ui.crop.ImageCropScreen
import com.aiosman.ravenow.ui.favourite.FavouriteListPage
import com.aiosman.ravenow.ui.favourite.FavouriteNoticeScreen
import com.aiosman.ravenow.ui.follower.FollowerListScreen
import com.aiosman.ravenow.ui.follower.FollowerNoticeScreen
import com.aiosman.ravenow.ui.follower.FollowingListScreen
import com.aiosman.ravenow.ui.gallery.OfficialGalleryScreen
import com.aiosman.ravenow.ui.gallery.OfficialPhotographerScreen
import com.aiosman.ravenow.ui.gallery.ProfileTimelineScreen
2025-08-25 10:49:00 +08:00
import com.aiosman.ravenow.ui.group.GroupChatInfoScreen
2024-11-17 20:07:42 +08:00
import com.aiosman.ravenow.ui.index.IndexScreen
import com.aiosman.ravenow.ui.index.tabs.message.NotificationsScreen
import com.aiosman.ravenow.ui.index.tabs.search.SearchScreen
import com.aiosman.ravenow.ui.like.LikeNoticeScreen
import com.aiosman.ravenow.ui.location.LocationDetailScreen
import com.aiosman.ravenow.ui.login.EmailSignupScreen
import com.aiosman.ravenow.ui.login.LoginPage
import com.aiosman.ravenow.ui.login.SignupScreen
import com.aiosman.ravenow.ui.login.UserAuthScreen
import com.aiosman.ravenow.ui.modification.EditModificationScreen
import com.aiosman.ravenow.ui.post.NewPostImageGridScreen
import com.aiosman.ravenow.ui.post.NewPostScreen
import com.aiosman.ravenow.ui.post.PostScreen
import com.aiosman.ravenow.ui.profile.AccountProfileV2
import com.aiosman.ravenow.ui.index.tabs.profile.vip.VipSelPage
import com.aiosman.ravenow.ui.notification.NotificationScreen
2024-07-23 15:25:00 +08:00
sealed class NavigationRoute(
val route: String,
) {
data object Index : NavigationRoute("Index")
data object ProfileTimeline : NavigationRoute("ProfileTimeline")
data object LocationDetail : NavigationRoute("LocationDetail/{x}/{y}")
data object OfficialPhoto : NavigationRoute("OfficialPhoto")
data object OfficialPhotographer : NavigationRoute("OfficialPhotographer")
2024-09-22 15:35:42 +08:00
data object Post : NavigationRoute("Post/{id}/{highlightCommentId}/{initImagePagerIndex}")
2024-07-23 15:25:00 +08:00
data object ModificationList : NavigationRoute("ModificationList")
data object MyMessage : NavigationRoute("MyMessage")
data object Comments : NavigationRoute("Comments")
data object Likes : NavigationRoute("Likes")
data object Followers : NavigationRoute("Followers")
data object NewPost : NavigationRoute("NewPost")
data object EditModification : NavigationRoute("EditModification")
2024-07-29 00:01:09 +08:00
data object Login : NavigationRoute("Login")
Enhance AI Agent Profile Interaction This commit introduces several enhancements to how AI agent profiles are displayed and interacted with: **Profile Display:** - **AI Account Distinction:** Profile pages now differentiate between regular user accounts and AI agent accounts. - AI agent profiles will not display the "Agents" tab in their profile. - The profile header height is adjusted for AI accounts. - **Navigation Parameter:** An `isAiAccount` boolean parameter is added to the `AccountProfile` navigation route to indicate if the profile being viewed belongs to an AI. **Interaction & Navigation:** - **Avatar Click Navigation:** - Clicking an AI agent's avatar in various lists (Hot Agents, My Agents, User Agents Row, User Agents List) now navigates to the agent's dedicated profile page. - When navigating to an agent's profile from an agent list, `isAiAccount` is set to `true`. - **Chat Initiation:** Clicking the chat button on AI agent cards in the "Agent" tab (both Hot and My Agents) now correctly initiates a chat with the respective AI. - **ViewModel Updates:** - `AgentViewModel`, `MineAgentViewModel`, and `HotAgentViewModel` now include a `goToProfile` function to handle navigation to agent profiles, correctly passing the `isAiAccount` flag. **Code Refinements:** - Click handlers for agent avatars and chat buttons are now wrapped with `DebounceUtils.simpleDebounceClick` to prevent multiple rapid clicks. - The `UserContentPageIndicator` now conditionally hides the "Agent" tab based on the `isAiAccount` status. - `UserAgentsRow` and `UserAgentsList` now accept an `onAvatarClick` callback for navigating to agent profiles. - `AgentItem` (used in `UserAgentsRow`) and `UserAgentCard` (used in `UserAgentsList`) now handle avatar clicks. - The general `Agent` composable (used in `AiPostComposable`) now also supports an `onAvatarClick` callback.
2025-09-01 01:10:35 +08:00
data object AccountProfile : NavigationRoute("AccountProfile/{id}?isAiAccount={isAiAccount}")
2024-07-30 09:04:07 +08:00
data object SignUp : NavigationRoute("SignUp")
data object UserAuth : NavigationRoute("UserAuth")
data object EmailSignUp : NavigationRoute("EmailSignUp")
2024-07-31 14:50:55 +08:00
data object AccountEdit : NavigationRoute("AccountEditScreen")
2024-08-03 15:58:19 +08:00
data object ImageViewer : NavigationRoute("ImageViewer")
2024-08-13 22:32:27 +08:00
data object ChangePasswordScreen : NavigationRoute("ChangePasswordScreen")
2024-08-20 19:48:12 +08:00
data object FavouritesScreen : NavigationRoute("FavouritesScreen")
2024-08-24 17:57:04 +08:00
data object NewPostImageGrid : NavigationRoute("NewPostImageGrid")
data object Search : NavigationRoute("Search")
data object FollowerList : NavigationRoute("FollowerList/{id}")
data object FollowingList : NavigationRoute("FollowingList/{id}")
2024-09-12 23:13:11 +08:00
data object ResetPassword : NavigationRoute("ResetPassword")
2024-09-13 23:20:38 +08:00
data object FavouriteList : NavigationRoute("FavouriteList")
2024-09-23 23:47:16 +08:00
data object Chat : NavigationRoute("Chat/{id}")
2025-08-07 19:03:05 +08:00
data object ChatAi : NavigationRoute("ChatAi/{id}")
data object ChatSetting : NavigationRoute("ChatSetting")
2025-08-20 19:19:14 +08:00
data object ChatGroup : NavigationRoute("ChatGroup/{id}/{name}/{avatar}")
2024-09-27 21:29:30 +08:00
data object CommentNoticeScreen : NavigationRoute("CommentNoticeScreen")
2024-10-09 15:33:08 +08:00
data object ImageCrop : NavigationRoute("ImageCrop")
data object AgentImageCrop : NavigationRoute("AgentImageCrop")
2024-12-07 17:14:45 +08:00
data object AccountSetting : NavigationRoute("AccountSetting")
data object AboutScreen : NavigationRoute("AboutScreen")
data object AddAgent : NavigationRoute("AddAgent")
data object CreateGroupChat : NavigationRoute("CreateGroupChat")
2025-08-25 10:49:00 +08:00
data object GroupInfo : NavigationRoute("GroupInfo/{id}")
data object VipSelPage : NavigationRoute("VipSelPage")
2025-08-28 14:30:47 +08:00
data object RemoveAccountScreen: NavigationRoute("RemoveAccount")
data object NotificationScreen : NavigationRoute("NotificationScreen")
2024-07-23 15:25:00 +08:00
}
@Composable
2024-07-31 14:50:55 +08:00
fun NavigationController(
navController: NavHostController,
startDestination: String = NavigationRoute.Login.route
) {
2024-07-23 15:25:00 +08:00
val navigationBarHeight = with(LocalDensity.current) {
WindowInsets.navigationBars.getBottom(this).toDp()
}
NavHost(
navController = navController,
2024-07-30 16:57:25 +08:00
startDestination = startDestination,
2024-07-23 15:25:00 +08:00
) {
composable(route = NavigationRoute.Index.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
IndexScreen()
}
}
composable(route = NavigationRoute.ProfileTimeline.route) {
ProfileTimelineScreen()
}
composable(
route = NavigationRoute.LocationDetail.route,
arguments = listOf(
navArgument("x") { type = NavType.FloatType },
navArgument("y") { type = NavType.FloatType }
)
) {
Box(
modifier = Modifier.padding(bottom = navigationBarHeight)
) {
val x = it.arguments?.getFloat("x") ?: 0f
val y = it.arguments?.getFloat("y") ?: 0f
LocationDetailScreen(
x, y
)
}
}
composable(route = NavigationRoute.OfficialPhoto.route) {
OfficialGalleryScreen()
}
composable(route = NavigationRoute.OfficialPhotographer.route) {
OfficialPhotographerScreen()
}
composable(
route = NavigationRoute.Post.route,
2024-09-20 17:10:54 +08:00
arguments = listOf(
navArgument("id") { type = NavType.StringType },
2024-09-22 15:35:42 +08:00
navArgument("highlightCommentId") { type = NavType.IntType },
navArgument("initImagePagerIndex") { type = NavType.IntType }
2024-09-20 17:10:54 +08:00
),
2024-10-27 11:31:27 +08:00
enterTransition = {
// iOS push: new screen slides in from the right
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(durationMillis = 280)
)
2024-10-27 11:31:27 +08:00
},
exitTransition = {
// iOS push: previous screen shifts slightly left (parallax)
slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth / 3 },
animationSpec = tween(durationMillis = 280)
)
2024-10-27 11:31:27 +08:00
},
popEnterTransition = {
// iOS pop: previous screen slides back from slight left offset
slideInHorizontally(
initialOffsetX = { fullWidth -> -fullWidth / 3 },
animationSpec = tween(durationMillis = 280)
)
2024-10-27 11:31:27 +08:00
},
popExitTransition = {
// iOS pop: current screen slides out to the right
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(durationMillis = 280)
)
2024-07-23 15:25:00 +08:00
}
2024-10-27 11:31:27 +08:00
) { backStackEntry ->
val id = backStackEntry.arguments?.getString("id")
val highlightCommentId =
backStackEntry.arguments?.getInt("highlightCommentId")?.let {
if (it == 0) null else it
}
val initIndex = backStackEntry.arguments?.getInt("initImagePagerIndex")
PostScreen(
id!!,
highlightCommentId,
initImagePagerIndex = initIndex
)
2024-07-23 15:25:00 +08:00
}
2024-10-27 11:31:27 +08:00
2024-09-12 21:47:00 +08:00
composable(route = NavigationRoute.ModificationList.route,
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 0))
}
) {
2024-07-23 15:25:00 +08:00
ModificationListScreen()
}
2024-09-12 21:47:00 +08:00
composable(route = NavigationRoute.MyMessage.route,
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 0))
}
) {
2024-07-23 15:25:00 +08:00
NotificationsScreen()
}
2024-09-12 21:47:00 +08:00
composable(route = NavigationRoute.Comments.route,
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 0))
}
) {
2024-07-23 15:25:00 +08:00
CommentsScreen()
}
2024-09-12 21:47:00 +08:00
composable(route = NavigationRoute.Likes.route,
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 0))
}
) {
LikeNoticeScreen()
2024-07-23 15:25:00 +08:00
}
2024-09-12 21:47:00 +08:00
composable(route = NavigationRoute.Followers.route,
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 0))
}
) {
FollowerNoticeScreen()
2024-07-23 15:25:00 +08:00
}
2024-08-24 21:59:16 +08:00
composable(
route = NavigationRoute.NewPost.route,
2024-09-12 21:47:00 +08:00
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 0))
}
2024-08-24 21:59:16 +08:00
) {
2024-07-23 15:25:00 +08:00
NewPostScreen()
}
composable(route = NavigationRoute.EditModification.route) {
Box(
modifier = Modifier.padding(top = 64.dp)
) {
EditModificationScreen()
}
}
2024-07-29 00:01:09 +08:00
composable(route = NavigationRoute.Login.route) {
LoginPage()
}
composable(
route = NavigationRoute.AccountProfile.route,
Enhance AI Agent Profile Interaction This commit introduces several enhancements to how AI agent profiles are displayed and interacted with: **Profile Display:** - **AI Account Distinction:** Profile pages now differentiate between regular user accounts and AI agent accounts. - AI agent profiles will not display the "Agents" tab in their profile. - The profile header height is adjusted for AI accounts. - **Navigation Parameter:** An `isAiAccount` boolean parameter is added to the `AccountProfile` navigation route to indicate if the profile being viewed belongs to an AI. **Interaction & Navigation:** - **Avatar Click Navigation:** - Clicking an AI agent's avatar in various lists (Hot Agents, My Agents, User Agents Row, User Agents List) now navigates to the agent's dedicated profile page. - When navigating to an agent's profile from an agent list, `isAiAccount` is set to `true`. - **Chat Initiation:** Clicking the chat button on AI agent cards in the "Agent" tab (both Hot and My Agents) now correctly initiates a chat with the respective AI. - **ViewModel Updates:** - `AgentViewModel`, `MineAgentViewModel`, and `HotAgentViewModel` now include a `goToProfile` function to handle navigation to agent profiles, correctly passing the `isAiAccount` flag. **Code Refinements:** - Click handlers for agent avatars and chat buttons are now wrapped with `DebounceUtils.simpleDebounceClick` to prevent multiple rapid clicks. - The `UserContentPageIndicator` now conditionally hides the "Agent" tab based on the `isAiAccount` status. - `UserAgentsRow` and `UserAgentsList` now accept an `onAvatarClick` callback for navigating to agent profiles. - `AgentItem` (used in `UserAgentsRow`) and `UserAgentCard` (used in `UserAgentsList`) now handle avatar clicks. - The general `Agent` composable (used in `AiPostComposable`) now also supports an `onAvatarClick` callback.
2025-09-01 01:10:35 +08:00
arguments = listOf(
navArgument("id") { type = NavType.StringType },
navArgument("isAiAccount") {
type = NavType.BoolType
defaultValue = false
}
),
2025-08-31 23:26:13 +08:00
enterTransition = {
// iOS push: new screen slides in from the right
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(durationMillis = 280)
)
},
exitTransition = {
// iOS push: previous screen shifts slightly left (parallax)
slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth / 3 },
animationSpec = tween(durationMillis = 280)
)
},
popEnterTransition = {
// iOS pop: previous screen slides back from slight left offset
slideInHorizontally(
initialOffsetX = { fullWidth -> -fullWidth / 3 },
animationSpec = tween(durationMillis = 280)
)
},
popExitTransition = {
// iOS pop: current screen slides out to the right
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(durationMillis = 280)
)
}
2024-07-29 00:01:09 +08:00
) {
2024-08-11 17:15:17 +08:00
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
Enhance AI Agent Profile Interaction This commit introduces several enhancements to how AI agent profiles are displayed and interacted with: **Profile Display:** - **AI Account Distinction:** Profile pages now differentiate between regular user accounts and AI agent accounts. - AI agent profiles will not display the "Agents" tab in their profile. - The profile header height is adjusted for AI accounts. - **Navigation Parameter:** An `isAiAccount` boolean parameter is added to the `AccountProfile` navigation route to indicate if the profile being viewed belongs to an AI. **Interaction & Navigation:** - **Avatar Click Navigation:** - Clicking an AI agent's avatar in various lists (Hot Agents, My Agents, User Agents Row, User Agents List) now navigates to the agent's dedicated profile page. - When navigating to an agent's profile from an agent list, `isAiAccount` is set to `true`. - **Chat Initiation:** Clicking the chat button on AI agent cards in the "Agent" tab (both Hot and My Agents) now correctly initiates a chat with the respective AI. - **ViewModel Updates:** - `AgentViewModel`, `MineAgentViewModel`, and `HotAgentViewModel` now include a `goToProfile` function to handle navigation to agent profiles, correctly passing the `isAiAccount` flag. **Code Refinements:** - Click handlers for agent avatars and chat buttons are now wrapped with `DebounceUtils.simpleDebounceClick` to prevent multiple rapid clicks. - The `UserContentPageIndicator` now conditionally hides the "Agent" tab based on the `isAiAccount` status. - `UserAgentsRow` and `UserAgentsList` now accept an `onAvatarClick` callback for navigating to agent profiles. - `AgentItem` (used in `UserAgentsRow`) and `UserAgentCard` (used in `UserAgentsList`) now handle avatar clicks. - The general `Agent` composable (used in `AiPostComposable`) now also supports an `onAvatarClick` callback.
2025-09-01 01:10:35 +08:00
val id = it.arguments?.getString("id")!!
val isAiAccount = it.arguments?.getBoolean("isAiAccount") ?: false
AccountProfileV2(id, isAiAccount)
2024-08-11 17:15:17 +08:00
}
2024-07-29 00:01:09 +08:00
}
composable(
route = NavigationRoute.SignUp.route,
enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 0))
}
) {
2024-07-30 09:04:07 +08:00
SignupScreen()
}
composable(
route = NavigationRoute.UserAuth.route,
enterTransition = {
2024-09-12 21:47:00 +08:00
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
2024-09-12 21:47:00 +08:00
fadeOut(animationSpec = tween(durationMillis = 0))
}
) {
2024-07-30 09:04:07 +08:00
UserAuthScreen()
}
composable(
route = NavigationRoute.EmailSignUp.route,
enterTransition = {
2024-09-12 21:47:00 +08:00
fadeIn(animationSpec = tween(durationMillis = 0))
},
exitTransition = {
2024-09-12 21:47:00 +08:00
fadeOut(animationSpec = tween(durationMillis = 0))
}
) {
2024-07-30 09:04:07 +08:00
EmailSignupScreen()
}
2024-09-12 21:47:00 +08:00
composable(
route = NavigationRoute.AccountEdit.route,
enterTransition = {
// iOS风格从底部向上滑入
slideInVertically(
initialOffsetY = { fullHeight -> fullHeight },
animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing)
) + fadeIn(
animationSpec = tween(durationMillis = 300)
)
2024-09-12 21:47:00 +08:00
},
exitTransition = {
// iOS风格向底部滑出
slideOutVertically(
targetOffsetY = { fullHeight -> fullHeight },
animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing)
) + fadeOut(
animationSpec = tween(durationMillis = 300)
)
},
popEnterTransition = {
// 返回时从底部滑入
slideInVertically(
initialOffsetY = { fullHeight -> fullHeight },
animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing)
) + fadeIn(
animationSpec = tween(durationMillis = 300)
)
},
popExitTransition = {
// 返回时向底部滑出
slideOutVertically(
targetOffsetY = { fullHeight -> fullHeight },
animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing)
) + fadeOut(
animationSpec = tween(durationMillis = 300)
)
2024-09-12 21:47:00 +08:00
}
) {
2024-09-05 22:04:41 +08:00
AccountEditScreen2()
2024-07-31 14:50:55 +08:00
}
2024-08-03 15:58:19 +08:00
composable(route = NavigationRoute.ImageViewer.route) {
2024-10-27 11:31:27 +08:00
ImageViewer()
2024-08-03 15:58:19 +08:00
}
2024-08-13 22:32:27 +08:00
composable(route = NavigationRoute.ChangePasswordScreen.route) {
ChangePasswordScreen()
}
2025-08-28 14:30:47 +08:00
composable(route = NavigationRoute.RemoveAccountScreen.route) {
RemoveAccountScreen()
}
composable(route = NavigationRoute.VipSelPage.route) {
VipSelPage()
}
2024-08-20 19:48:12 +08:00
composable(route = NavigationRoute.FavouritesScreen.route) {
FavouriteNoticeScreen()
2024-08-20 19:48:12 +08:00
}
2024-08-24 17:57:04 +08:00
composable(route = NavigationRoute.NewPostImageGrid.route) {
NewPostImageGridScreen()
}
composable(route = NavigationRoute.Search.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
SearchScreen()
}
}
composable(
route = NavigationRoute.FollowerList.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
FollowerListScreen(it.arguments?.getInt("id")!!)
}
}
composable(
route = NavigationRoute.FollowingList.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
FollowingListScreen(it.arguments?.getInt("id")!!)
}
}
2024-09-12 23:13:11 +08:00
composable(route = NavigationRoute.ResetPassword.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
ResetPasswordScreen()
}
}
2024-09-13 23:20:38 +08:00
composable(route = NavigationRoute.FavouriteList.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
FavouriteListPage()
}
}
2024-09-23 23:47:16 +08:00
composable(
route = NavigationRoute.Chat.route,
arguments = listOf(navArgument("id") { type = NavType.StringType })
) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
2024-10-27 11:31:27 +08:00
ChatScreen(it.arguments?.getString("id")!!)
2024-09-23 23:47:16 +08:00
}
}
2025-08-07 19:03:05 +08:00
composable(
route = NavigationRoute.ChatAi.route,
arguments = listOf(navArgument("id") { type = NavType.StringType })
) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
ChatAiScreen(it.arguments?.getString("id")!!)
}
}
composable(route = NavigationRoute.ChatSetting.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
ChatSettingScreen()
}
}
2025-08-18 19:02:11 +08:00
composable(
route = NavigationRoute.ChatGroup.route,
2025-08-20 19:19:14 +08:00
arguments = listOf(navArgument("id") { type = NavType.StringType },
navArgument("name") { type = NavType.StringType },
navArgument("avatar") { type = NavType.StringType })
2025-08-18 19:02:11 +08:00
) {
val encodedId = it.arguments?.getString("id")
val decodedId = encodedId?.let { java.net.URLDecoder.decode(it, "UTF-8") }
2025-08-20 19:19:14 +08:00
val name = it.arguments?.getString("name")
val avatar = it.arguments?.getString("avatar")
2025-08-18 19:02:11 +08:00
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
2025-08-20 19:19:14 +08:00
GroupChatScreen(decodedId?:"",name?:"",avatar?:"")
2025-08-18 19:02:11 +08:00
}
}
2025-08-07 19:03:05 +08:00
2024-09-27 21:29:30 +08:00
composable(route = NavigationRoute.CommentNoticeScreen.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
CommentNoticeScreen()
}
}
2024-10-09 15:33:08 +08:00
composable(route = NavigationRoute.ImageCrop.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
ImageCropScreen()
}
}
composable(route = NavigationRoute.AgentImageCrop.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
AgentImageCropScreen()
}
}
2024-12-07 17:14:45 +08:00
composable(route = NavigationRoute.AccountSetting.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
AccountSetting()
}
}
composable(route = NavigationRoute.AboutScreen.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
AboutScreen()
}
}
composable(
route = NavigationRoute.AddAgent.route,
) {
AddAgentScreen()
}
composable(
route = NavigationRoute.CreateGroupChat.route,
enterTransition = {
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(durationMillis = 280)
)
},
exitTransition = {
slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth / 3 },
animationSpec = tween(durationMillis = 280)
)
},
popEnterTransition = {
slideInHorizontally(
initialOffsetX = { fullWidth -> -fullWidth / 3 },
animationSpec = tween(durationMillis = 280)
)
},
popExitTransition = {
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(durationMillis = 280)
)
}
) {
CreateGroupChatScreen()
}
2025-08-11 18:21:22 +08:00
2025-08-25 10:49:00 +08:00
composable(
route = NavigationRoute.GroupInfo.route,
arguments = listOf(navArgument("id") { type = NavType.StringType })
) {
val encodedId = it.arguments?.getString("id")
val decodedId = encodedId?.let { java.net.URLDecoder.decode(it, "UTF-8") }
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
GroupChatInfoScreen(decodedId?:"")
}
}
composable(route = NavigationRoute.NotificationScreen.route) {
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
NotificationScreen()
}
}
2025-08-25 10:49:00 +08:00
2024-07-23 15:25:00 +08:00
}
}
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun Navigation(
startDestination: String = NavigationRoute.Login.route,
onLaunch: (navController: NavHostController) -> Unit
) {
2024-07-23 15:25:00 +08:00
val navController = rememberNavController()
2024-09-05 22:04:41 +08:00
LaunchedEffect(Unit) {
onLaunch(navController)
}
2024-07-23 15:25:00 +08:00
SharedTransitionLayout {
CompositionLocalProvider(
LocalNavController provides navController,
LocalSharedTransitionScope provides this@SharedTransitionLayout,
) {
Box {
2024-07-31 14:50:55 +08:00
NavigationController(
navController = navController,
startDestination = startDestination
)
AgentCreatedSuccessIndicator()
2024-07-23 15:25:00 +08:00
}
}
}
2024-09-22 15:35:42 +08:00
}
fun NavHostController.navigateToPost(
id: Int,
highlightCommentId: Int? = 0,
2024-09-29 23:17:59 +08:00
initImagePagerIndex: Int? = 0
2024-09-22 15:35:42 +08:00
) {
navigate(
route = NavigationRoute.Post.route
.replace("{id}", id.toString())
.replace("{highlightCommentId}", highlightCommentId.toString())
.replace("{initImagePagerIndex}", initImagePagerIndex.toString())
)
2024-09-23 23:47:16 +08:00
}
fun NavHostController.navigateToChat(id: String) {
navigate(
route = NavigationRoute.Chat.route
.replace("{id}", id)
2025-08-20 19:19:14 +08:00
2024-09-23 23:47:16 +08:00
)
2024-12-07 17:14:45 +08:00
}
2025-08-08 18:53:10 +08:00
fun NavHostController.navigateToChatAi(id: String) {
2025-08-07 19:03:05 +08:00
navigate(
2025-08-08 18:53:10 +08:00
route = NavigationRoute.ChatAi.route
2025-08-07 19:03:05 +08:00
.replace("{id}", id)
)
}
2025-08-20 19:19:14 +08:00
fun NavHostController.navigateToGroupChat(id: String,name:String,avatar:String) {
2025-08-18 19:02:11 +08:00
val encodedId = java.net.URLEncoder.encode(id, "UTF-8")
2025-08-20 19:19:14 +08:00
val encodedName = java.net.URLEncoder.encode(name, "UTF-8")
val encodedAvator = java.net.URLEncoder.encode(avatar, "UTF-8")
2025-08-18 19:02:11 +08:00
navigate(
route = NavigationRoute.ChatGroup.route
.replace("{id}", encodedId)
2025-08-20 19:19:14 +08:00
.replace("{name}", encodedName)
.replace("{avatar}", encodedAvator)
2025-08-18 19:02:11 +08:00
)
}
2025-08-21 19:04:59 +08:00
fun NavHostController.navigateToGroupInfo(id: String) {
val encodedId = java.net.URLEncoder.encode(id, "UTF-8")
2025-08-25 10:49:00 +08:00
2025-08-21 19:04:59 +08:00
navigate(
2025-08-25 18:35:06 +08:00
route = NavigationRoute.GroupInfo.route
2025-08-25 10:49:00 +08:00
.replace("{id}", encodedId)
2025-08-21 19:04:59 +08:00
)
}
2025-08-07 19:03:05 +08:00
2025-08-25 10:49:00 +08:00
2024-12-07 17:14:45 +08:00
fun NavHostController.goTo(
route: NavigationRoute
) {
navigate(route.route)
2024-07-23 15:25:00 +08:00
}