防抖调整

This commit is contained in:
2025-09-04 18:28:11 +08:00
parent 9b7349a761
commit 9f14b35847
15 changed files with 322 additions and 156 deletions

View File

@@ -23,26 +23,36 @@ import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.LocalNavController import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.ui.post.NewPostViewModel import com.aiosman.ravenow.ui.post.NewPostViewModel
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.composables.rememberDebouncedNavigation
import com.aiosman.ravenow.ui.composables.rememberDebouncedState
import com.aiosman.ravenow.ui.composables.rememberDebouncer
@Composable @Composable
fun AddPage(){ fun AddPage(){
val navController = LocalNavController.current val navController = LocalNavController.current
val debouncer = rememberDebouncedNavigation()
Column(modifier = Modifier Column(modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(Color.Black)) { .background(Color.Black)) {
AddBtn(icon = R.drawable.rider_pro_icon_rider_share, text = "Rave NowShare") { AddBtn(icon = R.drawable.rider_pro_icon_rider_share, text = "Rave NowShare") {
NewPostViewModel.asNewPost() NewPostViewModel.asNewPost()
debouncer {
navController.navigate("NewPost") navController.navigate("NewPost")
} }
}
// AddBtn(icon = R.drawable.rider_pro_location_create, text = "Location Create") // AddBtn(icon = R.drawable.rider_pro_location_create, text = "Location Create")
} }
} }
@Composable @Composable
fun AddBtn(@DrawableRes icon: Int, text: String,onClick: (() -> Unit)? = {}){ fun AddBtn(@DrawableRes icon: Int, text: String,onClick: (() -> Unit)? = {}){
val (isDebouncing, startDebounce, resetDebounce) = rememberDebouncedState()
Row (modifier = Modifier Row (modifier = Modifier
.fillMaxWidth().padding(24.dp).clickable { .fillMaxWidth().padding(24.dp).clickable {
if (!isDebouncing) {
startDebounce()
onClick?.invoke() onClick?.invoke()
}
}, },
verticalAlignment = Alignment.CenterVertically){ verticalAlignment = Alignment.CenterVertically){
Image( Image(

View File

@@ -34,6 +34,7 @@ import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.NavigationRoute import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.AgentCard import com.aiosman.ravenow.ui.composables.AgentCard
import com.aiosman.ravenow.ui.composables.rememberDebouncer
@OptIn(ExperimentalMaterialApi::class) @OptIn(ExperimentalMaterialApi::class)
@Composable @Composable
@@ -117,20 +118,26 @@ fun HotAgent() {
key = { idx -> idx } key = { idx -> idx }
) { idx -> ) { idx ->
val agentItem = agentList[idx] val agentItem = agentList[idx]
val chatDebouncer = rememberDebouncer()
val avatarDebouncer = rememberDebouncer()
AgentCard( AgentCard(
agentEntity = agentItem, agentEntity = agentItem,
onClick = { onClick = {
chatDebouncer {
// 检查游客模式,如果是游客则跳转登录 // 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.CHAT_WITH_AGENT)) { if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.CHAT_WITH_AGENT)) {
navController.navigate(NavigationRoute.Login.route) navController.navigate(NavigationRoute.Login.route)
} else { } else {
model.createSingleChat(agentItem.openId) model.createSingleChat(agentItem.openId)
model.goToChatAi(agentItem.openId,navController) model.goToChatAi(agentItem.openId, navController)
}
} }
}, },
onAvatarClick = { onAvatarClick = {
avatarDebouncer {
model.goToProfile(agentItem.openId, navController) model.goToProfile(agentItem.openId, navController)
} }
}
) )
} }

View File

@@ -37,6 +37,7 @@ import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.NavigationRoute import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.AgentCard import com.aiosman.ravenow.ui.composables.AgentCard
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatItem import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatItem
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListViewModel import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListViewModel
import java.util.UUID import java.util.UUID
@@ -108,9 +109,13 @@ fun MineAgent() {
items(count = agentList.itemCount, key = { index -> agentList[index]?.id ?: index }) { index -> items(count = agentList.itemCount, key = { index -> agentList[index]?.id ?: index }) { index ->
agentList[index]?.let { agent -> agentList[index]?.let { agent ->
val chatDebouncer = rememberDebouncer()
val avatarDebouncer = rememberDebouncer()
AgentCard( AgentCard(
agentEntity = agent, agentEntity = agent,
onClick = { onClick = {
chatDebouncer {
// 检查游客模式,如果是游客则跳转登录 // 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.CHAT_WITH_AGENT)) { if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.CHAT_WITH_AGENT)) {
navController.navigate(NavigationRoute.Login.route) navController.navigate(NavigationRoute.Login.route)
@@ -118,14 +123,18 @@ fun MineAgent() {
model.createSingleChat(agent.openId) model.createSingleChat(agent.openId)
model.goToChatAi(agent.openId,navController) model.goToChatAi(agent.openId,navController)
} }
}
}, },
onAvatarClick = { onAvatarClick = {
avatarDebouncer {
model.goToProfile(agent.openId, navController) model.goToProfile(agent.openId, navController)
} }
}
) )
} }
} }
// 加载更多指示器 // 加载更多指示器
if (agentList.loadState.append is LoadState.Loading) { if (agentList.loadState.append is LoadState.Loading) {
item { item {

View File

@@ -65,6 +65,8 @@ import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.StatusBarSpacer import com.aiosman.ravenow.ui.composables.StatusBarSpacer
import com.aiosman.ravenow.ui.composables.TabItem import com.aiosman.ravenow.ui.composables.TabItem
import com.aiosman.ravenow.ui.composables.TabSpacer import com.aiosman.ravenow.ui.composables.TabSpacer
import com.aiosman.ravenow.ui.composables.rememberDebouncedNavigation
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.follower.FollowerNoticeViewModel import com.aiosman.ravenow.ui.follower.FollowerNoticeViewModel
import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListScreen import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListScreen
import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListViewModel import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListViewModel
@@ -84,6 +86,7 @@ import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class) @OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
@Composable @Composable
fun NotificationsScreen() { fun NotificationsScreen() {
val debouncer = rememberDebouncer()
// 计算总未读消息数 // 计算总未读消息数
val totalUnreadCount = AgentChatListViewModel.totalUnreadCount + val totalUnreadCount = AgentChatListViewModel.totalUnreadCount +
GroupChatListViewModel.totalUnreadCount + GroupChatListViewModel.totalUnreadCount +
@@ -167,12 +170,15 @@ fun NotificationsScreen() {
modifier = Modifier modifier = Modifier
.size(24.dp) .size(24.dp)
.noRippleClickable { .noRippleClickable {
debouncer {
navController.navigate(NavigationRoute.CreateGroupChat.route) navController.navigate(NavigationRoute.CreateGroupChat.route)
}
}, },
colorFilter = ColorFilter.tint(AppColors.text) colorFilter = ColorFilter.tint(AppColors.text)
) )
} }
// 搜索栏// // 搜索栏//
Box( Box(
@@ -219,12 +225,17 @@ fun NotificationsScreen() {
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
) { ) {
val likeDebouncer = rememberDebouncer()
val followDebouncer = rememberDebouncer()
val commentDebouncer = rememberDebouncer()
NotificationIndicator( NotificationIndicator(
MessageListViewModel.likeNoticeCount, MessageListViewModel.likeNoticeCount,
R.mipmap.rider_pro_like, R.mipmap.rider_pro_like,
stringResource(R.string.like_upper), stringResource(R.string.like_upper),
Color(0xFFFAFD5D) Color(0xFFFAFD5D)
) { ) {
likeDebouncer {
if (MessageListViewModel.likeNoticeCount > 0) { if (MessageListViewModel.likeNoticeCount > 0) {
// 刷新点赞消息列表 // 刷新点赞消息列表
LikeNoticeViewModel.isFirstLoad = true LikeNoticeViewModel.isFirstLoad = true
@@ -233,12 +244,14 @@ fun NotificationsScreen() {
} }
navController.navigate(NavigationRoute.Likes.route) navController.navigate(NavigationRoute.Likes.route)
} }
}
NotificationIndicator( NotificationIndicator(
MessageListViewModel.followNoticeCount, MessageListViewModel.followNoticeCount,
R.mipmap.rider_pro_followers, R.mipmap.rider_pro_followers,
stringResource(R.string.followers_upper), stringResource(R.string.followers_upper),
Color(0xFFF470FE) Color(0xFFF470FE)
) { ) {
followDebouncer {
if (MessageListViewModel.followNoticeCount > 0) { if (MessageListViewModel.followNoticeCount > 0) {
// 刷新关注消息列表 // 刷新关注消息列表
FollowerNoticeViewModel.isFirstLoad = true FollowerNoticeViewModel.isFirstLoad = true
@@ -246,15 +259,18 @@ fun NotificationsScreen() {
} }
navController.navigate(NavigationRoute.Followers.route) navController.navigate(NavigationRoute.Followers.route)
} }
}
NotificationIndicator( NotificationIndicator(
MessageListViewModel.commentNoticeCount, MessageListViewModel.commentNoticeCount,
R.mipmap.rider_pro_comment, R.mipmap.rider_pro_comment,
stringResource(R.string.comment).uppercase(), stringResource(R.string.comment).uppercase(),
Color(0xFF6246FF) Color(0xFF6246FF)
) { ) {
commentDebouncer {
navController.navigate(NavigationRoute.CommentNoticeScreen.route) navController.navigate(NavigationRoute.CommentNoticeScreen.route)
} }
} }
}
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -264,15 +280,19 @@ fun NotificationsScreen() {
horizontalArrangement = Arrangement.Start, horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.Bottom verticalAlignment = Alignment.Bottom
) { ) {
val tabDebouncer = rememberDebouncer()
Box { Box {
TabItem( TabItem(
text = stringResource(R.string.chat_ai), text = stringResource(R.string.chat_ai),
isSelected = pagerState.currentPage == 0, isSelected = pagerState.currentPage == 0,
onClick = { onClick = {
tabDebouncer {
scope.launch { scope.launch {
pagerState.animateScrollToPage(0) pagerState.animateScrollToPage(0)
} }
} }
}
) )
// 智能体未读消息红点 // 智能体未读消息红点
@@ -295,10 +315,12 @@ fun NotificationsScreen() {
text = stringResource(R.string.chat_group), text = stringResource(R.string.chat_group),
isSelected = pagerState.currentPage == 1, isSelected = pagerState.currentPage == 1,
onClick = { onClick = {
tabDebouncer {
scope.launch { scope.launch {
pagerState.animateScrollToPage(1) pagerState.animateScrollToPage(1)
} }
} }
}
) )
// 群聊未读消息红点 // 群聊未读消息红点
@@ -321,10 +343,12 @@ fun NotificationsScreen() {
text = stringResource(R.string.chat_friend), text = stringResource(R.string.chat_friend),
isSelected = pagerState.currentPage == 2, isSelected = pagerState.currentPage == 2,
onClick = { onClick = {
tabDebouncer {
scope.launch { scope.launch {
pagerState.animateScrollToPage(2) pagerState.animateScrollToPage(2)
} }
} }
}
) )
// 朋友未读消息红点 // 朋友未读消息红点
@@ -378,6 +402,7 @@ fun NotificationIndicator(
onClick: () -> Unit onClick: () -> Unit
) { ) {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
Box( Box(
modifier = Modifier modifier = Modifier
) { ) {
@@ -435,3 +460,5 @@ fun NotificationIndicator(
} }

View File

@@ -44,6 +44,7 @@ import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.NavigationRoute import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.CustomAsyncImage import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.aiosman.ravenow.utils.NetworkUtils import com.aiosman.ravenow.utils.NetworkUtils
@@ -190,13 +191,16 @@ fun AgentChatItem(
onChatClick: (AgentConversation) -> Unit = {} onChatClick: (AgentConversation) -> Unit = {}
) { ) {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val chatDebouncer = rememberDebouncer()
val avatarDebouncer = rememberDebouncer()
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp) .padding(horizontal = 16.dp, vertical = 12.dp)
.noRippleClickable { .noRippleClickable {
chatDebouncer {
onChatClick(conversation) onChatClick(conversation)
}
}, },
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
@@ -209,8 +213,10 @@ fun AgentChatItem(
.size(48.dp) .size(48.dp)
.clip(RoundedCornerShape(48.dp)) .clip(RoundedCornerShape(48.dp))
.noRippleClickable { .noRippleClickable {
avatarDebouncer {
onUserAvatarClick(conversation) onUserAvatarClick(conversation)
} }
}
) )
} }

View File

@@ -32,6 +32,7 @@ import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.composables.CustomAsyncImage import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.aiosman.ravenow.utils.NetworkUtils import com.aiosman.ravenow.utils.NetworkUtils
@@ -169,13 +170,17 @@ fun FriendChatItem(
onChatClick: (FriendConversation) -> Unit = {} onChatClick: (FriendConversation) -> Unit = {}
) { ) {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val chatDebouncer = rememberDebouncer()
val avatarDebouncer = rememberDebouncer()
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp) .padding(horizontal = 16.dp, vertical = 12.dp)
.noRippleClickable { .noRippleClickable {
chatDebouncer {
onChatClick(conversation) onChatClick(conversation)
}
}, },
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
@@ -188,8 +193,10 @@ fun FriendChatItem(
.size(48.dp) .size(48.dp)
.clip(RoundedCornerShape(48.dp)) .clip(RoundedCornerShape(48.dp))
.noRippleClickable { .noRippleClickable {
avatarDebouncer {
onUserAvatarClick(conversation) onUserAvatarClick(conversation)
} }
}
) )
} }
@@ -259,3 +266,4 @@ fun FriendChatItem(
} }
} }
} }

View File

@@ -31,6 +31,7 @@ import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.composables.CustomAsyncImage import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.aiosman.ravenow.utils.NetworkUtils import com.aiosman.ravenow.utils.NetworkUtils
@@ -172,14 +173,18 @@ fun GroupChatItem(
onChatClick: (GroupConversation) -> Unit = {} onChatClick: (GroupConversation) -> Unit = {}
) { ) {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val chatDebouncer = rememberDebouncer()
val avatarDebouncer = rememberDebouncer()
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 12.dp) .padding(horizontal = 24.dp, vertical = 12.dp)
.noRippleClickable { .noRippleClickable {
chatDebouncer {
onChatClick(conversation) onChatClick(conversation)
} }
}
) { ) {
Box { Box {
CustomAsyncImage( CustomAsyncImage(
@@ -190,8 +195,10 @@ fun GroupChatItem(
.size(48.dp) .size(48.dp)
.clip(RoundedCornerShape(12.dp)) .clip(RoundedCornerShape(12.dp))
.noRippleClickable { .noRippleClickable {
avatarDebouncer {
onGroupAvatarClick(conversation) onGroupAvatarClick(conversation)
} }
}
) )
} }
@@ -261,3 +268,4 @@ fun GroupChatItem(
} }
} }
} }

View File

@@ -24,6 +24,7 @@ import com.aiosman.ravenow.GuestLoginCheckOutScene
import com.aiosman.ravenow.LocalNavController import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.ui.NavigationRoute import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.MomentCard import com.aiosman.ravenow.ui.composables.MomentCard
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
/** /**
@@ -101,8 +102,16 @@ fun Dynamic() {
//处理下标越界 //处理下标越界
if (idx < 0 || idx >= moments.size) return@items if (idx < 0 || idx >= moments.size) return@items
val momentItem = moments[idx] ?: return@items val momentItem = moments[idx] ?: return@items
MomentCard(momentEntity = momentItem,
val commentDebouncer = rememberDebouncer()
val likeDebouncer = rememberDebouncer()
val favoriteDebouncer = rememberDebouncer()
val followDebouncer = rememberDebouncer()
MomentCard(
momentEntity = momentItem,
onAddComment = { onAddComment = {
commentDebouncer {
// 检查游客模式,如果是游客则跳转登录 // 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.COMMENT_MOMENT)) { if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.COMMENT_MOMENT)) {
navController.navigate(NavigationRoute.Login.route) navController.navigate(NavigationRoute.Login.route)
@@ -111,8 +120,10 @@ fun Dynamic() {
model.onAddComment(momentItem.id) model.onAddComment(momentItem.id)
} }
} }
}
}, },
onLikeClick = { onLikeClick = {
likeDebouncer {
// 检查游客模式,如果是游客则跳转登录 // 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.LIKE_MOMENT)) { if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.LIKE_MOMENT)) {
navController.navigate(NavigationRoute.Login.route) navController.navigate(NavigationRoute.Login.route)
@@ -125,8 +136,10 @@ fun Dynamic() {
} }
} }
} }
}
}, },
onFavoriteClick = { onFavoriteClick = {
favoriteDebouncer {
// 检查游客模式,如果是游客则跳转登录 // 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.LIKE_MOMENT)) { if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.LIKE_MOMENT)) {
navController.navigate(NavigationRoute.Login.route) navController.navigate(NavigationRoute.Login.route)
@@ -139,20 +152,22 @@ fun Dynamic() {
} }
} }
} }
}
}, },
onFollowClick = { onFollowClick = {
followDebouncer {
// 检查游客模式,如果是游客则跳转登录 // 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.FOLLOW_USER)) { if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.FOLLOW_USER)) {
navController.navigate(NavigationRoute.Login.route) navController.navigate(NavigationRoute.Login.route)
} else { } else {
model.followAction(momentItem) model.followAction(momentItem)
} }
}
}, },
showFollowButton = true showFollowButton = true
) )
} }
} }
PullRefreshIndicator(model.refreshing, state, Modifier.align(Alignment.TopCenter))
} }
} }
} }

View File

@@ -46,6 +46,7 @@ import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.NavigationRoute import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.CustomAsyncImage import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.StatusBarSpacer import com.aiosman.ravenow.ui.composables.StatusBarSpacer
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.index.tabs.search.SearchViewModel import com.aiosman.ravenow.ui.index.tabs.search.SearchViewModel
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.aiosman.ravenow.ui.navigateToPost import com.aiosman.ravenow.ui.navigateToPost
@@ -130,18 +131,21 @@ fun DiscoverView() {
// contentPadding = PaddingValues(8.dp) // contentPadding = PaddingValues(8.dp)
) { ) {
items(moments) { momentItem -> items(moments) { momentItem ->
val debouncer = rememberDebouncer()
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.aspectRatio(1f) .aspectRatio(1f)
.padding(2.dp) .padding(2.dp)
.noRippleClickable { .noRippleClickable {
debouncer {
navController.navigateToPost( navController.navigateToPost(
id = momentItem.id, id = momentItem.id,
highlightCommentId = 0, highlightCommentId = 0,
initImagePagerIndex = 0 initImagePagerIndex = 0
) )
} }
}
) { ) {
CustomAsyncImage( CustomAsyncImage(
imageUrl = momentItem.images[0].thumbnail, imageUrl = momentItem.images[0].thumbnail,

View File

@@ -41,6 +41,7 @@ import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.LocalAppTheme import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.composables.MomentCard import com.aiosman.ravenow.ui.composables.MomentCard
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
/** /**
@@ -86,6 +87,7 @@ fun TimelineMomentsList() {
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
val exploreDebouncer = rememberDebouncer()
Image( Image(
painter = painterResource( painter = painterResource(
id = if(AppState.darkMode) R.mipmap.qst_gz_qs_as_img id = if(AppState.darkMode) R.mipmap.qst_gz_qs_as_img
@@ -109,7 +111,10 @@ fun TimelineMomentsList() {
) )
Spacer(modifier = Modifier.size(16.dp)) Spacer(modifier = Modifier.size(16.dp))
ExploreButton( ExploreButton(
onClick = { /* TODO: 添加点击事件处理 */ } onClick = {
exploreDebouncer {
/* TODO: 添加点击事件处理 */
} }
) )
} }
} }
@@ -128,14 +133,22 @@ fun TimelineMomentsList() {
key = { idx -> moments.getOrNull(idx)?.id ?: idx } key = { idx -> moments.getOrNull(idx)?.id ?: idx }
) { idx -> ) { idx ->
moments.getOrNull(idx)?.let { momentItem -> moments.getOrNull(idx)?.let { momentItem ->
val commentDebouncer = rememberDebouncer()
val likeDebouncer = rememberDebouncer()
val favoriteDebouncer = rememberDebouncer()
val followDebouncer = rememberDebouncer()
MomentCard( MomentCard(
momentEntity = momentItem, momentEntity = momentItem,
onAddComment = { onAddComment = {
commentDebouncer {
scope.launch { scope.launch {
model.onAddComment(momentItem.id) model.onAddComment(momentItem.id)
} }
}
}, },
onLikeClick = { onLikeClick = {
likeDebouncer {
scope.launch { scope.launch {
if (momentItem.liked) { if (momentItem.liked) {
model.dislikeMoment(momentItem.id) model.dislikeMoment(momentItem.id)
@@ -143,8 +156,10 @@ fun TimelineMomentsList() {
model.likeMoment(momentItem.id) model.likeMoment(momentItem.id)
} }
} }
}
}, },
onFavoriteClick = { onFavoriteClick = {
favoriteDebouncer {
scope.launch { scope.launch {
if (momentItem.isFavorite) { if (momentItem.isFavorite) {
model.unfavoriteMoment(momentItem.id) model.unfavoriteMoment(momentItem.id)
@@ -152,14 +167,18 @@ fun TimelineMomentsList() {
model.favoriteMoment(momentItem.id) model.favoriteMoment(momentItem.id)
} }
} }
}
}, },
onFollowClick = { onFollowClick = {
followDebouncer {
model.followAction(momentItem) model.followAction(momentItem)
}
}, },
showFollowButton = false showFollowButton = false
) )
} }
} }
} }
PullRefreshIndicator(model.refreshing, state, Modifier.align(Alignment.TopCenter)) PullRefreshIndicator(model.refreshing, state, Modifier.align(Alignment.TopCenter))
} }

View File

@@ -38,6 +38,7 @@ import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import com.aiosman.ravenow.AppState import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.ui.composables.rememberDebouncer
@Composable @Composable
fun GalleryItem( fun GalleryItem(
@@ -46,6 +47,7 @@ fun GalleryItem(
) { ) {
val navController = LocalNavController.current val navController = LocalNavController.current
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val debouncer = rememberDebouncer()
Box( Box(
modifier = Modifier modifier = Modifier
@@ -65,10 +67,12 @@ fun GalleryItem(
} }
.clip(RoundedCornerShape(8.dp)) .clip(RoundedCornerShape(8.dp))
.noRippleClickable { .noRippleClickable {
debouncer {
navController.navigateToPost( navController.navigateToPost(
moment.id moment.id
) )
} }
}
) { ) {
// 检查图片列表是否为空 // 检查图片列表是否为空
if (moment.images.isEmpty()) { if (moment.images.isEmpty()) {
@@ -116,6 +120,7 @@ fun GalleryItem(
} }
} }
@Composable @Composable
fun GalleryGrid( fun GalleryGrid(
moments: List<MomentEntity> moments: List<MomentEntity>
@@ -123,6 +128,7 @@ fun GalleryGrid(
val navController = LocalNavController.current val navController = LocalNavController.current
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val gridState = rememberLazyGridState() val gridState = rememberLazyGridState()
val debouncer = rememberDebouncer()
if (moments.isEmpty()) { if (moments.isEmpty()) {
Column( Column(
@@ -166,18 +172,21 @@ fun GalleryGrid(
) { ) {
itemsIndexed(moments) { idx, moment -> itemsIndexed(moments) { idx, moment ->
if (moment != null) { if (moment != null) {
val itemDebouncer = rememberDebouncer()
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.aspectRatio(1f) .aspectRatio(1f)
.padding(2.dp) .padding(2.dp)
.noRippleClickable { .noRippleClickable {
itemDebouncer {
navController.navigateToPost( navController.navigateToPost(
id = moment.id, id = moment.id,
highlightCommentId = 0, highlightCommentId = 0,
initImagePagerIndex = 0 initImagePagerIndex = 0
) )
} }
}
) { ) {
CustomAsyncImage( CustomAsyncImage(
imageUrl = moment.images[0].thumbnail, imageUrl = moment.images[0].thumbnail,
@@ -208,3 +217,4 @@ fun GalleryGrid(
} }
} }

View File

@@ -23,6 +23,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.LocalAppTheme import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
@Composable @Composable
@@ -31,6 +32,8 @@ fun SelfProfileAction(
onPremiumClick: (() -> Unit)? = null onPremiumClick: (() -> Unit)? = null
) { ) {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val editProfileDebouncer = rememberDebouncer()
val premiumClickDebouncer = rememberDebouncer()
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -47,8 +50,10 @@ fun SelfProfileAction(
.background(AppColors.nonActive) .background(AppColors.nonActive)
.padding(horizontal = 16.dp, vertical = 12.dp) .padding(horizontal = 16.dp, vertical = 12.dp)
.noRippleClickable { .noRippleClickable {
editProfileDebouncer {
onEditProfile() onEditProfile()
} }
}
) { ) {
Text( Text(
text = stringResource(R.string.edit_profile), text = stringResource(R.string.edit_profile),
@@ -68,8 +73,10 @@ fun SelfProfileAction(
.background(AppColors.premiumBackground) .background(AppColors.premiumBackground)
.padding(horizontal = 16.dp, vertical = 12.dp) .padding(horizontal = 16.dp, vertical = 12.dp)
.noRippleClickable { .noRippleClickable {
premiumClickDebouncer {
onPremiumClick?.invoke() onPremiumClick?.invoke()
} }
}
) { ) {
Image( Image(
painter = painterResource(id = R.drawable.ic_member), painter = painterResource(id = R.drawable.ic_member),

View File

@@ -42,6 +42,7 @@ import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
import com.aiosman.ravenow.entity.AgentEntity import com.aiosman.ravenow.entity.AgentEntity
import com.aiosman.ravenow.ui.composables.CustomAsyncImage import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
@Composable @Composable
@@ -164,6 +165,9 @@ private fun AgentItem(
onLongClick: () -> Unit = {} onLongClick: () -> Unit = {}
) { ) {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val clickDebouncer = rememberDebouncer()
val avatarClickDebouncer = rememberDebouncer()
val longClickDebouncer = rememberDebouncer()
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
@@ -173,12 +177,16 @@ private fun AgentItem(
indication = null, indication = null,
onClick = { onClick = {
Log.d("AgentItem", "onClick triggered for agent: ${agent.title}") Log.d("AgentItem", "onClick triggered for agent: ${agent.title}")
clickDebouncer {
onClick() onClick()
}
}, },
onLongClick = { onLongClick = {
Log.d("AgentItem", "onLongClick triggered for agent: ${agent.title}") Log.d("AgentItem", "onLongClick triggered for agent: ${agent.title}")
longClickDebouncer {
onLongClick() onLongClick()
} }
}
) )
) { ) {
// 头像 // 头像
@@ -191,12 +199,16 @@ private fun AgentItem(
indication = null, indication = null,
onClick = { onClick = {
Log.d("AgentItem", "Avatar clicked for agent: ${agent.title}") Log.d("AgentItem", "Avatar clicked for agent: ${agent.title}")
avatarClickDebouncer {
onAvatarClick() onAvatarClick()
}
}, },
onLongClick = { onLongClick = {
Log.d("AgentItem", "Avatar long clicked for agent: ${agent.title}") Log.d("AgentItem", "Avatar long clicked for agent: ${agent.title}")
longClickDebouncer {
onLongClick() onLongClick()
} }
}
) )
) { ) {
CustomAsyncImage( CustomAsyncImage(
@@ -205,7 +217,7 @@ private fun AgentItem(
contentDescription = agent.title, contentDescription = agent.title,
modifier = Modifier.size(48.dp), modifier = Modifier.size(48.dp),
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
defaultRes = com.aiosman.ravenow.R.mipmap.rider_pro_agent defaultRes = R.mipmap.rider_pro_agent
) )
} }
@@ -225,16 +237,22 @@ private fun AgentItem(
} }
} }
@Composable @Composable
private fun MoreAgentItem( private fun MoreAgentItem(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onClick: () -> Unit = {} onClick: () -> Unit = {}
) { ) {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val debouncer = rememberDebouncer()
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier.noRippleClickable { onClick() } modifier = modifier.noRippleClickable {
debouncer {
onClick()
}
}
) { ) {
// 圆形右箭头按钮 // 圆形右箭头按钮
Box( Box(
@@ -267,3 +285,4 @@ private fun MoreAgentItem(
) )
} }
} }

View File

@@ -27,6 +27,7 @@ import com.aiosman.ravenow.R
import com.aiosman.ravenow.entity.AccountProfileEntity import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.ui.NavigationRoute import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.CustomAsyncImage import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
@Composable @Composable
@@ -36,6 +37,8 @@ fun UserItem(
) { ) {
val navController = LocalNavController.current val navController = LocalNavController.current
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
val followerDebouncer = rememberDebouncer()
val followingDebouncer = rememberDebouncer()
Column( Column(
modifier = Modifier modifier = Modifier
@@ -84,6 +87,7 @@ fun UserItem(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.noRippleClickable { .noRippleClickable {
followerDebouncer {
navController.navigate( navController.navigate(
NavigationRoute.FollowerList.route.replace( NavigationRoute.FollowerList.route.replace(
"{id}", "{id}",
@@ -91,6 +95,7 @@ fun UserItem(
) )
) )
} }
}
) { ) {
Text( Text(
text = accountProfileEntity.followerCount.toString(), text = accountProfileEntity.followerCount.toString(),
@@ -111,6 +116,7 @@ fun UserItem(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.noRippleClickable { .noRippleClickable {
followingDebouncer {
navController.navigate( navController.navigate(
NavigationRoute.FollowingList.route.replace( NavigationRoute.FollowingList.route.replace(
"{id}", "{id}",
@@ -118,6 +124,7 @@ fun UserItem(
) )
) )
} }
}
) { ) {
Text( Text(
text = accountProfileEntity.followingCount.toString(), text = accountProfileEntity.followingCount.toString(),

View File

@@ -80,6 +80,7 @@ import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.DraggableGrid import com.aiosman.ravenow.ui.composables.DraggableGrid
import com.aiosman.ravenow.ui.composables.RelPostCard import com.aiosman.ravenow.ui.composables.RelPostCard
import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout import com.aiosman.ravenow.ui.composables.StatusBarMaskLayout
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -486,6 +487,9 @@ fun AddImageGrid() {
} }
} }
val addImageDebouncer = rememberDebouncer()
val takePhotoDebouncer = rememberDebouncer()
val stroke = Stroke( val stroke = Stroke(
width = 2f, width = 2f,
pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f) pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
@@ -551,10 +555,16 @@ fun AddImageGrid() {
.clip(RoundedCornerShape(16.dp)) // 设置圆角 .clip(RoundedCornerShape(16.dp)) // 设置圆角
.background(AppColors.basicMain) // 设置背景色 .background(AppColors.basicMain) // 设置背景色
.noRippleClickable { .noRippleClickable {
addImageDebouncer {
if (model.imageList.size < 9) { if (model.imageList.size < 9) {
pickImagesLauncher.launch("image/*") pickImagesLauncher.launch("image/*")
} else { } else {
Toast.makeText(context, "最多只能选择9张图片", Toast.LENGTH_SHORT).show() Toast.makeText(
context,
"最多只能选择9张图片",
Toast.LENGTH_SHORT
).show()
}
} }
}, },
) { ) {