修改若干bug、调整动态标签栏、添加文本等

修复修改用户头像以及壁纸不保存,头像仍然修改成功

动态-新闻界面暗色模式调整

新增动态标签栏选中标签时会有文本变大效果

搜索后的动态界面增加点赞/收藏/评论/转发动态按钮

修复搜索智能体后点击智能体不能跳转至智能体主页

修复进入消息-全部列表,消息界面显示为空

我的派币-历史记录添加文本资源
This commit is contained in:
2025-11-14 17:30:51 +08:00
parent 6d38b3c549
commit f981efd58d
14 changed files with 416 additions and 127 deletions

View File

@@ -1,6 +1,8 @@
package com.aiosman.ravenow.data
import android.content.Context
import com.aiosman.ravenow.AppStore
import com.aiosman.ravenow.R
import com.aiosman.ravenow.data.api.ApiClient
import com.aiosman.ravenow.data.api.DictItem
import com.aiosman.ravenow.data.api.PointsBalance
@@ -370,27 +372,29 @@ object PointService {
}
/**
* 获取变更原因的中文描述
* 获取变更原因的描述(支持多语言)
*
* @param context Context 用于获取资源
* @param reason 变更原因代码
* @return 中文描述
* @return 本地化描述
*/
fun getReasonDescription(reason: String): String {
return when (reason) {
ChangeReason.EARN_REGISTER -> "新用户注册奖励"
ChangeReason.EARN_DAILY -> "每日签到奖励"
ChangeReason.EARN_TASK -> "任务完成奖励"
ChangeReason.EARN_INVITE -> "邀请好友奖励"
ChangeReason.EARN_RECHARGE -> "充值获得"
ChangeReason.SPEND_GROUP_CREATE -> "创建群聊"
ChangeReason.SPEND_GROUP_EXPAND -> "扩容群聊"
ChangeReason.SPEND_AGENT_PRIVATE -> "Agent 私密模式"
ChangeReason.SPEND_AGENT_MEMORY -> "Agent 记忆添加"
ChangeReason.SPEND_ROOM_MEMORY -> "房间记忆添加"
ChangeReason.SPEND_CHAT_BACKGROUND -> "自定义聊天背景"
ChangeReason.SPEND_SCHEDULE_EVENT -> "定时事件解锁"
else -> reason // 未知原因,返回原始代码
fun getReasonDescription(context: Context, reason: String): String {
val resourceId = when (reason) {
ChangeReason.EARN_REGISTER -> R.string.earn_register
ChangeReason.EARN_DAILY -> R.string.earn_daily
ChangeReason.EARN_TASK -> R.string.earn_task
ChangeReason.EARN_INVITE -> R.string.earn_invite
ChangeReason.EARN_RECHARGE -> R.string.earn_recharge
ChangeReason.SPEND_GROUP_CREATE -> R.string.spend_group_create
ChangeReason.SPEND_GROUP_EXPAND -> R.string.spend_group_expand
ChangeReason.SPEND_AGENT_PRIVATE -> R.string.spend_agent_private
ChangeReason.SPEND_AGENT_MEMORY -> R.string.spend_agent_memory
ChangeReason.SPEND_ROOM_MEMORY -> R.string.spend_room_memory
ChangeReason.SPEND_CHAT_BACKGROUND -> R.string.spend_chat_background
ChangeReason.SPEND_SCHEDULE_EVENT -> R.string.spend_schedule_event
else -> null
}
return resourceId?.let { context.getString(it) } ?: reason // 未知原因,返回原始代码
}
/**

View File

@@ -31,7 +31,12 @@ object AccountEditViewModel : ViewModel() {
// 本地扩展字段
var mbti by mutableStateOf<String?>(null)
var zodiac by mutableStateOf<String?>(null)
suspend fun reloadProfile(updateTrtcProfile:Boolean = false) {
// 保存原始值,用于取消时恢复
private var originalName: String = ""
private var originalBio: String = ""
private var originalMbti: String? = null
private var originalZodiac: String? = null
suspend fun reloadProfile(updateTrtcProfile:Boolean = false, clearCroppedBitmap: Boolean = false) {
Log.d("AccountEditViewModel", "reloadProfile: 开始加载用户资料")
isLoading = true
try {
@@ -41,13 +46,23 @@ object AccountEditViewModel : ViewModel() {
profile = it
name = it.nickName
bio = it.bio
// 清除之前裁剪的图片
croppedBitmap = null
// 保存原始值,用于取消时恢复
originalName = it.nickName
originalBio = it.bio
// 只在明确要求时清除之前裁剪的图片(例如保存成功后)
if (clearCroppedBitmap) {
croppedBitmap = null
}
// 读取本地扩展字段
try {
val uid = it.id // 使用 profile 的 id确保非空
mbti = com.aiosman.ravenow.AppStore.getUserMbti(uid)
zodiac = com.aiosman.ravenow.AppStore.getUserZodiac(uid)
val loadedMbti = com.aiosman.ravenow.AppStore.getUserMbti(uid)
val loadedZodiac = com.aiosman.ravenow.AppStore.getUserZodiac(uid)
mbti = loadedMbti
zodiac = loadedZodiac
// 保存原始值
originalMbti = loadedMbti
originalZodiac = loadedZodiac
} catch (_: Exception) { }
if (updateTrtcProfile) {
TrtcHelper.updateTrtcProfile(
@@ -69,12 +84,15 @@ object AccountEditViewModel : ViewModel() {
}
fun resetToOriginalData() {
profile?.let {
name = it.nickName
bio = it.bio
// 清除之前裁剪的图片
croppedBitmap = null
}
// 恢复所有字段到原始值
name = originalName
bio = originalBio
mbti = originalMbti
zodiac = originalZodiac
// 清除之前裁剪的图片和壁纸
croppedBitmap = null
bannerImageUrl = null
bannerFile = null
}
@@ -129,8 +147,8 @@ object AccountEditViewModel : ViewModel() {
// 清除背景图状态
bannerImageUrl = null
bannerFile = null
// 刷新用户资料
reloadProfile()
// 刷新用户资料,保存成功后清除裁剪的图片
reloadProfile(clearCroppedBitmap = true)
// 刷新个人资料页面的用户资料
MyProfileViewModel.loadUserProfile()
}

View File

@@ -74,6 +74,7 @@ import com.aiosman.ravenow.ConstVars
import com.aiosman.ravenow.ui.composables.pickupAndCompressLauncher
import android.widget.Toast
import java.io.File
import androidx.activity.compose.BackHandler
/**
* 编辑用户资料界面
@@ -171,6 +172,13 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
model.reloadProfile()
}
// 处理系统返回键
BackHandler {
// 用户未保存直接返回,恢复所有字段到原始值
model.resetToOriginalData()
navController.navigateUp()
}
// 设置状态栏为透明,根据暗色模式决定图标颜色
val systemUiController = rememberSystemUiController()
LaunchedEffect(Unit) {
@@ -291,6 +299,8 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
.clip(CircleShape)
.background(Color.White.copy(alpha = 0.3f))
.noRippleClickable {
// 用户未保存直接返回,恢复所有字段到原始值
model.resetToOriginalData()
navController.navigateUp()
}
.align(Alignment.CenterStart),

View File

@@ -6,8 +6,10 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -15,10 +17,14 @@ import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.LocalAppTheme
@@ -75,30 +81,51 @@ fun UnderlineTabItem(
) {
val AppColors = LocalAppTheme.current
// 动画化字体大小和padding
val animatedFontSize by animateFloatAsState(
targetValue = if (isSelected) 17f else 15f,
animationSpec = tween(durationMillis = 200),
label = "fontSize"
)
val animatedPadding by animateDpAsState(
targetValue = if (isSelected) 20.dp else 16.dp,
animationSpec = tween(durationMillis = 200),
label = "padding"
)
Column(
modifier = modifier
.noRippleClickable { onClick() },
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = text,
fontSize = 15.sp,
fontWeight = FontWeight.ExtraBold,
color = if (isSelected) AppColors.text else AppColors.text.copy(alpha = 0.6f),
modifier = Modifier.padding(horizontal = 16.dp).padding(top = 13.dp)
)
Box(
modifier = Modifier
.padding(horizontal = animatedPadding)
.padding(top = 13.dp, bottom = 0.dp),
contentAlignment = Alignment.BottomCenter
) {
Text(
text = text,
fontSize = animatedFontSize.sp,
fontWeight = FontWeight.ExtraBold,
color = if (isSelected) AppColors.text else AppColors.text.copy(alpha = 0.6f),
textAlign = androidx.compose.ui.text.style.TextAlign.Center
)
}
// 选中状态下显示图标
Box(
modifier = Modifier.size(24.dp),
contentAlignment = Alignment.Center
) {
if (isSelected) {
if (isSelected) {
Box(
modifier = Modifier
.size(24.dp)
.offset(y = (-4).dp),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(id = R.mipmap.underline),
contentDescription = "selected indicator",
modifier = Modifier.fillMaxSize()
)
}
}

View File

@@ -72,6 +72,8 @@ fun ImageCropScreen() {
}
}
if (uri == null) {
// 用户取消图片选择,清除已裁剪的图片
AccountEditViewModel.croppedBitmap = null
navController.popBackStack()
}
}
@@ -103,6 +105,8 @@ fun ImageCropScreen() {
painter = painterResource(R.drawable.rider_pro_back_icon),
contentDescription = null,
modifier = Modifier.clickable {
// 用户取消头像选择,清除已裁剪的图片
AccountEditViewModel.croppedBitmap = null
navController.popBackStack()
},
colorFilter = ColorFilter.tint(Color.White)
@@ -119,11 +123,9 @@ fun ImageCropScreen() {
val bitmap = it.onCrop()
// 专门处理个人资料头像
// 只设置裁剪后的图片,不立即上传,等待用户在编辑资料界面点击保存
AccountEditViewModel.croppedBitmap = bitmap
AccountEditViewModel.viewModelScope.launch {
AccountEditViewModel.updateUserProfile(context)
navController.popBackStack()
}
navController.popBackStack()
}
}
)

View File

@@ -121,35 +121,88 @@ fun AllChatListScreen() {
var isLoading by remember { mutableStateOf(false) }
var error by remember { mutableStateOf<String?>(null) }
// 监听各个 ViewModel 的列表变化
val agentChatList = AgentChatListViewModel.agentChatList
val groupChatList = GroupChatListViewModel.groupChatList
val friendChatList = FriendChatListViewModel.friendChatList
// 当列表变化时,自动更新合并列表
LaunchedEffect(agentChatList, groupChatList, friendChatList) {
val combinedList = mutableListOf<CombinedConversation>()
agentChatList.forEach { agent ->
combinedList.add(CombinedConversation(type = "agent", agentConversation = agent))
}
groupChatList.forEach { group ->
combinedList.add(CombinedConversation(type = "group", groupConversation = group))
}
friendChatList.forEach { friend ->
val isDuplicate = combinedList.any {
it.type == "agent" && it.agentConversation?.trtcUserId == friend.trtcUserId
}
if (!isDuplicate) {
combinedList.add(CombinedConversation(type = "friend", friendConversation = friend))
}
}
// 按最后消息时间排序
val sortedList = combinedList.sortedByDescending {
it.lastMessageTime
}
allConversations = sortedList
}
// 监听加载状态
val isAnyLoading = AgentChatListViewModel.isLoading ||
GroupChatListViewModel.isLoading ||
FriendChatListViewModel.isLoading
// 当加载状态变化时,更新 isLoading
LaunchedEffect(isAnyLoading) {
if (isAnyLoading) {
// 如果有任何数据正在加载,确保显示加载状态
if (!isLoading) {
isLoading = true
}
} else {
// 所有数据加载完成
if (isLoading) {
isLoading = false
}
}
}
val state = rememberPullRefreshState(
refreshing = refreshing,
onRefresh = {
refreshing = true
refreshAllData(context,
onSuccess = { conversations ->
allConversations = conversations
refreshing = false
},
onError = { errorMsg ->
error = errorMsg
refreshing = false
}
)
// 刷新所有类型的数据
AgentChatListViewModel.refreshPager(pullRefresh = true, context = context)
GroupChatListViewModel.refreshPager(pullRefresh = true, context = context)
FriendChatListViewModel.refreshPager(pullRefresh = true, context = context)
}
)
// 监听刷新状态
LaunchedEffect(AgentChatListViewModel.refreshing, GroupChatListViewModel.refreshing, FriendChatListViewModel.refreshing) {
val isAnyRefreshing = AgentChatListViewModel.refreshing ||
GroupChatListViewModel.refreshing ||
FriendChatListViewModel.refreshing
if (!isAnyRefreshing && refreshing) {
refreshing = false
}
}
LaunchedEffect(Unit) {
isLoading = true
refreshAllData(context,
onSuccess = { conversations ->
allConversations = conversations
isLoading = false
},
onError = { errorMsg ->
error = errorMsg
isLoading = false
}
)
// 初始化加载所有类型的数据
AgentChatListViewModel.refreshPager(context = context)
GroupChatListViewModel.refreshPager(context = context)
FriendChatListViewModel.refreshPager(context = context)
}
Column(
@@ -235,16 +288,10 @@ fun AllChatListScreen() {
ReloadButton(
onClick = {
isLoading = true
refreshAllData(context,
onSuccess = { conversations ->
allConversations = conversations
isLoading = false
},
onError = { errorMsg ->
error = errorMsg
isLoading = false
}
)
// 重新加载所有类型的数据
AgentChatListViewModel.refreshPager(context = context)
GroupChatListViewModel.refreshPager(context = context)
FriendChatListViewModel.refreshPager(context = context)
}
)
}
@@ -363,44 +410,3 @@ fun AllChatListScreen() {
}
}
fun refreshAllData(
context: android.content.Context,
onSuccess: (List<CombinedConversation>) -> Unit,
onError: (String) -> Unit
) {
try {
// 同时刷新所有类型的数据
AgentChatListViewModel.refreshPager(context = context)
GroupChatListViewModel.refreshPager(context = context)
FriendChatListViewModel.refreshPager(context = context)
val combinedList = mutableListOf<CombinedConversation>()
AgentChatListViewModel.agentChatList.forEach { agent ->
combinedList.add(CombinedConversation(type = "agent", agentConversation = agent))
}
GroupChatListViewModel.groupChatList.forEach { group ->
combinedList.add(CombinedConversation(type = "group", groupConversation = group))
}
FriendChatListViewModel.friendChatList.forEach { friend ->
val isDuplicate = combinedList.any {//判断重复
it.type == "agent" && it.agentConversation?.trtcUserId == friend.trtcUserId
}
if (!isDuplicate) {
combinedList.add(CombinedConversation(type = "friend", friendConversation = friend))
}
}
// 按最后消息时间排序
val sortedList = combinedList.sortedByDescending {
it.lastMessageTime
}
onSuccess(sortedList)
} catch (e: Exception) {
onError("刷新数据失败: ${e.message}")
}
}

View File

@@ -104,7 +104,7 @@ fun MomentsList(
Row(
modifier = Modifier
.fillMaxWidth()
.height(44.dp)
.height(54.dp)
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically

View File

@@ -390,7 +390,8 @@ fun NewsItem(
NewsActionButton(
icon = if (moment.isFavorite) R.mipmap.icon_variant_2 else R.mipmap.icon_collect,
count = moment.favoriteCount.toString(),
isActive = moment.isFavorite,
isActive = false, // 收藏后不使用红色滤镜,保持图标原本颜色
keepOriginalColor = moment.isFavorite, // 收藏后保持原始颜色
modifier = Modifier.noRippleClickable { onFavoriteClick() }
)
@@ -406,6 +407,9 @@ fun NewsItem(
}
}
// 激活状态的颜色(点赞/收藏时的红色)
private val ActiveIconColor = Color(0xFFD80264)
// 互动栏按钮
@Composable
fun NewsActionButton(
@@ -414,7 +418,8 @@ fun NewsActionButton(
isActive: Boolean,
modifier: Modifier = Modifier,
text: String? = null,
textSize: androidx.compose.ui.unit.TextUnit = 12.sp
textSize: androidx.compose.ui.unit.TextUnit = 12.sp,
keepOriginalColor: Boolean = false // 是否保持原始颜色(不应用颜色滤镜)
) {
val AppColors = LocalAppTheme.current
@@ -432,7 +437,12 @@ fun NewsActionButton(
Image(
painter = androidx.compose.ui.res.painterResource(id = icon),
contentDescription = "操作图标",
modifier = Modifier.size(16.dp)
modifier = Modifier.size(16.dp),
colorFilter = when {
isActive -> ColorFilter.tint(ActiveIconColor)
keepOriginalColor -> null // 保持原始颜色
else -> ColorFilter.tint(AppColors.text) // 未激活状态时使用文字颜色适配暗色模式
}
)
if (count.isNotEmpty()) {

View File

@@ -69,14 +69,18 @@ import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R
import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.GuestLoginCheckOut
import com.aiosman.ravenow.GuestLoginCheckOutScene
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.MomentCard
import com.aiosman.ravenow.ui.composables.TabItem
import com.aiosman.ravenow.ui.composables.TabSpacer
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListViewModel
import com.aiosman.ravenow.ui.index.tabs.profile.composable.RoomItem
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.aiosman.ravenow.ui.navigateToGroupChat
import com.aiosman.ravenow.ui.NavigationRoute
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.launch
import com.aiosman.ravenow.utils.NetworkUtils
@@ -403,6 +407,8 @@ fun MomentResultTab() {
var moments = dataFlow.collectAsLazyPagingItems()
val AppColors = LocalAppTheme.current
val context = LocalContext.current
val scope = rememberCoroutineScope()
val navController = LocalNavController.current
Box(
modifier = Modifier
.fillMaxSize()
@@ -473,6 +479,12 @@ fun MomentResultTab() {
) {
items(moments.itemCount) { idx ->
val momentItem = moments[idx] ?: return@items
val commentDebouncer = rememberDebouncer()
val likeDebouncer = rememberDebouncer()
val favoriteDebouncer = rememberDebouncer()
val followDebouncer = rememberDebouncer()
Box(
modifier = Modifier
.fillMaxWidth()
@@ -480,10 +492,61 @@ fun MomentResultTab() {
) {
MomentCard(
momentEntity = momentItem,
hideAction = true,
onAddComment = {
commentDebouncer {
// 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.COMMENT_MOMENT)) {
navController.navigate(NavigationRoute.Login.route)
} else {
scope.launch {
model.onAddComment(momentItem.id)
}
}
}
},
onLikeClick = {
likeDebouncer {
// 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.LIKE_MOMENT)) {
navController.navigate(NavigationRoute.Login.route)
} else {
scope.launch {
if (momentItem.liked) {
model.dislikeMoment(momentItem.id)
} else {
model.likeMoment(momentItem.id)
}
}
}
}
},
onFavoriteClick = {
favoriteDebouncer {
// 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.LIKE_MOMENT)) {
navController.navigate(NavigationRoute.Login.route)
} else {
scope.launch {
if (momentItem.isFavorite) {
model.unfavoriteMoment(momentItem.id)
} else {
model.favoriteMoment(momentItem.id)
}
}
}
}
},
onFollowClick = {
model.momentFollowAction(momentItem)
}
followDebouncer {
// 检查游客模式,如果是游客则跳转登录
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.FOLLOW_USER)) {
navController.navigate(NavigationRoute.Login.route)
} else {
model.momentFollowAction(momentItem)
}
}
},
showFollowButton = true
)
}
// Spacer(modifier = Modifier.padding(16.dp))
@@ -663,6 +726,8 @@ fun AiResultTab() {
val context = LocalContext.current
val model = SearchViewModel
val agents = model.agentsFlow.collectAsLazyPagingItems()
val navController = LocalNavController.current
val scope = rememberCoroutineScope()
Box(
modifier = Modifier
.fillMaxSize()
@@ -736,7 +801,23 @@ fun AiResultTab() {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
.padding(16.dp)
.noRippleClickable {
scope.launch {
try {
val userService = com.aiosman.ravenow.data.UserServiceImpl()
val profile = userService.getUserProfileByOpenId(agent.openId)
navController.navigate(
NavigationRoute.AccountProfile.route
.replace("{id}", profile.id.toString())
.replace("{isAiAccount}", "true")
)
} catch (e: Exception) {
// 处理错误
e.printStackTrace()
}
}
},
verticalAlignment = Alignment.CenterVertically
) {
CustomAsyncImage(

View File

@@ -200,4 +200,88 @@ object SearchViewModel : ViewModel() {
}
}
}
suspend fun likeMoment(id: Int) {
try {
momentService.likeMoment(id)
updateMomentLike(id, true)
} catch (e: Exception) {
e.printStackTrace()
}
}
suspend fun dislikeMoment(id: Int) {
try {
momentService.dislikeMoment(id)
updateMomentLike(id, false)
} catch (e: Exception) {
e.printStackTrace()
}
}
suspend fun favoriteMoment(id: Int) {
try {
momentService.favoriteMoment(id)
updateMomentFavorite(id, true)
} catch (e: Exception) {
e.printStackTrace()
}
}
suspend fun unfavoriteMoment(id: Int) {
try {
momentService.unfavoriteMoment(id)
updateMomentFavorite(id, false)
} catch (e: Exception) {
e.printStackTrace()
}
}
fun onAddComment(id: Int) {
updateMomentCommentCount(id, 1)
}
private fun updateMomentLike(id: Int, isLike: Boolean) {
val currentPagingData = _momentsFlow.value
val updatedPagingData = currentPagingData.map { momentItem ->
if (momentItem.id == id) {
momentItem.copy(
liked = isLike,
likeCount = momentItem.likeCount + if (isLike) 1 else -1
)
} else {
momentItem
}
}
_momentsFlow.value = updatedPagingData
}
private fun updateMomentFavorite(id: Int, isFavorite: Boolean) {
val currentPagingData = _momentsFlow.value
val updatedPagingData = currentPagingData.map { momentItem ->
if (momentItem.id == id) {
momentItem.copy(
isFavorite = isFavorite,
favoriteCount = momentItem.favoriteCount + if (isFavorite) 1 else -1
)
} else {
momentItem
}
}
_momentsFlow.value = updatedPagingData
}
private fun updateMomentCommentCount(id: Int, delta: Int) {
val currentPagingData = _momentsFlow.value
val updatedPagingData = currentPagingData.map { momentItem ->
if (momentItem.id == id) {
momentItem.copy(
commentCount = (momentItem.commentCount + delta).coerceAtLeast(0)
)
} else {
momentItem
}
}
_momentsFlow.value = updatedPagingData
}
}

View File

@@ -57,6 +57,7 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
@@ -453,6 +454,7 @@ private fun PointsHistoryList(
hasNext: Boolean
) {
val AppColors = LocalAppTheme.current
val context = LocalContext.current
val numberFormat = remember { NumberFormat.getNumberInstance(Locale.getDefault()) }
val listState = rememberLazyListState()
val loading = PointsViewModel.loading
@@ -544,7 +546,7 @@ private fun PointsHistoryList(
)
Spacer(Modifier.size(12.dp))
Column {
Text(text = PointService.getReasonDescription(item.reason ?: "" ), color = AppColors.text, fontSize = 16.sp, fontWeight = FontWeight.W600)
Text(text = PointService.getReasonDescription(context, item.reason ?: "" ), color = AppColors.text, fontSize = 16.sp, fontWeight = FontWeight.W600)
Spacer(Modifier.height(4.dp))
Text(text = item.createdAt ?: "", color = AppColors.secondaryText, fontSize = 12.sp)
}

View File

@@ -362,6 +362,21 @@
<string name="complete_tasks_desc">タスクを完了して報酬を獲得</string>
<string name="recharge_pai_coin">パイコインをチャージ</string>
<string name="recharge_pai_coin_desc">複数のパッケージが利用可能、今すぐチャージ</string>
<!-- Transaction History Reasons -->
<string name="earn_register">新規ユーザー登録報酬</string>
<string name="earn_daily">デイリーチェックイン報酬</string>
<string name="earn_task">タスク完了報酬</string>
<string name="earn_invite">友達招待報酬</string>
<string name="earn_recharge">チャージ</string>
<string name="spend_group_create">グループチャット作成</string>
<string name="spend_group_expand">グループチャット拡張</string>
<string name="spend_agent_private">エージェントプライベートモード</string>
<string name="spend_agent_memory">エージェント記憶追加</string>
<string name="spend_room_memory">ルーム記憶追加</string>
<string name="spend_chat_background">カスタムチャット背景</string>
<string name="spend_schedule_event">スケジュールイベント解除</string>
<string name="create_group_chat_failed">グループチャットの作成に失敗しました: %1$s</string>
<string name="connect_world_start_following">世界をつなぐ、フォローから始めましょう</string>
<string name="why_not_start_with_agent">エージェントから世界を知り始めませんか?</string>

View File

@@ -367,6 +367,21 @@
<string name="complete_tasks_desc">完成任务可获得奖励</string>
<string name="recharge_pai_coin">充值派币</string>
<string name="recharge_pai_coin_desc">多种套餐可选,立即充值</string>
<!-- Transaction History Reasons -->
<string name="earn_register">新用户注册奖励</string>
<string name="earn_daily">每日签到奖励</string>
<string name="earn_task">任务完成奖励</string>
<string name="earn_invite">邀请好友奖励</string>
<string name="earn_recharge">充值获得</string>
<string name="spend_group_create">创建群聊</string>
<string name="spend_group_expand">扩容群聊</string>
<string name="spend_agent_private">Agent 私密模式</string>
<string name="spend_agent_memory">Agent 记忆添加</string>
<string name="spend_room_memory">房间记忆添加</string>
<string name="spend_chat_background">自定义聊天背景</string>
<string name="spend_schedule_event">定时事件解锁</string>
<string name="create_group_chat_failed">创建群聊失败: %1$s</string>
<string name="create_group_chat_confirm_title">创建群聊确认</string>
<string name="create_group_chat_required_cost">需要消耗:</string>

View File

@@ -361,6 +361,21 @@
<string name="complete_tasks_desc">Complete tasks to earn rewards</string>
<string name="recharge_pai_coin">Recharge Pai Coin</string>
<string name="recharge_pai_coin_desc">Multiple packages available, recharge now</string>
<!-- Transaction History Reasons -->
<string name="earn_register">New User Registration Reward</string>
<string name="earn_daily">Daily Check-in Reward</string>
<string name="earn_task">Task Completion Reward</string>
<string name="earn_invite">Invite Friends Reward</string>
<string name="earn_recharge">Recharge</string>
<string name="spend_group_create">Create Group Chat</string>
<string name="spend_group_expand">Expand Group Chat</string>
<string name="spend_agent_private">Agent Private Mode</string>
<string name="spend_agent_memory">Agent Memory Added</string>
<string name="spend_room_memory">Room Memory Added</string>
<string name="spend_chat_background">Custom Chat Background</string>
<string name="spend_schedule_event">Scheduled Event Unlocked</string>
<string name="create_group_chat_failed">Failed to create group chat: %1$s</string>
<string name="create_group_chat_confirm_title">Create Group Chat</string>
<string name="create_group_chat_required_cost">Required consumption:</string>