@@ -54,6 +54,7 @@ import com.airbnb.lottie.compose.LottieAnimation
|
|||||||
import com.airbnb.lottie.compose.LottieCompositionSpec
|
import com.airbnb.lottie.compose.LottieCompositionSpec
|
||||||
import com.airbnb.lottie.compose.LottieConstants
|
import com.airbnb.lottie.compose.LottieConstants
|
||||||
import com.airbnb.lottie.compose.rememberLottieComposition
|
import com.airbnb.lottie.compose.rememberLottieComposition
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.ChatEmptyStateView
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 智能体聊天列表页面
|
* 智能体聊天列表页面
|
||||||
@@ -104,22 +105,7 @@ fun AgentChatListScreen() {
|
|||||||
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
|
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
|
||||||
|
|
||||||
if (isNetworkAvailable) {
|
if (isNetworkAvailable) {
|
||||||
Image(
|
ChatEmptyStateView()
|
||||||
painter = painterResource(id = R.mipmap.invalid_name_3),
|
|
||||||
contentDescription = "null data",
|
|
||||||
modifier = Modifier.size(120.dp)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.no_one_knocked_yet),
|
|
||||||
color = AppColors.text,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
fontWeight = FontWeight.W600,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
NetworkErrorContentCompact(
|
NetworkErrorContentCompact(
|
||||||
onReload = {
|
onReload = {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import com.aiosman.ravenow.ui.network.NetworkErrorContentCompact
|
|||||||
import androidx.compose.material.Button
|
import androidx.compose.material.Button
|
||||||
import androidx.compose.material.ButtonDefaults
|
import androidx.compose.material.ButtonDefaults
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.ChatEmptyStateView
|
||||||
|
|
||||||
data class CombinedConversation(
|
data class CombinedConversation(
|
||||||
val type: String, // "agent", "group", or "friend"
|
val type: String, // "agent", "group", or "friend"
|
||||||
@@ -230,22 +231,7 @@ fun AllChatListScreen() {
|
|||||||
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
|
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
|
||||||
|
|
||||||
if (isNetworkAvailable) {
|
if (isNetworkAvailable) {
|
||||||
Image(
|
ChatEmptyStateView()
|
||||||
painter = painterResource(id = R.mipmap.invalid_name_3),
|
|
||||||
contentDescription = "null data",
|
|
||||||
modifier = Modifier.size(120.dp)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.no_one_knocked_yet),
|
|
||||||
color = AppColors.text,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
fontWeight = FontWeight.W600,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
NetworkErrorContentCompact(
|
NetworkErrorContentCompact(
|
||||||
onReload = {
|
onReload = {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import androidx.compose.ui.graphics.Brush
|
|||||||
import androidx.compose.material.Button
|
import androidx.compose.material.Button
|
||||||
import androidx.compose.material.ButtonDefaults
|
import androidx.compose.material.ButtonDefaults
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.ChatEmptyStateView
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -85,22 +86,7 @@ fun FriendChatListScreen() {
|
|||||||
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
|
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
|
||||||
|
|
||||||
if (isNetworkAvailable) {
|
if (isNetworkAvailable) {
|
||||||
Image(
|
ChatEmptyStateView()
|
||||||
painter = painterResource(id = R.mipmap.invalid_name_3),
|
|
||||||
contentDescription = "null data",
|
|
||||||
modifier = Modifier.size(120.dp)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.no_one_knocked_yet),
|
|
||||||
color = AppColors.text,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
fontWeight = FontWeight.W600,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
NetworkErrorContentCompact(
|
NetworkErrorContentCompact(
|
||||||
onReload = {
|
onReload = {
|
||||||
@@ -279,43 +265,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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ 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
|
||||||
import com.aiosman.ravenow.ui.network.NetworkErrorContentCompact
|
import com.aiosman.ravenow.ui.network.NetworkErrorContentCompact
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.ChatEmptyStateView
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -80,22 +81,7 @@ fun GroupChatListScreen() {
|
|||||||
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
|
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
|
||||||
|
|
||||||
if (isNetworkAvailable) {
|
if (isNetworkAvailable) {
|
||||||
Image(
|
ChatEmptyStateView()
|
||||||
painter = painterResource(id = R.mipmap.invalid_name_3),
|
|
||||||
contentDescription = "null data",
|
|
||||||
modifier = Modifier.size(120.dp)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.no_one_knocked_yet),
|
|
||||||
color = AppColors.text,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
fontWeight = FontWeight.W600,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
NetworkErrorContentCompact(
|
NetworkErrorContentCompact(
|
||||||
onReload = {
|
onReload = {
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空状态缺省图组件
|
||||||
|
* 用于显示我的-动态、智能体、群聊无内容时的缺省图片和提示文本
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun EmptyStateView(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
contentDescription: String = "暂无内容",
|
||||||
|
text: String = stringResource(R.string.cosmos_awaits),
|
||||||
|
fontWeight: FontWeight = FontWeight.W600
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.l_empty_img),
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(width = 181.dp, height = 153.dp),
|
||||||
|
contentScale = ContentScale.Fit
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(9.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = AppColors.text,
|
||||||
|
fontWeight = fontWeight,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息页统一空状态
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun ChatEmptyStateView(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
contentDescription: String = "暂无会话",
|
||||||
|
text: String = stringResource(R.string.no_one_knocked_yet)
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.invalid_name_3),
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
modifier = Modifier.size(120.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
color = AppColors.text,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.W600,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -158,7 +158,8 @@ fun GalleryGrid(
|
|||||||
modifier = baseModifier
|
modifier = baseModifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
.padding(vertical = 60.dp),
|
.padding(vertical = 60.dp)
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
@@ -201,24 +202,8 @@ fun GalleryGrid(
|
|||||||
.padding(vertical = 60.dp),
|
.padding(vertical = 60.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Image(
|
EmptyStateView(
|
||||||
painter = painterResource(id = R.mipmap.l_empty_img),
|
contentDescription = "暂无图片"
|
||||||
contentDescription = "暂无图片",
|
|
||||||
modifier = Modifier
|
|
||||||
.size(width = 181.dp, height = 153.dp),
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(9.dp))
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.cosmos_awaits),
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = AppColors.text,
|
|
||||||
fontWeight = FontWeight.W600,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -16,15 +16,16 @@ import androidx.compose.foundation.layout.size
|
|||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
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.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
import androidx.compose.material.pullrefresh.pullRefresh
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.Text
|
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.LottieAnimation
|
||||||
import com.airbnb.lottie.compose.LottieCompositionSpec
|
import com.airbnb.lottie.compose.LottieCompositionSpec
|
||||||
import com.airbnb.lottie.compose.LottieConstants
|
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.AppStore
|
||||||
import com.aiosman.ravenow.data.api.ApiClient
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
|
import com.aiosman.ravenow.ui.network.ReloadButton
|
||||||
|
import com.aiosman.ravenow.utils.NetworkUtils.isNetworkAvailable
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -78,6 +81,7 @@ fun GroupChatEmptyContent(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
val viewModel = MyProfileViewModel
|
val viewModel = MyProfileViewModel
|
||||||
|
val networkAvailable = isNetworkAvailable(context)
|
||||||
|
|
||||||
// 如果查看其他用户的房间,固定使用全部类型(filterType = 0)
|
// 如果查看其他用户的房间,固定使用全部类型(filterType = 0)
|
||||||
val filterType = if (showSegments) selectedSegment else 0
|
val filterType = if (showSegments) selectedSegment else 0
|
||||||
@@ -133,32 +137,36 @@ fun GroupChatEmptyContent(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
// 空状态插图
|
// 空状态插图
|
||||||
EmptyStateIllustration()
|
EmptyStateIllustration(
|
||||||
|
isNetworkAvailable = networkAvailable,
|
||||||
|
onReload = {
|
||||||
|
MyProfileViewModel.ResetModel()
|
||||||
|
MyProfileViewModel.loadProfile(pullRefresh = true)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(9.dp))
|
Spacer(modifier = Modifier.height(9.dp))
|
||||||
|
|
||||||
// 空状态文本
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.cosmos_awaits),
|
|
||||||
fontSize = 16.sp,
|
|
||||||
fontWeight = FontWeight.SemiBold,
|
|
||||||
color = AppColors.text,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = listState,
|
state = listState,
|
||||||
modifier = nestedScrollModifier.fillMaxSize()
|
modifier = nestedScrollModifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
itemsIndexed(
|
// 网格布局:每行显示2个房间卡片
|
||||||
items = viewModel.rooms,
|
items(
|
||||||
key = { _, item -> item.id }
|
items = viewModel.rooms.chunked(2),
|
||||||
) { index, room ->
|
key = { rowRooms -> rowRooms.firstOrNull()?.id?.toString() ?: "" }
|
||||||
RoomItem(
|
) { rowRooms ->
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(bottom = 12.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
rowRooms.forEach { room ->
|
||||||
|
RoomCard(
|
||||||
room = room,
|
room = room,
|
||||||
onRoomClick = { roomEntity ->
|
onRoomClick = { roomEntity ->
|
||||||
// 导航到群聊聊天界面
|
// 导航到群聊聊天界面
|
||||||
@@ -167,14 +175,14 @@ fun GroupChatEmptyContent(
|
|||||||
name = roomEntity.name,
|
name = roomEntity.name,
|
||||||
avatar = roomEntity.avatar
|
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 +224,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
|
@Composable
|
||||||
fun RoomItem(
|
fun RoomItem(
|
||||||
room: RoomEntity,
|
room: RoomEntity,
|
||||||
@@ -229,7 +351,6 @@ fun RoomItem(
|
|||||||
val avatarUrl = if (room.avatar.isNotEmpty()) {
|
val avatarUrl = if (room.avatar.isNotEmpty()) {
|
||||||
"${ConstVars.BASE_SERVER}/api/v1/outside/${room.avatar}?token=${AppStore.token}"
|
"${ConstVars.BASE_SERVER}/api/v1/outside/${room.avatar}?token=${AppStore.token}"
|
||||||
} else {
|
} else {
|
||||||
// 如果头像为空,使用群头像接口
|
|
||||||
val groupIdBase64 = Base64.encodeToString(
|
val groupIdBase64 = Base64.encodeToString(
|
||||||
room.trtcType.toByteArray(),
|
room.trtcType.toByteArray(),
|
||||||
Base64.NO_WRAP
|
Base64.NO_WRAP
|
||||||
@@ -388,14 +509,43 @@ private fun SegmentButton(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EmptyStateIllustration() {
|
private fun EmptyStateIllustration(
|
||||||
Image(
|
isNetworkAvailable: Boolean,
|
||||||
painter = painterResource(id = R.mipmap.l_empty_img),
|
onReload: () -> Unit
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
if (isNetworkAvailable) {
|
||||||
|
EmptyStateView(
|
||||||
contentDescription = "空状态",
|
contentDescription = "空状态",
|
||||||
modifier = Modifier
|
fontWeight = FontWeight.SemiBold
|
||||||
.width(181.dp)
|
|
||||||
.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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -281,25 +281,8 @@ fun AgentEmptyContentWithSegments(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
if (isNetworkAvailable) {
|
if (isNetworkAvailable) {
|
||||||
Image(
|
EmptyStateView(
|
||||||
painter = painterResource(id = R.mipmap.l_empty_img),
|
contentDescription = "暂无Agent"
|
||||||
contentDescription = "暂无Agent",
|
|
||||||
modifier = Modifier
|
|
||||||
.size(width = 181.dp, height = 153.dp)
|
|
||||||
.align(Alignment.CenterHorizontally),
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(9.dp))
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.cosmos_awaits),
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = AppColors.text,
|
|
||||||
fontWeight = FontWeight.W600,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Image(
|
Image(
|
||||||
|
|||||||
@@ -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