优化代码
修改我的-群聊UI将群聊列表样改为网格样式
This commit is contained in:
@@ -279,43 +279,4 @@ fun FriendChatItem(
|
||||
}
|
||||
}
|
||||
}
|
||||
@Composable
|
||||
fun ReloadButton(
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val gradientBrush = Brush.linearGradient(
|
||||
colors = listOf(
|
||||
Color(0xFF7c45ed),
|
||||
Color(0xFF7c68ef),
|
||||
Color(0xFF7bd8f8)
|
||||
)
|
||||
)
|
||||
|
||||
Button(
|
||||
onClick = onClick,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 120.dp)
|
||||
.height(48.dp),
|
||||
shape = RoundedCornerShape(30.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
backgroundColor = Color.Transparent
|
||||
),
|
||||
contentPadding = PaddingValues(0.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(gradientBrush),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.Reload),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = Color.White,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,8 @@ fun GalleryGrid(
|
||||
modifier = baseModifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(vertical = 60.dp),
|
||||
.padding(vertical = 60.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
|
||||
@@ -16,15 +16,16 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.pullRefresh
|
||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import com.airbnb.lottie.compose.LottieAnimation
|
||||
import com.airbnb.lottie.compose.LottieCompositionSpec
|
||||
import com.airbnb.lottie.compose.LottieConstants
|
||||
@@ -63,6 +64,8 @@ import com.aiosman.ravenow.ui.navigateToGroupChat
|
||||
import com.aiosman.ravenow.AppStore
|
||||
import com.aiosman.ravenow.data.api.ApiClient
|
||||
import android.util.Base64
|
||||
import com.aiosman.ravenow.ui.network.ReloadButton
|
||||
import com.aiosman.ravenow.utils.NetworkUtils.isNetworkAvailable
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
@@ -78,6 +81,7 @@ fun GroupChatEmptyContent(
|
||||
val context = LocalContext.current
|
||||
val navController = LocalNavController.current
|
||||
val viewModel = MyProfileViewModel
|
||||
val networkAvailable = isNetworkAvailable(context)
|
||||
|
||||
// 如果查看其他用户的房间,固定使用全部类型(filterType = 0)
|
||||
val filterType = if (showSegments) selectedSegment else 0
|
||||
@@ -133,11 +137,18 @@ fun GroupChatEmptyContent(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
// 空状态插图
|
||||
EmptyStateIllustration()
|
||||
EmptyStateIllustration(
|
||||
isNetworkAvailable = networkAvailable,
|
||||
onReload = {
|
||||
MyProfileViewModel.ResetModel()
|
||||
MyProfileViewModel.loadProfile(pullRefresh = true)
|
||||
}
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(9.dp))
|
||||
|
||||
// 空状态文本
|
||||
// 网络可用时才展示空状态文本
|
||||
if (networkAvailable) {
|
||||
Text(
|
||||
text = stringResource(R.string.cosmos_awaits),
|
||||
fontSize = 16.sp,
|
||||
@@ -149,16 +160,25 @@ fun GroupChatEmptyContent(
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
modifier = nestedScrollModifier.fillMaxSize()
|
||||
) {
|
||||
itemsIndexed(
|
||||
items = viewModel.rooms,
|
||||
key = { _, item -> item.id }
|
||||
) { index, room ->
|
||||
RoomItem(
|
||||
// 网格布局:每行显示2个房间卡片
|
||||
items(
|
||||
items = viewModel.rooms.chunked(2),
|
||||
key = { rowRooms -> rowRooms.firstOrNull()?.id?.toString() ?: "" }
|
||||
) { rowRooms ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
rowRooms.forEach { room ->
|
||||
RoomCard(
|
||||
room = room,
|
||||
onRoomClick = { roomEntity ->
|
||||
// 导航到群聊聊天界面
|
||||
@@ -167,14 +187,14 @@ fun GroupChatEmptyContent(
|
||||
name = roomEntity.name,
|
||||
avatar = roomEntity.avatar
|
||||
)
|
||||
},
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
}
|
||||
// 如果这一行只有一个房间,添加一个空的占位符
|
||||
if (rowRooms.size == 1) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
)
|
||||
|
||||
if (index < viewModel.rooms.size - 1) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(horizontal = 24.dp),
|
||||
color = AppColors.divider
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +236,120 @@ fun GroupChatEmptyContent(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RoomCard(
|
||||
room: RoomEntity,
|
||||
onRoomClick: (RoomEntity) -> Unit = {},
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
val context = LocalContext.current
|
||||
val roomDebouncer = rememberDebouncer()
|
||||
val cardSize = 180.dp
|
||||
|
||||
// 构建头像URL
|
||||
val avatarUrl = if (room.avatar.isNotEmpty()) {
|
||||
"${ConstVars.BASE_SERVER}/api/v1/outside/${room.avatar}?token=${AppStore.token}"
|
||||
} else {
|
||||
// 如果头像为空,使用群头像接口
|
||||
val groupIdBase64 = Base64.encodeToString(
|
||||
room.trtcType.toByteArray(),
|
||||
Base64.NO_WRAP
|
||||
)
|
||||
"${ApiClient.RETROFIT_URL}group/avatar?groupIdBase64=${groupIdBase64}&token=${AppStore.token}"
|
||||
}
|
||||
|
||||
// 优先显示cover,如果没有cover则显示recommendBanner,最后显示avatar
|
||||
val imageUrl = when {
|
||||
room.cover.isNotEmpty() -> "${ConstVars.BASE_SERVER}/api/v1/outside/${room.cover}?token=${AppStore.token}"
|
||||
room.recommendBanner.isNotEmpty() -> "${ConstVars.BASE_SERVER}/api/v1/outside/${room.recommendBanner}?token=${AppStore.token}"
|
||||
else -> avatarUrl
|
||||
}
|
||||
|
||||
// 正方形卡片,文字重叠在底部
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(cardSize)
|
||||
.background(AppColors.tabUnselectedBackground, RoundedCornerShape(12.dp))
|
||||
.noRippleClickable {
|
||||
roomDebouncer {
|
||||
onRoomClick(room)
|
||||
}
|
||||
}
|
||||
) {
|
||||
CustomAsyncImage(
|
||||
context = context,
|
||||
imageUrl = imageUrl,
|
||||
contentDescription = room.name,
|
||||
modifier = Modifier
|
||||
.width(cardSize)
|
||||
.height(120.dp)
|
||||
.clip(RoundedCornerShape(
|
||||
topStart = 12.dp,
|
||||
topEnd = 12.dp,
|
||||
bottomStart = 0.dp,
|
||||
bottomEnd = 0.dp)),
|
||||
contentScale = ContentScale.Crop,
|
||||
defaultRes = R.mipmap.rider_pro_agent
|
||||
)
|
||||
|
||||
// 房间名称,重叠在底部
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 32.dp, start = 10.dp, end = 10.dp)
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
) {
|
||||
Text(
|
||||
text = room.name,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.W900,
|
||||
color = AppColors.text,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
textAlign = TextAlign.Left
|
||||
)
|
||||
}
|
||||
|
||||
// 显示人数
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 10.dp, start = 10.dp, end = 10.dp)
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.rider_pro_nav_profile),
|
||||
contentDescription = "chat",
|
||||
modifier = Modifier.size(16.dp),
|
||||
colorFilter = ColorFilter.tint(AppColors.secondaryText)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = "${room.userCount} ${stringResource(R.string.chatting_now)}",
|
||||
fontSize = 12.sp,
|
||||
modifier = Modifier
|
||||
.alpha(0.6f)
|
||||
.weight(1f),
|
||||
color = AppColors.text,
|
||||
fontWeight = FontWeight.W500,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表样式的房间项,供搜索等场景复用
|
||||
*/
|
||||
@Composable
|
||||
fun RoomItem(
|
||||
room: RoomEntity,
|
||||
@@ -229,7 +363,6 @@ fun RoomItem(
|
||||
val avatarUrl = if (room.avatar.isNotEmpty()) {
|
||||
"${ConstVars.BASE_SERVER}/api/v1/outside/${room.avatar}?token=${AppStore.token}"
|
||||
} else {
|
||||
// 如果头像为空,使用群头像接口
|
||||
val groupIdBase64 = Base64.encodeToString(
|
||||
room.trtcType.toByteArray(),
|
||||
Base64.NO_WRAP
|
||||
@@ -388,7 +521,12 @@ private fun SegmentButton(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EmptyStateIllustration() {
|
||||
private fun EmptyStateIllustration(
|
||||
isNetworkAvailable: Boolean,
|
||||
onReload: () -> Unit
|
||||
) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
if (isNetworkAvailable) {
|
||||
Image(
|
||||
painter = painterResource(id = R.mipmap.l_empty_img),
|
||||
contentDescription = "空状态",
|
||||
@@ -397,5 +535,32 @@ private fun EmptyStateIllustration() {
|
||||
.height(153.dp),
|
||||
contentScale = ContentScale.Fit
|
||||
)
|
||||
} else {
|
||||
Image(
|
||||
painter = painterResource(id = R.mipmap.invalid_name_10),
|
||||
contentDescription = "network error",
|
||||
modifier = Modifier.size(181.dp),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.friend_chat_no_network_title),
|
||||
fontSize = 16.sp,
|
||||
color = AppColors.text,
|
||||
fontWeight = FontWeight.W600
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.friend_chat_no_network_subtitle),
|
||||
fontSize = 14.sp,
|
||||
color = AppColors.secondaryText,
|
||||
fontWeight = FontWeight.W400
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
ReloadButton(onClick = onReload)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -786,42 +786,3 @@ fun SearchPlaceholderContent(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ReloadButton(
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val gradientBrush = Brush.linearGradient(
|
||||
colors = listOf(
|
||||
Color(0xFF7c45ed),
|
||||
Color(0xFF7c68ef),
|
||||
Color(0xFF7bd8f8)
|
||||
)
|
||||
)
|
||||
|
||||
Button(
|
||||
onClick = onClick,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 120.dp)
|
||||
.height(48.dp),
|
||||
shape = RoundedCornerShape(30.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
backgroundColor = Color.Transparent
|
||||
),
|
||||
contentPadding = PaddingValues(0.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(gradientBrush),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.Reload),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = Color.White,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user