修改若干bug、调整动态标签栏、添加文本等
修复修改用户头像以及壁纸不保存,头像仍然修改成功 动态-新闻界面暗色模式调整 新增动态标签栏选中标签时会有文本变大效果 搜索后的动态界面增加点赞/收藏/评论/转发动态按钮 修复搜索智能体后点击智能体不能跳转至智能体主页 修复进入消息-全部列表,消息界面显示为空 我的派币-历史记录添加文本资源
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package com.aiosman.ravenow.data
|
package com.aiosman.ravenow.data
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import com.aiosman.ravenow.AppStore
|
import com.aiosman.ravenow.AppStore
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
import com.aiosman.ravenow.data.api.ApiClient
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
import com.aiosman.ravenow.data.api.DictItem
|
import com.aiosman.ravenow.data.api.DictItem
|
||||||
import com.aiosman.ravenow.data.api.PointsBalance
|
import com.aiosman.ravenow.data.api.PointsBalance
|
||||||
@@ -370,27 +372,29 @@ object PointService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取变更原因的中文描述
|
* 获取变更原因的描述(支持多语言)
|
||||||
*
|
*
|
||||||
|
* @param context Context 用于获取资源
|
||||||
* @param reason 变更原因代码
|
* @param reason 变更原因代码
|
||||||
* @return 中文描述
|
* @return 本地化描述
|
||||||
*/
|
*/
|
||||||
fun getReasonDescription(reason: String): String {
|
fun getReasonDescription(context: Context, reason: String): String {
|
||||||
return when (reason) {
|
val resourceId = when (reason) {
|
||||||
ChangeReason.EARN_REGISTER -> "新用户注册奖励"
|
ChangeReason.EARN_REGISTER -> R.string.earn_register
|
||||||
ChangeReason.EARN_DAILY -> "每日签到奖励"
|
ChangeReason.EARN_DAILY -> R.string.earn_daily
|
||||||
ChangeReason.EARN_TASK -> "任务完成奖励"
|
ChangeReason.EARN_TASK -> R.string.earn_task
|
||||||
ChangeReason.EARN_INVITE -> "邀请好友奖励"
|
ChangeReason.EARN_INVITE -> R.string.earn_invite
|
||||||
ChangeReason.EARN_RECHARGE -> "充值获得"
|
ChangeReason.EARN_RECHARGE -> R.string.earn_recharge
|
||||||
ChangeReason.SPEND_GROUP_CREATE -> "创建群聊"
|
ChangeReason.SPEND_GROUP_CREATE -> R.string.spend_group_create
|
||||||
ChangeReason.SPEND_GROUP_EXPAND -> "扩容群聊"
|
ChangeReason.SPEND_GROUP_EXPAND -> R.string.spend_group_expand
|
||||||
ChangeReason.SPEND_AGENT_PRIVATE -> "Agent 私密模式"
|
ChangeReason.SPEND_AGENT_PRIVATE -> R.string.spend_agent_private
|
||||||
ChangeReason.SPEND_AGENT_MEMORY -> "Agent 记忆添加"
|
ChangeReason.SPEND_AGENT_MEMORY -> R.string.spend_agent_memory
|
||||||
ChangeReason.SPEND_ROOM_MEMORY -> "房间记忆添加"
|
ChangeReason.SPEND_ROOM_MEMORY -> R.string.spend_room_memory
|
||||||
ChangeReason.SPEND_CHAT_BACKGROUND -> "自定义聊天背景"
|
ChangeReason.SPEND_CHAT_BACKGROUND -> R.string.spend_chat_background
|
||||||
ChangeReason.SPEND_SCHEDULE_EVENT -> "定时事件解锁"
|
ChangeReason.SPEND_SCHEDULE_EVENT -> R.string.spend_schedule_event
|
||||||
else -> reason // 未知原因,返回原始代码
|
else -> null
|
||||||
}
|
}
|
||||||
|
return resourceId?.let { context.getString(it) } ?: reason // 未知原因,返回原始代码
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -31,7 +31,12 @@ object AccountEditViewModel : ViewModel() {
|
|||||||
// 本地扩展字段
|
// 本地扩展字段
|
||||||
var mbti by mutableStateOf<String?>(null)
|
var mbti by mutableStateOf<String?>(null)
|
||||||
var zodiac 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: 开始加载用户资料")
|
Log.d("AccountEditViewModel", "reloadProfile: 开始加载用户资料")
|
||||||
isLoading = true
|
isLoading = true
|
||||||
try {
|
try {
|
||||||
@@ -41,13 +46,23 @@ object AccountEditViewModel : ViewModel() {
|
|||||||
profile = it
|
profile = it
|
||||||
name = it.nickName
|
name = it.nickName
|
||||||
bio = it.bio
|
bio = it.bio
|
||||||
// 清除之前裁剪的图片
|
// 保存原始值,用于取消时恢复
|
||||||
croppedBitmap = null
|
originalName = it.nickName
|
||||||
|
originalBio = it.bio
|
||||||
|
// 只在明确要求时清除之前裁剪的图片(例如保存成功后)
|
||||||
|
if (clearCroppedBitmap) {
|
||||||
|
croppedBitmap = null
|
||||||
|
}
|
||||||
// 读取本地扩展字段
|
// 读取本地扩展字段
|
||||||
try {
|
try {
|
||||||
val uid = it.id // 使用 profile 的 id,确保非空
|
val uid = it.id // 使用 profile 的 id,确保非空
|
||||||
mbti = com.aiosman.ravenow.AppStore.getUserMbti(uid)
|
val loadedMbti = com.aiosman.ravenow.AppStore.getUserMbti(uid)
|
||||||
zodiac = com.aiosman.ravenow.AppStore.getUserZodiac(uid)
|
val loadedZodiac = com.aiosman.ravenow.AppStore.getUserZodiac(uid)
|
||||||
|
mbti = loadedMbti
|
||||||
|
zodiac = loadedZodiac
|
||||||
|
// 保存原始值
|
||||||
|
originalMbti = loadedMbti
|
||||||
|
originalZodiac = loadedZodiac
|
||||||
} catch (_: Exception) { }
|
} catch (_: Exception) { }
|
||||||
if (updateTrtcProfile) {
|
if (updateTrtcProfile) {
|
||||||
TrtcHelper.updateTrtcProfile(
|
TrtcHelper.updateTrtcProfile(
|
||||||
@@ -69,12 +84,15 @@ object AccountEditViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun resetToOriginalData() {
|
fun resetToOriginalData() {
|
||||||
profile?.let {
|
// 恢复所有字段到原始值
|
||||||
name = it.nickName
|
name = originalName
|
||||||
bio = it.bio
|
bio = originalBio
|
||||||
// 清除之前裁剪的图片
|
mbti = originalMbti
|
||||||
croppedBitmap = null
|
zodiac = originalZodiac
|
||||||
}
|
// 清除之前裁剪的图片和壁纸
|
||||||
|
croppedBitmap = null
|
||||||
|
bannerImageUrl = null
|
||||||
|
bannerFile = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -129,8 +147,8 @@ object AccountEditViewModel : ViewModel() {
|
|||||||
// 清除背景图状态
|
// 清除背景图状态
|
||||||
bannerImageUrl = null
|
bannerImageUrl = null
|
||||||
bannerFile = null
|
bannerFile = null
|
||||||
// 刷新用户资料
|
// 刷新用户资料,保存成功后清除裁剪的图片
|
||||||
reloadProfile()
|
reloadProfile(clearCroppedBitmap = true)
|
||||||
// 刷新个人资料页面的用户资料
|
// 刷新个人资料页面的用户资料
|
||||||
MyProfileViewModel.loadUserProfile()
|
MyProfileViewModel.loadUserProfile()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ import com.aiosman.ravenow.ConstVars
|
|||||||
import com.aiosman.ravenow.ui.composables.pickupAndCompressLauncher
|
import com.aiosman.ravenow.ui.composables.pickupAndCompressLauncher
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编辑用户资料界面
|
* 编辑用户资料界面
|
||||||
@@ -171,6 +172,13 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
|
|||||||
model.reloadProfile()
|
model.reloadProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理系统返回键
|
||||||
|
BackHandler {
|
||||||
|
// 用户未保存直接返回,恢复所有字段到原始值
|
||||||
|
model.resetToOriginalData()
|
||||||
|
navController.navigateUp()
|
||||||
|
}
|
||||||
|
|
||||||
// 设置状态栏为透明,根据暗色模式决定图标颜色
|
// 设置状态栏为透明,根据暗色模式决定图标颜色
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
@@ -291,6 +299,8 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
|
|||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.background(Color.White.copy(alpha = 0.3f))
|
.background(Color.White.copy(alpha = 0.3f))
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
|
// 用户未保存直接返回,恢复所有字段到原始值
|
||||||
|
model.resetToOriginalData()
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
}
|
}
|
||||||
.align(Alignment.CenterStart),
|
.align(Alignment.CenterStart),
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
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.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.res.painterResource
|
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.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.aiosman.ravenow.LocalAppTheme
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
@@ -74,6 +80,18 @@ fun UnderlineTabItem(
|
|||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
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(
|
Column(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
@@ -81,24 +99,33 @@ fun UnderlineTabItem(
|
|||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Text(
|
Box(
|
||||||
text = text,
|
modifier = Modifier
|
||||||
fontSize = 15.sp,
|
.padding(horizontal = animatedPadding)
|
||||||
fontWeight = FontWeight.ExtraBold,
|
.padding(top = 13.dp, bottom = 0.dp),
|
||||||
color = if (isSelected) AppColors.text else AppColors.text.copy(alpha = 0.6f),
|
contentAlignment = Alignment.BottomCenter
|
||||||
modifier = Modifier.padding(horizontal = 16.dp).padding(top = 13.dp)
|
) {
|
||||||
)
|
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(
|
if (isSelected) {
|
||||||
modifier = Modifier.size(24.dp),
|
Box(
|
||||||
contentAlignment = Alignment.Center
|
modifier = Modifier
|
||||||
) {
|
.size(24.dp)
|
||||||
if (isSelected) {
|
.offset(y = (-4).dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.mipmap.underline),
|
painter = painterResource(id = R.mipmap.underline),
|
||||||
contentDescription = "selected indicator",
|
contentDescription = "selected indicator",
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ fun ImageCropScreen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
|
// 用户取消图片选择,清除已裁剪的图片
|
||||||
|
AccountEditViewModel.croppedBitmap = null
|
||||||
navController.popBackStack()
|
navController.popBackStack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,6 +105,8 @@ fun ImageCropScreen() {
|
|||||||
painter = painterResource(R.drawable.rider_pro_back_icon),
|
painter = painterResource(R.drawable.rider_pro_back_icon),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
|
// 用户取消头像选择,清除已裁剪的图片
|
||||||
|
AccountEditViewModel.croppedBitmap = null
|
||||||
navController.popBackStack()
|
navController.popBackStack()
|
||||||
},
|
},
|
||||||
colorFilter = ColorFilter.tint(Color.White)
|
colorFilter = ColorFilter.tint(Color.White)
|
||||||
@@ -119,11 +123,9 @@ fun ImageCropScreen() {
|
|||||||
val bitmap = it.onCrop()
|
val bitmap = it.onCrop()
|
||||||
|
|
||||||
// 专门处理个人资料头像
|
// 专门处理个人资料头像
|
||||||
|
// 只设置裁剪后的图片,不立即上传,等待用户在编辑资料界面点击保存
|
||||||
AccountEditViewModel.croppedBitmap = bitmap
|
AccountEditViewModel.croppedBitmap = bitmap
|
||||||
AccountEditViewModel.viewModelScope.launch {
|
navController.popBackStack()
|
||||||
AccountEditViewModel.updateUserProfile(context)
|
|
||||||
navController.popBackStack()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -121,35 +121,88 @@ fun AllChatListScreen() {
|
|||||||
var isLoading by remember { mutableStateOf(false) }
|
var isLoading by remember { mutableStateOf(false) }
|
||||||
var error by remember { mutableStateOf<String?>(null) }
|
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(
|
val state = rememberPullRefreshState(
|
||||||
refreshing = refreshing,
|
refreshing = refreshing,
|
||||||
onRefresh = {
|
onRefresh = {
|
||||||
refreshing = true
|
refreshing = true
|
||||||
refreshAllData(context,
|
// 刷新所有类型的数据
|
||||||
onSuccess = { conversations ->
|
AgentChatListViewModel.refreshPager(pullRefresh = true, context = context)
|
||||||
allConversations = conversations
|
GroupChatListViewModel.refreshPager(pullRefresh = true, context = context)
|
||||||
refreshing = false
|
FriendChatListViewModel.refreshPager(pullRefresh = true, context = context)
|
||||||
},
|
|
||||||
onError = { errorMsg ->
|
|
||||||
error = errorMsg
|
|
||||||
refreshing = false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 监听刷新状态
|
||||||
|
LaunchedEffect(AgentChatListViewModel.refreshing, GroupChatListViewModel.refreshing, FriendChatListViewModel.refreshing) {
|
||||||
|
val isAnyRefreshing = AgentChatListViewModel.refreshing ||
|
||||||
|
GroupChatListViewModel.refreshing ||
|
||||||
|
FriendChatListViewModel.refreshing
|
||||||
|
if (!isAnyRefreshing && refreshing) {
|
||||||
|
refreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
isLoading = true
|
isLoading = true
|
||||||
refreshAllData(context,
|
// 初始化加载所有类型的数据
|
||||||
onSuccess = { conversations ->
|
AgentChatListViewModel.refreshPager(context = context)
|
||||||
allConversations = conversations
|
GroupChatListViewModel.refreshPager(context = context)
|
||||||
isLoading = false
|
FriendChatListViewModel.refreshPager(context = context)
|
||||||
},
|
|
||||||
onError = { errorMsg ->
|
|
||||||
error = errorMsg
|
|
||||||
isLoading = false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
@@ -235,16 +288,10 @@ fun AllChatListScreen() {
|
|||||||
ReloadButton(
|
ReloadButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
isLoading = true
|
isLoading = true
|
||||||
refreshAllData(context,
|
// 重新加载所有类型的数据
|
||||||
onSuccess = { conversations ->
|
AgentChatListViewModel.refreshPager(context = context)
|
||||||
allConversations = conversations
|
GroupChatListViewModel.refreshPager(context = context)
|
||||||
isLoading = false
|
FriendChatListViewModel.refreshPager(context = context)
|
||||||
},
|
|
||||||
onError = { errorMsg ->
|
|
||||||
error = errorMsg
|
|
||||||
isLoading = false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -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}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ fun MomentsList(
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(44.dp)
|
.height(54.dp)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
|||||||
@@ -390,7 +390,8 @@ fun NewsItem(
|
|||||||
NewsActionButton(
|
NewsActionButton(
|
||||||
icon = if (moment.isFavorite) R.mipmap.icon_variant_2 else R.mipmap.icon_collect,
|
icon = if (moment.isFavorite) R.mipmap.icon_variant_2 else R.mipmap.icon_collect,
|
||||||
count = moment.favoriteCount.toString(),
|
count = moment.favoriteCount.toString(),
|
||||||
isActive = moment.isFavorite,
|
isActive = false, // 收藏后不使用红色滤镜,保持图标原本颜色
|
||||||
|
keepOriginalColor = moment.isFavorite, // 收藏后保持原始颜色
|
||||||
modifier = Modifier.noRippleClickable { onFavoriteClick() }
|
modifier = Modifier.noRippleClickable { onFavoriteClick() }
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -406,6 +407,9 @@ fun NewsItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 激活状态的颜色(点赞/收藏时的红色)
|
||||||
|
private val ActiveIconColor = Color(0xFFD80264)
|
||||||
|
|
||||||
// 互动栏按钮
|
// 互动栏按钮
|
||||||
@Composable
|
@Composable
|
||||||
fun NewsActionButton(
|
fun NewsActionButton(
|
||||||
@@ -414,7 +418,8 @@ fun NewsActionButton(
|
|||||||
isActive: Boolean,
|
isActive: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
text: String? = null,
|
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
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
@@ -432,7 +437,12 @@ fun NewsActionButton(
|
|||||||
Image(
|
Image(
|
||||||
painter = androidx.compose.ui.res.painterResource(id = icon),
|
painter = androidx.compose.ui.res.painterResource(id = icon),
|
||||||
contentDescription = "操作图标",
|
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()) {
|
if (count.isNotEmpty()) {
|
||||||
|
|||||||
@@ -69,14 +69,18 @@ import com.aiosman.ravenow.LocalAppTheme
|
|||||||
import com.aiosman.ravenow.LocalNavController
|
import com.aiosman.ravenow.LocalNavController
|
||||||
import com.aiosman.ravenow.R
|
import com.aiosman.ravenow.R
|
||||||
import com.aiosman.ravenow.entity.AccountProfileEntity
|
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.CustomAsyncImage
|
||||||
import com.aiosman.ravenow.ui.composables.MomentCard
|
import com.aiosman.ravenow.ui.composables.MomentCard
|
||||||
import com.aiosman.ravenow.ui.composables.TabItem
|
import com.aiosman.ravenow.ui.composables.TabItem
|
||||||
import com.aiosman.ravenow.ui.composables.TabSpacer
|
import com.aiosman.ravenow.ui.composables.TabSpacer
|
||||||
|
import com.aiosman.ravenow.ui.composables.rememberDebouncer
|
||||||
import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListViewModel
|
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.index.tabs.profile.composable.RoomItem
|
||||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
import com.aiosman.ravenow.ui.navigateToGroupChat
|
import com.aiosman.ravenow.ui.navigateToGroupChat
|
||||||
|
import com.aiosman.ravenow.ui.NavigationRoute
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import com.aiosman.ravenow.utils.NetworkUtils
|
import com.aiosman.ravenow.utils.NetworkUtils
|
||||||
@@ -403,6 +407,8 @@ fun MomentResultTab() {
|
|||||||
var moments = dataFlow.collectAsLazyPagingItems()
|
var moments = dataFlow.collectAsLazyPagingItems()
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val navController = LocalNavController.current
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -473,6 +479,12 @@ fun MomentResultTab() {
|
|||||||
) {
|
) {
|
||||||
items(moments.itemCount) { idx ->
|
items(moments.itemCount) { idx ->
|
||||||
val momentItem = moments[idx] ?: return@items
|
val momentItem = moments[idx] ?: return@items
|
||||||
|
|
||||||
|
val commentDebouncer = rememberDebouncer()
|
||||||
|
val likeDebouncer = rememberDebouncer()
|
||||||
|
val favoriteDebouncer = rememberDebouncer()
|
||||||
|
val followDebouncer = rememberDebouncer()
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -480,10 +492,61 @@ fun MomentResultTab() {
|
|||||||
) {
|
) {
|
||||||
MomentCard(
|
MomentCard(
|
||||||
momentEntity = momentItem,
|
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 = {
|
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))
|
// Spacer(modifier = Modifier.padding(16.dp))
|
||||||
@@ -663,6 +726,8 @@ fun AiResultTab() {
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val model = SearchViewModel
|
val model = SearchViewModel
|
||||||
val agents = model.agentsFlow.collectAsLazyPagingItems()
|
val agents = model.agentsFlow.collectAsLazyPagingItems()
|
||||||
|
val navController = LocalNavController.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -736,7 +801,23 @@ fun AiResultTab() {
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.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
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
CustomAsyncImage(
|
CustomAsyncImage(
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +57,7 @@ import androidx.compose.ui.graphics.Brush
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.onSizeChanged
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.unit.IntSize
|
import androidx.compose.ui.unit.IntSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -453,6 +454,7 @@ private fun PointsHistoryList(
|
|||||||
hasNext: Boolean
|
hasNext: Boolean
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
|
val context = LocalContext.current
|
||||||
val numberFormat = remember { NumberFormat.getNumberInstance(Locale.getDefault()) }
|
val numberFormat = remember { NumberFormat.getNumberInstance(Locale.getDefault()) }
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
val loading = PointsViewModel.loading
|
val loading = PointsViewModel.loading
|
||||||
@@ -544,7 +546,7 @@ private fun PointsHistoryList(
|
|||||||
)
|
)
|
||||||
Spacer(Modifier.size(12.dp))
|
Spacer(Modifier.size(12.dp))
|
||||||
Column {
|
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))
|
Spacer(Modifier.height(4.dp))
|
||||||
Text(text = item.createdAt ?: "", color = AppColors.secondaryText, fontSize = 12.sp)
|
Text(text = item.createdAt ?: "", color = AppColors.secondaryText, fontSize = 12.sp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,6 +362,21 @@
|
|||||||
<string name="complete_tasks_desc">タスクを完了して報酬を獲得</string>
|
<string name="complete_tasks_desc">タスクを完了して報酬を獲得</string>
|
||||||
<string name="recharge_pai_coin">パイコインをチャージ</string>
|
<string name="recharge_pai_coin">パイコインをチャージ</string>
|
||||||
<string name="recharge_pai_coin_desc">複数のパッケージが利用可能、今すぐチャージ</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="create_group_chat_failed">グループチャットの作成に失敗しました: %1$s</string>
|
||||||
<string name="connect_world_start_following">世界をつなぐ、フォローから始めましょう</string>
|
<string name="connect_world_start_following">世界をつなぐ、フォローから始めましょう</string>
|
||||||
<string name="why_not_start_with_agent">エージェントから世界を知り始めませんか?</string>
|
<string name="why_not_start_with_agent">エージェントから世界を知り始めませんか?</string>
|
||||||
|
|||||||
@@ -367,6 +367,21 @@
|
|||||||
<string name="complete_tasks_desc">完成任务可获得奖励</string>
|
<string name="complete_tasks_desc">完成任务可获得奖励</string>
|
||||||
<string name="recharge_pai_coin">充值派币</string>
|
<string name="recharge_pai_coin">充值派币</string>
|
||||||
<string name="recharge_pai_coin_desc">多种套餐可选,立即充值</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_failed">创建群聊失败: %1$s</string>
|
||||||
<string name="create_group_chat_confirm_title">创建群聊确认</string>
|
<string name="create_group_chat_confirm_title">创建群聊确认</string>
|
||||||
<string name="create_group_chat_required_cost">需要消耗:</string>
|
<string name="create_group_chat_required_cost">需要消耗:</string>
|
||||||
|
|||||||
@@ -361,6 +361,21 @@
|
|||||||
<string name="complete_tasks_desc">Complete tasks to earn rewards</string>
|
<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">Recharge Pai Coin</string>
|
||||||
<string name="recharge_pai_coin_desc">Multiple packages available, recharge now</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_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_confirm_title">Create Group Chat</string>
|
||||||
<string name="create_group_chat_required_cost">Required consumption:</string>
|
<string name="create_group_chat_required_cost">Required consumption:</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user