首页UI调整
This commit is contained in:
@@ -18,8 +18,8 @@ import com.aiosman.ravenow.ui.favourite.FavouriteNoticeViewModel
|
||||
import com.aiosman.ravenow.ui.follower.FollowerNoticeViewModel
|
||||
import com.aiosman.ravenow.ui.index.IndexViewModel
|
||||
import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel
|
||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.dynamic.DynamicViewModel
|
||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.Explore
|
||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.ExploreViewModel
|
||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.hot.HotMomentViewModel
|
||||
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.timeline.TimelineMomentViewModel
|
||||
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
|
||||
@@ -152,7 +152,7 @@ object AppState {
|
||||
fun ReloadAppState(context: Context) {
|
||||
// 重置动态列表页面
|
||||
TimelineMomentViewModel.ResetModel()
|
||||
ExploreViewModel.ResetModel()
|
||||
DynamicViewModel.ResetModel()
|
||||
HotMomentViewModel.ResetModel()
|
||||
|
||||
// 重置我的页面
|
||||
|
||||
@@ -53,7 +53,7 @@ fun AgentCard(
|
||||
Box(
|
||||
modifier = Modifier.padding(start = 0.dp, end = 0.dp, top = 16.dp, bottom = 8.dp)
|
||||
.noRippleClickable {
|
||||
onClick ()
|
||||
onClick ()
|
||||
}
|
||||
) {
|
||||
Row(
|
||||
|
||||
@@ -110,11 +110,13 @@ fun HotAgent() {
|
||||
key = { idx -> idx }
|
||||
) { idx ->
|
||||
val agentItem = agentList[idx]
|
||||
AgentCard(agentEntity = agentItem,
|
||||
AgentCard(
|
||||
agentEntity = agentItem,
|
||||
onClick = {
|
||||
model.createSingleChat(agentItem.openId)
|
||||
model.goToChatAi(agentItem.openId,navController)
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// 加载更多指示器
|
||||
|
||||
@@ -27,13 +27,10 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.aiosman.ravenow.LocalAppTheme
|
||||
import com.aiosman.ravenow.LocalNavController
|
||||
import com.aiosman.ravenow.R
|
||||
import com.aiosman.ravenow.ui.composables.AgentCard
|
||||
import com.aiosman.ravenow.ui.navigateToChat
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
@@ -113,11 +110,14 @@ fun MineAgent() {
|
||||
key = { idx -> idx }
|
||||
) { idx ->
|
||||
val agentItem = agentList[idx]
|
||||
AgentCard(agentEntity = agentItem,
|
||||
AgentCard(
|
||||
agentEntity = agentItem,
|
||||
onClick = {
|
||||
model.createSingleChat(agentItem.openId)
|
||||
model.goToChatAi(agentItem.openId,navController)
|
||||
})
|
||||
},
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
// 加载更多指示器
|
||||
|
||||
@@ -228,10 +228,10 @@ fun MomentsList() {
|
||||
) {
|
||||
when (it) {
|
||||
0 -> {
|
||||
Dynamic()
|
||||
Explore()
|
||||
}
|
||||
1 -> {
|
||||
Explore()
|
||||
Dynamic()
|
||||
}
|
||||
|
||||
2 -> {
|
||||
|
||||
@@ -21,11 +21,86 @@ import com.aiosman.ravenow.ui.composables.MomentCard
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* 探索
|
||||
* 动态列表
|
||||
*/
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun Dynamic() {
|
||||
val model = DynamicViewModel
|
||||
var moments = model.moments
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
val state = rememberPullRefreshState(model.refreshing, onRefresh = {
|
||||
model.refreshPager(
|
||||
pullRefresh = true
|
||||
)
|
||||
})
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
// observe list scrolling
|
||||
val reachedBottom by remember {
|
||||
derivedStateOf {
|
||||
val lastVisibleItem = listState.layoutInfo.visibleItemsInfo.lastOrNull()
|
||||
lastVisibleItem?.index != 0 && lastVisibleItem?.index == listState.layoutInfo.totalItemsCount - 2
|
||||
}
|
||||
}
|
||||
|
||||
// load more if scrolled to bottom
|
||||
LaunchedEffect(reachedBottom) {
|
||||
if (reachedBottom) {
|
||||
model.loadMore()
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
model.refreshPager()
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
|
||||
) {
|
||||
Box(Modifier.pullRefresh(state)) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = listState
|
||||
) {
|
||||
items(
|
||||
moments.size,
|
||||
key = { idx -> idx }
|
||||
) { idx ->
|
||||
val momentItem = moments[idx] ?: return@items
|
||||
MomentCard(momentEntity = momentItem,
|
||||
onAddComment = {
|
||||
scope.launch {
|
||||
model.onAddComment(momentItem.id)
|
||||
}
|
||||
},
|
||||
onLikeClick = {
|
||||
scope.launch {
|
||||
if (momentItem.liked) {
|
||||
model.dislikeMoment(momentItem.id)
|
||||
} else {
|
||||
model.likeMoment(momentItem.id)
|
||||
}
|
||||
}
|
||||
},
|
||||
onFavoriteClick = {
|
||||
scope.launch {
|
||||
if (momentItem.isFavorite) {
|
||||
model.unfavoriteMoment(momentItem.id)
|
||||
} else {
|
||||
model.favoriteMoment(momentItem.id)
|
||||
}
|
||||
}
|
||||
},
|
||||
onFollowClick = {
|
||||
model.followAction(momentItem)
|
||||
},
|
||||
showFollowButton = true
|
||||
)
|
||||
}
|
||||
}
|
||||
PullRefreshIndicator(model.refreshing, state, Modifier.align(Alignment.TopCenter))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
package com.aiosman.ravenow.ui.index.tabs.moment.tabs.dynamic
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
|
||||
import com.aiosman.ravenow.ui.index.tabs.moment.BaseMomentModel
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
|
||||
object DynamicViewModel : ViewModel() {
|
||||
object DynamicViewModel : BaseMomentModel() {
|
||||
init {
|
||||
EventBus.getDefault().register(this)
|
||||
|
||||
}
|
||||
override fun extraArgs(): MomentLoaderExtraArgs {
|
||||
return MomentLoaderExtraArgs(explore = true)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,106 +1,790 @@
|
||||
package com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
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.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
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.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.aiosman.ravenow.ui.composables.MomentCard
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.draw.clip
|
||||
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.aiosman.ravenow.AppStore
|
||||
import com.aiosman.ravenow.LocalAppTheme
|
||||
import com.aiosman.ravenow.R
|
||||
import kotlinx.coroutines.launch
|
||||
import com.aiosman.ravenow.data.Room
|
||||
import com.aiosman.ravenow.data.Agent
|
||||
import com.aiosman.ravenow.data.api.ApiClient
|
||||
import com.aiosman.ravenow.ui.composables.AgentCard
|
||||
|
||||
// Banner数据类
|
||||
data class BannerItem(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val subtitle: String,
|
||||
val imageUrl: String,
|
||||
val backgroundImageUrl: String,
|
||||
val userCount: Int,
|
||||
val agentName: String
|
||||
) {
|
||||
companion object {
|
||||
fun fromRoom(room: Room): BannerItem {
|
||||
return BannerItem(
|
||||
id = room.id,
|
||||
title = room.name ?: "聊天室",
|
||||
subtitle = room.description ?: "欢迎加入我们的聊天室",
|
||||
imageUrl = room.avatar ?: "",
|
||||
backgroundImageUrl = "${ApiClient.BASE_API_URL+"/outside"}${room.recommendBanner}"+"?token="+"${AppStore.token}" ?: "",
|
||||
userCount = room.userCount,
|
||||
agentName = room.creator.profile.nickname
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Agent数据类
|
||||
data class AgentItem(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val desc: String,
|
||||
val avatar: String,
|
||||
val useCount: Int,
|
||||
val author: String
|
||||
) {
|
||||
companion object {
|
||||
fun fromAgent(agent: Agent): AgentItem {
|
||||
return AgentItem(
|
||||
id = agent.id,
|
||||
title = agent.title,
|
||||
desc = agent.desc,
|
||||
avatar = "${ApiClient.BASE_API_URL+"/outside"}${agent.avatar}"+"?token="+"${AppStore.token}",
|
||||
useCount = agent.useCount,
|
||||
author = agent.author
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态列表
|
||||
* 探索页面
|
||||
*/
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun Explore() {
|
||||
val model = ExploreViewModel
|
||||
var moments = model.moments
|
||||
|
||||
val AppColors = LocalAppTheme.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val state = rememberPullRefreshState(model.refreshing, onRefresh = {
|
||||
model.refreshPager(
|
||||
pullRefresh = true
|
||||
)
|
||||
})
|
||||
val listState = rememberLazyListState()
|
||||
val viewModel: ExploreViewModel = viewModel()
|
||||
|
||||
// observe list scrolling
|
||||
val reachedBottom by remember {
|
||||
derivedStateOf {
|
||||
val lastVisibleItem = listState.layoutInfo.visibleItemsInfo.lastOrNull()
|
||||
lastVisibleItem?.index != 0 && lastVisibleItem?.index == listState.layoutInfo.totalItemsCount - 2
|
||||
// 模拟刷新状态
|
||||
var isRefreshing by remember { mutableStateOf(false) }
|
||||
|
||||
// 监听ViewModel的刷新状态
|
||||
LaunchedEffect(viewModel.isRefreshing) {
|
||||
isRefreshing = viewModel.isRefreshing
|
||||
}
|
||||
|
||||
// 处理刷新
|
||||
LaunchedEffect(isRefreshing) {
|
||||
if (isRefreshing) {
|
||||
viewModel.refreshBannerData()
|
||||
viewModel.refreshAgentData()
|
||||
// 模拟网络请求延迟
|
||||
kotlinx.coroutines.delay(2000)
|
||||
isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
// load more if scrolled to bottom
|
||||
LaunchedEffect(reachedBottom) {
|
||||
if (reachedBottom) {
|
||||
model.loadMore()
|
||||
val pullRefreshState = rememberPullRefreshState(
|
||||
refreshing = isRefreshing,
|
||||
onRefresh = {
|
||||
scope.launch {
|
||||
isRefreshing = true
|
||||
viewModel.refreshBannerData()
|
||||
viewModel.refreshAgentData()
|
||||
// 模拟网络请求延迟
|
||||
kotlinx.coroutines.delay(2000)
|
||||
isRefreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
model.refreshPager()
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
)
|
||||
|
||||
) {
|
||||
Box(Modifier.pullRefresh(state)) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = listState
|
||||
@Composable
|
||||
fun AgentCard2(agentItem: AgentItem) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
items(
|
||||
moments.size,
|
||||
key = { idx -> idx }
|
||||
) { idx ->
|
||||
val momentItem = moments[idx] ?: return@items
|
||||
MomentCard(momentEntity = momentItem,
|
||||
onAddComment = {
|
||||
scope.launch {
|
||||
model.onAddComment(momentItem.id)
|
||||
}
|
||||
},
|
||||
onLikeClick = {
|
||||
scope.launch {
|
||||
if (momentItem.liked) {
|
||||
model.dislikeMoment(momentItem.id)
|
||||
} else {
|
||||
model.likeMoment(momentItem.id)
|
||||
}
|
||||
}
|
||||
},
|
||||
onFavoriteClick = {
|
||||
scope.launch {
|
||||
if (momentItem.isFavorite) {
|
||||
model.unfavoriteMoment(momentItem.id)
|
||||
} else {
|
||||
model.favoriteMoment(momentItem.id)
|
||||
}
|
||||
}
|
||||
},
|
||||
onFollowClick = {
|
||||
model.followAction(momentItem)
|
||||
},
|
||||
showFollowButton = true
|
||||
// 左侧头像
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.background(Color(0xFFF5F5F5), RoundedCornerShape(24.dp)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (agentItem.avatar.isNotEmpty()) {
|
||||
CustomAsyncImage(
|
||||
imageUrl = agentItem.avatar,
|
||||
contentDescription = "Agent头像",
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.clip(RoundedCornerShape(24.dp)),
|
||||
contentScale = androidx.compose.ui.layout.ContentScale.Crop
|
||||
)
|
||||
} else {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_agent),
|
||||
contentDescription = "默认头像",
|
||||
modifier = Modifier.size(24.dp),
|
||||
colorFilter = ColorFilter.tint(AppColors.secondaryText)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
|
||||
// 中间文字内容
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(end = 8.dp)
|
||||
) {
|
||||
// 标题
|
||||
Text(
|
||||
text = agentItem.title,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
|
||||
color = AppColors.text,
|
||||
maxLines = 1,
|
||||
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
// 描述
|
||||
Text(
|
||||
text = agentItem.desc,
|
||||
fontSize = 12.sp,
|
||||
color = AppColors.secondaryText,
|
||||
maxLines = 2,
|
||||
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
// 右侧聊天按钮
|
||||
androidx.compose.material3.Button(
|
||||
onClick = {
|
||||
// 聊天逻辑
|
||||
},
|
||||
colors = androidx.compose.material3.ButtonDefaults.buttonColors(
|
||||
containerColor = AppColors.main,
|
||||
contentColor = Color.White
|
||||
),
|
||||
shape = RoundedCornerShape(20.dp),
|
||||
modifier = Modifier.size(width = 60.dp, height = 32.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "聊天",
|
||||
fontSize = 12.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
|
||||
)
|
||||
}
|
||||
}
|
||||
PullRefreshIndicator(model.refreshing, state, Modifier.align(Alignment.TopCenter))
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AgentPage(agentItems: List<AgentItem>, page: Int) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 0.dp)
|
||||
) {
|
||||
// 显示3个agent
|
||||
agentItems.forEachIndexed { index, agentItem ->
|
||||
AgentCard2(agentItem = agentItem)
|
||||
if (index < agentItems.size - 1) {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun AgentViewPagerSection(agentItems: List<AgentItem>) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
|
||||
// 每页显示3个agent
|
||||
val itemsPerPage = 3
|
||||
val totalPages = (agentItems.size + itemsPerPage - 1) / itemsPerPage
|
||||
|
||||
if (totalPages > 0) {
|
||||
val pagerState = rememberPagerState(pageCount = { totalPages })
|
||||
|
||||
Column {
|
||||
// Agent内容
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) { page ->
|
||||
AgentPage(
|
||||
agentItems = agentItems.drop(page * itemsPerPage).take(itemsPerPage),
|
||||
page = page
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 指示器
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 12.dp),
|
||||
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.Center
|
||||
) {
|
||||
repeat(totalPages) { index ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 4.dp)
|
||||
.size(3.dp)
|
||||
.background(
|
||||
color = if (pagerState.currentPage == index) AppColors.main else AppColors.secondaryText.copy(alpha = 0.3f),
|
||||
shape = androidx.compose.foundation.shape.CircleShape
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HotChatRoomCard(roomItem: BannerItem) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.width(160.dp)
|
||||
.height(80.dp),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
elevation = androidx.compose.material3.CardDefaults.cardElevation(defaultElevation = 4.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// 左侧图标
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.background(
|
||||
color = when (roomItem.id % 5) {
|
||||
0 -> Color(0xFFE3F2FD) // 浅蓝色
|
||||
1 -> Color(0xFFF3E5F5) // 浅紫色
|
||||
2 -> Color(0xFFFFF3E0) // 浅橙色
|
||||
3 -> Color(0xFFFCE4EC) // 浅粉色
|
||||
else -> Color(0xFFFFF8E1) // 浅黄色
|
||||
},
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.rider_pro_group_chat),
|
||||
contentDescription = "chat",
|
||||
modifier = Modifier.size(16.dp),
|
||||
colorFilter = ColorFilter.tint(Color.White)
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
|
||||
// 右侧文字
|
||||
Text(
|
||||
text = roomItem.title,
|
||||
fontSize = 12.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W500,
|
||||
color = AppColors.text,
|
||||
maxLines = 2,
|
||||
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HotChatRoomSection(roomItems: List<BannerItem>) {
|
||||
LazyRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
items(roomItems.size) { index ->
|
||||
HotChatRoomCard(roomItem = roomItems[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun BannerCard(bannerItem: BannerItem) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
val context = LocalContext.current
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 0.dp),
|
||||
shape = RoundedCornerShape(20.dp),
|
||||
elevation = androidx.compose.material3.CardDefaults.cardElevation(defaultElevation = 0.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
// 背景图片
|
||||
if (bannerItem.backgroundImageUrl.isNotEmpty()) {
|
||||
CustomAsyncImage(
|
||||
imageUrl = bannerItem.backgroundImageUrl,
|
||||
contentDescription = "背景图片",
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentScale = androidx.compose.ui.layout.ContentScale.Crop
|
||||
)
|
||||
} else {
|
||||
// 如果没有背景图片,使用默认渐变背景
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
brush = androidx.compose.ui.graphics.Brush.linearGradient(
|
||||
colors = listOf(
|
||||
Color(0xFF4CAF50),
|
||||
Color(0xFF4CAF50).copy(alpha = 0.8f)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 内容
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(20.dp),
|
||||
verticalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween
|
||||
) {
|
||||
// 顶部:用户数量
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.rider_pro_nav_profile),
|
||||
contentDescription = "chat",
|
||||
modifier = Modifier.size(16.dp),
|
||||
colorFilter = ColorFilter.tint(Color.White)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = "${bannerItem.userCount}人在聊",
|
||||
fontSize = 12.sp,
|
||||
color = Color.White,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
|
||||
)
|
||||
}
|
||||
|
||||
// 底部:标题和描述
|
||||
Column {
|
||||
Text(
|
||||
text = bannerItem.title,
|
||||
fontSize = 24.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.Bold,
|
||||
color = Color.White
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = bannerItem.subtitle,
|
||||
fontSize = 14.sp,
|
||||
color = Color.White.copy(alpha = 0.9f),
|
||||
maxLines = 2,
|
||||
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// Agent信息
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.background(Color.White.copy(alpha = 0.2f), RoundedCornerShape(16.dp)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = bannerItem.agentName.firstOrNull().toString(),
|
||||
fontSize = 14.sp,
|
||||
color = Color.White,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.Bold
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = bannerItem.agentName,
|
||||
fontSize = 14.sp,
|
||||
color = Color.White,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
|
||||
)
|
||||
}
|
||||
|
||||
// 进入按钮
|
||||
androidx.compose.material3.Button(
|
||||
onClick = {
|
||||
// 进入房间逻辑
|
||||
},
|
||||
colors = androidx.compose.material3.ButtonDefaults.buttonColors(
|
||||
containerColor = Color.White.copy(alpha = 0.9f),
|
||||
contentColor = Color(0xFF4CAF50)
|
||||
),
|
||||
shape = RoundedCornerShape(20.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "进入",
|
||||
fontSize = 14.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W600
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.pullRefresh(pullRefreshState)
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = androidx.compose.foundation.layout.PaddingValues(16.dp)
|
||||
) {
|
||||
|
||||
|
||||
// 可以添加更多不同高度的内容项
|
||||
// 四个圆角布局
|
||||
item {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 6.dp),
|
||||
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceEvenly
|
||||
) {
|
||||
// 第一个
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(64.dp)
|
||||
.background(Color(0XFFC686FF), RoundedCornerShape(24.dp)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_group),
|
||||
contentDescription = "创建群聊",
|
||||
modifier = Modifier.size(24.dp),
|
||||
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.size(8.dp))
|
||||
Text(
|
||||
text = "创建群聊",
|
||||
fontSize = 12.sp,
|
||||
color = AppColors.text,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
|
||||
)
|
||||
}
|
||||
|
||||
// 第二个
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(64.dp)
|
||||
.background(Color(0xFF94f9f2), RoundedCornerShape(24.dp)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_agent),
|
||||
contentDescription = "创建Agent",
|
||||
modifier = Modifier.size(24.dp),
|
||||
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.size(8.dp))
|
||||
Text(
|
||||
text = "创建Agent",
|
||||
fontSize = 12.sp,
|
||||
color = AppColors.text,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
|
||||
)
|
||||
}
|
||||
|
||||
// 第三个
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(64.dp)
|
||||
.background(Color(0xFFfafd5d), RoundedCornerShape(24.dp)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_release),
|
||||
contentDescription = "发布动态",
|
||||
modifier = Modifier.size(24.dp),
|
||||
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.size(8.dp))
|
||||
Text(
|
||||
text = "发布动态",
|
||||
fontSize = 12.sp,
|
||||
color = AppColors.text,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
|
||||
)
|
||||
}
|
||||
|
||||
// 第四个
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(64.dp)
|
||||
.background(Color(0xFFfc724b), RoundedCornerShape(24.dp)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_fire),
|
||||
contentDescription = "热门Agents",
|
||||
modifier = Modifier.size(24.dp),
|
||||
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.size(8.dp))
|
||||
Text(
|
||||
text = "热门Agents",
|
||||
fontSize = 12.sp,
|
||||
color = AppColors.text,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun BannerSection(bannerItems: List<BannerItem>) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val pagerState = rememberPagerState(pageCount = { bannerItems.size })
|
||||
|
||||
Column {
|
||||
// Banner内容
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(362.dp)
|
||||
) {
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) { page ->
|
||||
val bannerItem = bannerItems[page]
|
||||
BannerCard(bannerItem = bannerItem)
|
||||
}
|
||||
}
|
||||
|
||||
// 指示器
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 12.dp),
|
||||
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.Center
|
||||
) {
|
||||
bannerItems.forEachIndexed { index, _ ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 4.dp)
|
||||
.size(3.dp)
|
||||
.background(
|
||||
color = if (pagerState.currentPage == index) AppColors.main else AppColors.secondaryText.copy(alpha = 0.3f),
|
||||
shape = androidx.compose.foundation.shape.CircleShape
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 第二块区域:Banner
|
||||
item {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp)
|
||||
) {
|
||||
// 标题
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_fire2),
|
||||
contentDescription = "fire",
|
||||
modifier = Modifier.size(28.dp),
|
||||
colorFilter = ColorFilter.tint(Color(0xFFEF4444))
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = "正在高能对话中",
|
||||
fontSize = 16.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
|
||||
color = AppColors.text
|
||||
)
|
||||
}
|
||||
|
||||
// Banner
|
||||
BannerSection(bannerItems = viewModel.bannerItems)
|
||||
}
|
||||
}
|
||||
|
||||
// 第三块区域:推荐Agent
|
||||
item {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp)
|
||||
) {
|
||||
// 标题
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_agent2),
|
||||
contentDescription = "agent",
|
||||
modifier = Modifier.size(28.dp),
|
||||
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = "推荐Agent",
|
||||
fontSize = 16.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
|
||||
color = AppColors.text
|
||||
)
|
||||
}
|
||||
|
||||
// Agent ViewPager
|
||||
AgentViewPagerSection(agentItems = viewModel.agentItems)
|
||||
}
|
||||
}
|
||||
|
||||
// 第四块区域:热门聊天室
|
||||
item {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp)
|
||||
) {
|
||||
// 标题
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_group),
|
||||
contentDescription = "chat room",
|
||||
modifier = Modifier.size(16.dp),
|
||||
colorFilter = ColorFilter.tint(Color(0xFFFFA500))
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = "热门聊天室",
|
||||
fontSize = 16.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
|
||||
color = AppColors.text
|
||||
)
|
||||
}
|
||||
|
||||
// 热门聊天室列表
|
||||
//HotChatRoomSection(roomItems = viewModel.bannerItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PullRefreshIndicator(
|
||||
refreshing = isRefreshing,
|
||||
state = pullRefreshState,
|
||||
modifier = Modifier.align(Alignment.TopCenter)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,126 @@
|
||||
package com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre
|
||||
|
||||
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
|
||||
import com.aiosman.ravenow.ui.index.tabs.moment.BaseMomentModel
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.aiosman.ravenow.data.Room
|
||||
import com.aiosman.ravenow.data.Agent
|
||||
import com.aiosman.ravenow.data.api.ApiClient
|
||||
import com.aiosman.ravenow.data.api.RaveNowAPI
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ExploreViewModel : ViewModel() {
|
||||
|
||||
private val apiClient: RaveNowAPI = ApiClient.api
|
||||
|
||||
var bannerItems by mutableStateOf<List<BannerItem>>(emptyList())
|
||||
private set
|
||||
|
||||
var agentItems by mutableStateOf<List<AgentItem>>(emptyList())
|
||||
private set
|
||||
|
||||
var isLoading by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
var isRefreshing by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
var errorMessage by mutableStateOf<String?>(null)
|
||||
private set
|
||||
|
||||
object ExploreViewModel : BaseMomentModel() {
|
||||
init {
|
||||
EventBus.getDefault().register(this)
|
||||
|
||||
loadBannerData()
|
||||
loadAgentData()
|
||||
}
|
||||
override fun extraArgs(): MomentLoaderExtraArgs {
|
||||
return MomentLoaderExtraArgs(explore = true)
|
||||
|
||||
fun refreshBannerData() {
|
||||
viewModelScope.launch {
|
||||
isRefreshing = true
|
||||
errorMessage = null
|
||||
try {
|
||||
val response = apiClient.getRooms(page = 1, pageSize = 12, isRecommended = 1)
|
||||
if (response.isSuccessful) {
|
||||
val rooms = response.body()?.list ?: emptyList()
|
||||
bannerItems = rooms.map { room ->
|
||||
BannerItem.fromRoom(room)
|
||||
}
|
||||
} else {
|
||||
errorMessage = "获取数据失败: ${response.code()}"
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
errorMessage = "网络请求失败: ${e.message}"
|
||||
} finally {
|
||||
isRefreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshAgentData() {
|
||||
viewModelScope.launch {
|
||||
isRefreshing = true
|
||||
errorMessage = null
|
||||
try {
|
||||
val response = apiClient.getAgent(page = 1, pageSize = 20, withWorkflow = 1)
|
||||
if (response.isSuccessful) {
|
||||
val agents = response.body()?.data?.list ?: emptyList()
|
||||
agentItems = agents.map { agent ->
|
||||
AgentItem.fromAgent(agent)
|
||||
}
|
||||
} else {
|
||||
errorMessage = "获取Agent数据失败: ${response.code()}"
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
errorMessage = "网络请求失败: ${e.message}"
|
||||
} finally {
|
||||
isRefreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadBannerData() {
|
||||
viewModelScope.launch {
|
||||
isLoading = true
|
||||
errorMessage = null
|
||||
try {
|
||||
val response = apiClient.getRooms(page = 1, pageSize = 10, isRecommended = 1)
|
||||
if (response.isSuccessful) {
|
||||
val rooms = response.body()?.list ?: emptyList()
|
||||
bannerItems = rooms.map { room ->
|
||||
BannerItem.fromRoom(room)
|
||||
}
|
||||
} else {
|
||||
errorMessage = "获取数据失败: ${response.code()}"
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
errorMessage = "网络请求失败: ${e.message}"
|
||||
} finally {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadAgentData() {
|
||||
viewModelScope.launch {
|
||||
isLoading = true
|
||||
errorMessage = null
|
||||
try {
|
||||
val response = apiClient.getAgent(page = 1, pageSize = 20, withWorkflow = 1)
|
||||
if (response.isSuccessful) {
|
||||
val agents = response.body()?.data?.list ?: emptyList()
|
||||
agentItems = agents.map { agent ->
|
||||
AgentItem.fromAgent(agent)
|
||||
}
|
||||
} else {
|
||||
errorMessage = "获取Agent数据失败: ${response.code()}"
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
errorMessage = "网络请求失败: ${e.message}"
|
||||
} finally {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
23
app/src/main/res/drawable/rider_pro_group_chat.xml
Normal file
23
app/src/main/res/drawable/rider_pro_group_chat.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#110C13"
|
||||
android:strokeWidth="1.432"
|
||||
android:strokeLineCap="round"
|
||||
android:pathData="M8.804 5.458a3.58 3.58 0 0 1 3.074-1.046l5.454 0.797 c2.008 0.293 3.407 2.224 3.125 4.312l-1.022 7.56-1.167-0.17" />
|
||||
<path
|
||||
android:fillColor="#110C13"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M6.494 14.375 7.348-0.04-0.01 1.907-7.349 0.04 z" />
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#110C13"
|
||||
android:strokeWidth="1.432"
|
||||
android:pathData="M6.77 8.113 5.171-0.756a3.818 3.818 0 0 1 4.335 3.266l0.51 3.775a3.818 3.818 0 0 1-3.23 4.289L4.565 20 3.54 12.402a3.818 3.818 0 0 1 3.23-4.29z" />
|
||||
</vector>
|
||||
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_agent.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_agent.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 636 B |
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_agent2.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_agent2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 608 B |
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_fire.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_fire.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 826 B |
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_fire2.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_fire2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 440 B |
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_group.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_group.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 816 B |
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_release.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_release.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 627 B |
Reference in New Issue
Block a user