Merge branch 'main' into atm
4
.idea/deploymentTargetSelector.xml
generated
@@ -4,10 +4,10 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-09-17T06:25:35.585100400Z">
|
<DropdownSelection timestamp="2025-11-05T12:24:27.034893100Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="Default" identifier="serial=192.168.0.216:5555;connection=698a7727" />
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=c328a150" />
|
||||||
</handle>
|
</handle>
|
||||||
</Target>
|
</Target>
|
||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
|
|||||||
@@ -71,4 +71,29 @@ object AppStore {
|
|||||||
AppState.chatBackgroundUrl = url
|
AppState.chatBackgroundUrl = url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===================== 用户本地扩展信息 =====================
|
||||||
|
// 后端暂未提供 MBTI 与星座字段,使用本地持久化按用户维度进行存储
|
||||||
|
private fun mbtiKey(userId: Int) = "mbti_user_$userId"
|
||||||
|
private fun zodiacKey(userId: Int) = "zodiac_user_$userId"
|
||||||
|
|
||||||
|
fun getUserMbti(userId: Int): String? {
|
||||||
|
return sharedPreferences.getString(mbtiKey(userId), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUserMbti(userId: Int, mbti: String?) {
|
||||||
|
sharedPreferences.edit().apply {
|
||||||
|
if (mbti.isNullOrEmpty()) remove(mbtiKey(userId)) else putString(mbtiKey(userId), mbti)
|
||||||
|
}.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUserZodiac(userId: Int): String? {
|
||||||
|
return sharedPreferences.getString(zodiacKey(userId), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUserZodiac(userId: Int, zodiac: String?) {
|
||||||
|
sharedPreferences.edit().apply {
|
||||||
|
if (zodiac.isNullOrEmpty()) remove(zodiacKey(userId)) else putString(zodiacKey(userId), zodiac)
|
||||||
|
}.apply()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -35,8 +35,10 @@ import com.aiosman.ravenow.LocalSharedTransitionScope
|
|||||||
import com.aiosman.ravenow.ui.about.AboutScreen
|
import com.aiosman.ravenow.ui.about.AboutScreen
|
||||||
import com.aiosman.ravenow.ui.account.AccountEditScreen2
|
import com.aiosman.ravenow.ui.account.AccountEditScreen2
|
||||||
import com.aiosman.ravenow.ui.account.AccountSetting
|
import com.aiosman.ravenow.ui.account.AccountSetting
|
||||||
|
import com.aiosman.ravenow.ui.account.MbtiSelectScreen
|
||||||
import com.aiosman.ravenow.ui.account.RemoveAccountScreen
|
import com.aiosman.ravenow.ui.account.RemoveAccountScreen
|
||||||
import com.aiosman.ravenow.ui.account.ResetPasswordScreen
|
import com.aiosman.ravenow.ui.account.ResetPasswordScreen
|
||||||
|
import com.aiosman.ravenow.ui.account.ZodiacSelectScreen
|
||||||
import com.aiosman.ravenow.ui.agent.AddAgentScreen
|
import com.aiosman.ravenow.ui.agent.AddAgentScreen
|
||||||
import com.aiosman.ravenow.ui.agent.AgentImageCropScreen
|
import com.aiosman.ravenow.ui.agent.AgentImageCropScreen
|
||||||
import com.aiosman.ravenow.ui.group.CreateGroupChatScreen
|
import com.aiosman.ravenow.ui.group.CreateGroupChatScreen
|
||||||
@@ -120,6 +122,8 @@ sealed class NavigationRoute(
|
|||||||
data object VipSelPage : NavigationRoute("VipSelPage")
|
data object VipSelPage : NavigationRoute("VipSelPage")
|
||||||
data object RemoveAccountScreen: NavigationRoute("RemoveAccount")
|
data object RemoveAccountScreen: NavigationRoute("RemoveAccount")
|
||||||
data object NotificationScreen : NavigationRoute("NotificationScreen")
|
data object NotificationScreen : NavigationRoute("NotificationScreen")
|
||||||
|
data object MbtiSelect : NavigationRoute("MbtiSelect")
|
||||||
|
data object ZodiacSelect : NavigationRoute("ZodiacSelect")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -421,6 +425,12 @@ fun NavigationController(
|
|||||||
composable(route = NavigationRoute.RemoveAccountScreen.route) {
|
composable(route = NavigationRoute.RemoveAccountScreen.route) {
|
||||||
RemoveAccountScreen()
|
RemoveAccountScreen()
|
||||||
}
|
}
|
||||||
|
composable(route = NavigationRoute.MbtiSelect.route) {
|
||||||
|
MbtiSelectScreen()
|
||||||
|
}
|
||||||
|
composable(route = NavigationRoute.ZodiacSelect.route) {
|
||||||
|
ZodiacSelectScreen()
|
||||||
|
}
|
||||||
composable(route = NavigationRoute.VipSelPage.route) {
|
composable(route = NavigationRoute.VipSelPage.route) {
|
||||||
VipSelPage()
|
VipSelPage()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ object AccountEditViewModel : ViewModel() {
|
|||||||
var croppedBitmap by mutableStateOf<Bitmap?>(null)
|
var croppedBitmap by mutableStateOf<Bitmap?>(null)
|
||||||
var isUpdating by mutableStateOf(false)
|
var isUpdating by mutableStateOf(false)
|
||||||
var isLoading by mutableStateOf(false)
|
var isLoading by mutableStateOf(false)
|
||||||
|
// 本地扩展字段
|
||||||
|
var mbti by mutableStateOf<String?>(null)
|
||||||
|
var zodiac by mutableStateOf<String?>(null)
|
||||||
suspend fun reloadProfile(updateTrtcProfile:Boolean = false) {
|
suspend fun reloadProfile(updateTrtcProfile:Boolean = false) {
|
||||||
Log.d("AccountEditViewModel", "reloadProfile: 开始加载用户资料")
|
Log.d("AccountEditViewModel", "reloadProfile: 开始加载用户资料")
|
||||||
isLoading = true
|
isLoading = true
|
||||||
@@ -38,6 +41,12 @@ object AccountEditViewModel : ViewModel() {
|
|||||||
bio = it.bio
|
bio = it.bio
|
||||||
// 清除之前裁剪的图片
|
// 清除之前裁剪的图片
|
||||||
croppedBitmap = null
|
croppedBitmap = null
|
||||||
|
// 读取本地扩展字段
|
||||||
|
try {
|
||||||
|
val uid = it.id // 使用 profile 的 id,确保非空
|
||||||
|
mbti = com.aiosman.ravenow.AppStore.getUserMbti(uid)
|
||||||
|
zodiac = com.aiosman.ravenow.AppStore.getUserZodiac(uid)
|
||||||
|
} catch (_: Exception) { }
|
||||||
if (updateTrtcProfile) {
|
if (updateTrtcProfile) {
|
||||||
TrtcHelper.updateTrtcProfile(
|
TrtcHelper.updateTrtcProfile(
|
||||||
it.nickName,
|
it.nickName,
|
||||||
@@ -84,6 +93,13 @@ object AccountEditViewModel : ViewModel() {
|
|||||||
nickName = newName,
|
nickName = newName,
|
||||||
bio = cleanBio
|
bio = cleanBio
|
||||||
)
|
)
|
||||||
|
// 保存本地扩展字段
|
||||||
|
try {
|
||||||
|
profile?.id?.let { uid ->
|
||||||
|
com.aiosman.ravenow.AppStore.setUserMbti(uid, mbti)
|
||||||
|
com.aiosman.ravenow.AppStore.setUserZodiac(uid, zodiac)
|
||||||
|
}
|
||||||
|
} catch (_: Exception) { }
|
||||||
// 刷新用户资料
|
// 刷新用户资料
|
||||||
reloadProfile()
|
reloadProfile()
|
||||||
// 刷新个人资料页面的用户资料
|
// 刷新个人资料页面的用户资料
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
package com.aiosman.ravenow.ui.account
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
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.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.LocalNavController
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
|
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
|
||||||
|
|
||||||
|
// MBTI类型列表
|
||||||
|
val MBTI_TYPES = listOf(
|
||||||
|
"INTJ", "INTP", "ENTJ", "ENTP",
|
||||||
|
"INFJ", "INFP", "ENFJ", "ENFP",
|
||||||
|
"ISTJ", "ISFJ", "ESTJ", "ESFJ",
|
||||||
|
"ISTP", "ISFP", "ESTP", "ESFP"
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MbtiSelectScreen() {
|
||||||
|
val navController = LocalNavController.current
|
||||||
|
val appColors = LocalAppTheme.current
|
||||||
|
val model = AccountEditViewModel
|
||||||
|
val currentMbti = model.mbti
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(appColors.profileBackground)
|
||||||
|
) {
|
||||||
|
// 头部
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 16.dp)
|
||||||
|
) {
|
||||||
|
NoticeScreenHeader(
|
||||||
|
title = stringResource(R.string.choose_mbti),
|
||||||
|
moreIcon = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列表
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
items(MBTI_TYPES) { mbti ->
|
||||||
|
MBTIItem(
|
||||||
|
mbti = mbti,
|
||||||
|
isSelected = mbti == currentMbti,
|
||||||
|
onClick = {
|
||||||
|
model.mbti = mbti
|
||||||
|
navController.navigateUp()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MBTIItem(
|
||||||
|
mbti: String,
|
||||||
|
isSelected: Boolean,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
val appColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(if (isSelected) appColors.main.copy(alpha = 0.1f) else Color.White)
|
||||||
|
.clickable(
|
||||||
|
indication = null,
|
||||||
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
) {
|
||||||
|
onClick()
|
||||||
|
}
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = mbti,
|
||||||
|
fontSize = 17.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
color = if (isSelected) appColors.main else appColors.text,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isSelected) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Check,
|
||||||
|
contentDescription = "Selected",
|
||||||
|
modifier = Modifier.size(20.dp),
|
||||||
|
tint = appColors.main
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
package com.aiosman.ravenow.ui.account
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
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.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.LocalNavController
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
|
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
|
||||||
|
|
||||||
|
// 星座列表
|
||||||
|
val ZODIAC_SIGNS = listOf(
|
||||||
|
"白羊座", "金牛座", "双子座", "巨蟹座",
|
||||||
|
"狮子座", "处女座", "天秤座", "天蝎座",
|
||||||
|
"射手座", "摩羯座", "水瓶座", "双鱼座"
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ZodiacSelectScreen() {
|
||||||
|
val navController = LocalNavController.current
|
||||||
|
val appColors = LocalAppTheme.current
|
||||||
|
val model = AccountEditViewModel
|
||||||
|
val currentZodiac = model.zodiac
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(appColors.profileBackground)
|
||||||
|
) {
|
||||||
|
// 头部
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 16.dp)
|
||||||
|
) {
|
||||||
|
NoticeScreenHeader(
|
||||||
|
title = stringResource(R.string.choose_zodiac),
|
||||||
|
moreIcon = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列表
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
items(ZODIAC_SIGNS) { zodiac ->
|
||||||
|
ZodiacItem(
|
||||||
|
zodiac = zodiac,
|
||||||
|
isSelected = zodiac == currentZodiac,
|
||||||
|
onClick = {
|
||||||
|
model.zodiac = zodiac
|
||||||
|
navController.navigateUp()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ZodiacItem(
|
||||||
|
zodiac: String,
|
||||||
|
isSelected: Boolean,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
val appColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(if (isSelected) appColors.main.copy(alpha = 0.1f) else Color.White)
|
||||||
|
.clickable(
|
||||||
|
indication = null,
|
||||||
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
) {
|
||||||
|
onClick()
|
||||||
|
}
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = zodiac,
|
||||||
|
fontSize = 17.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
color = if (isSelected) appColors.main else appColors.text,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isSelected) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Check,
|
||||||
|
contentDescription = "Selected",
|
||||||
|
modifier = Modifier.size(20.dp),
|
||||||
|
tint = appColors.main
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -125,12 +125,13 @@ fun CommentNoticeScreen() {
|
|||||||
) {
|
) {
|
||||||
androidx.compose.foundation.Image(
|
androidx.compose.foundation.Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id =if(AppState.darkMode) R.mipmap.qst_pl_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.tietie_dark
|
||||||
else R.mipmap.invalid_name_11),
|
else R.mipmap.invalid_name_11),
|
||||||
contentDescription = "No Comment",
|
contentDescription = "No Comment",
|
||||||
modifier = Modifier.size(181.dp)
|
modifier = Modifier
|
||||||
|
.size(width = 181.dp, height = 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "等一位旅人~",
|
text = "等一位旅人~",
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
|
|||||||
@@ -137,9 +137,9 @@ fun FavouriteListPage() {
|
|||||||
id = if (com.aiosman.ravenow.AppState.darkMode) R.mipmap.invalid_dark
|
id = if (com.aiosman.ravenow.AppState.darkMode) R.mipmap.invalid_dark
|
||||||
else R.mipmap.invalid_name_1),
|
else R.mipmap.invalid_name_1),
|
||||||
contentDescription = "No favourites",
|
contentDescription = "No favourites",
|
||||||
modifier = Modifier.size(110.dp)
|
modifier = Modifier.size(181.dp, 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(24.dp))
|
Spacer(modifier = Modifier.size(9.dp)) // 调整间距为9dp
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.favourites_null),
|
text = stringResource(R.string.favourites_null),
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
|
|||||||
@@ -124,21 +124,21 @@ fun FollowerListScreen(userId: Int) {
|
|||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id =if(AppState.darkMode) R.mipmap.qst_fs_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.frame_4
|
||||||
else R.mipmap.invalid_name_8),
|
else R.mipmap.invalid_name_8),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(181.dp)
|
modifier = Modifier.size(181.dp, 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(24.dp))
|
Spacer(modifier = Modifier.size(9.dp)) // 调整间距为9dp
|
||||||
androidx.compose.material.Text(
|
androidx.compose.material.Text(
|
||||||
text = "还没有人关注哦",
|
text = "还没有人关注你呢",
|
||||||
color = appColors.text,
|
color = appColors.text,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.W600
|
fontWeight = FontWeight.W600
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(8.dp))
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
androidx.compose.material.Text(
|
androidx.compose.material.Text(
|
||||||
text = "去发布动态,吸引更多粉丝~",
|
text = "试着发信号出来,某人就会被吸引啦~",
|
||||||
color = appColors.text,
|
color = appColors.text,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.W400
|
fontWeight = FontWeight.W400
|
||||||
|
|||||||
@@ -114,21 +114,22 @@ fun FollowerNoticeScreen() {
|
|||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id =if(AppState.darkMode) R.mipmap.qst_fs_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.frame_4
|
||||||
else R.mipmap.invalid_name_8),
|
else R.mipmap.invalid_name_8),
|
||||||
contentDescription = "No Followers",
|
contentDescription = "No Followers",
|
||||||
modifier = Modifier.size(181.dp)
|
modifier = Modifier
|
||||||
|
.size(width = 181.dp, height = 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(24.dp))
|
Spacer(modifier = Modifier.height(if (AppState.darkMode) 9.dp else 24.dp))
|
||||||
androidx.compose.material.Text(
|
androidx.compose.material.Text(
|
||||||
text = "还没有人关注哦",
|
text = "还没有人关注你呢",
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.W600
|
fontWeight = FontWeight.W600
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(8.dp))
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
androidx.compose.material.Text(
|
androidx.compose.material.Text(
|
||||||
text = "去发布动态,吸引更多粉丝~",
|
text = "试着发信号出来,某人就会被吸引啦~",
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.W400
|
fontWeight = FontWeight.W400
|
||||||
|
|||||||
@@ -126,14 +126,14 @@ fun FollowingListScreen(userId: Int) {
|
|||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id =if(AppState.darkMode) R.mipmap.qst_gz_qs_as_img_my
|
id = if(AppState.darkMode) R.mipmap.frame_3
|
||||||
else R.mipmap.invalid_name_9),
|
else R.mipmap.invalid_name_9),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(181.dp)
|
modifier = Modifier.size(181.dp, 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(24.dp))
|
Spacer(modifier = Modifier.size(9.dp)) // 调整间距为9dp
|
||||||
androidx.compose.material.Text(
|
androidx.compose.material.Text(
|
||||||
text = "没有关注任何灵魂",
|
text = "还没有关注任何灵魂",
|
||||||
color = appColors.text,
|
color = appColors.text,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.W600
|
fontWeight = FontWeight.W600
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.aiosman.ravenow.ui.group
|
package com.aiosman.ravenow.ui.group
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -8,6 +9,10 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import com.aiosman.ravenow.AppStore
|
import com.aiosman.ravenow.AppStore
|
||||||
import com.aiosman.ravenow.ChatState
|
import com.aiosman.ravenow.ChatState
|
||||||
import com.aiosman.ravenow.data.api.ApiClient
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
|
import com.aiosman.ravenow.data.api.CreatePromptRuleRequestBody
|
||||||
|
import com.aiosman.ravenow.data.api.PromptRule
|
||||||
|
import com.aiosman.ravenow.data.api.PromptRuleQuota
|
||||||
|
import com.aiosman.ravenow.data.parseErrorResponse
|
||||||
import com.aiosman.ravenow.entity.ChatNotification
|
import com.aiosman.ravenow.entity.ChatNotification
|
||||||
import com.aiosman.ravenow.entity.GroupInfo
|
import com.aiosman.ravenow.entity.GroupInfo
|
||||||
import com.aiosman.ravenow.entity.GroupMember
|
import com.aiosman.ravenow.entity.GroupMember
|
||||||
@@ -22,9 +27,36 @@ class GroupChatInfoViewModel(
|
|||||||
var isLoading by mutableStateOf(false)
|
var isLoading by mutableStateOf(false)
|
||||||
var error by mutableStateOf<String?>(null)
|
var error by mutableStateOf<String?>(null)
|
||||||
var chatNotification by mutableStateOf<ChatNotification?>(null)
|
var chatNotification by mutableStateOf<ChatNotification?>(null)
|
||||||
|
var isAddingMemory by mutableStateOf(false)
|
||||||
|
var addMemoryError by mutableStateOf<String?>(null)
|
||||||
|
var addMemorySuccess by mutableStateOf(false)
|
||||||
val notificationStrategy get() = chatNotification?.strategy ?: "default"
|
val notificationStrategy get() = chatNotification?.strategy ?: "default"
|
||||||
|
|
||||||
|
// 记忆管理相关状态
|
||||||
|
var memoryQuota by mutableStateOf<PromptRuleQuota?>(null)
|
||||||
|
var memoryList by mutableStateOf<List<PromptRule>>(emptyList())
|
||||||
|
var isLoadingMemory by mutableStateOf(false)
|
||||||
|
var memoryError by mutableStateOf<String?>(null)
|
||||||
|
var promptOpenId by mutableStateOf<String?>(null)
|
||||||
init {
|
init {
|
||||||
loadGroupInfo()
|
loadGroupInfo()
|
||||||
|
loadPromptOpenId()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群聊中智能体的 OpenID
|
||||||
|
*/
|
||||||
|
private fun loadPromptOpenId() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
val response = ApiClient.api.createGroupChatAi(trtcGroupId = groupId)
|
||||||
|
val groupChatResponse = response.body()?.data
|
||||||
|
val prompts = groupChatResponse?.prompts
|
||||||
|
promptOpenId = prompts?.firstOrNull()?.openId
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("GroupChatInfoViewModel", "获取智能体OpenID失败: ${e.message}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
suspend fun updateNotificationStrategy(strategy: String) {
|
suspend fun updateNotificationStrategy(strategy: String) {
|
||||||
val result = ChatState.updateChatNotification(groupId.hashCode(), strategy)
|
val result = ChatState.updateChatNotification(groupId.hashCode(), strategy)
|
||||||
@@ -71,4 +103,218 @@ class GroupChatInfoViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加群记忆
|
||||||
|
* @param memoryText 记忆内容
|
||||||
|
* @param promptOpenId 智能体的 OpenID(可选),如果不提供则从群聊信息中获取
|
||||||
|
*/
|
||||||
|
fun addGroupMemory(memoryText: String, promptOpenId: String? = null) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
isAddingMemory = true
|
||||||
|
addMemoryError = null
|
||||||
|
addMemorySuccess = false
|
||||||
|
|
||||||
|
// 如果没有提供 promptOpenId,需要先获取群聊的智能体信息
|
||||||
|
val openId = promptOpenId ?: run {
|
||||||
|
// 通过 createGroupChatAi 接口获取群聊详细信息(包含 prompts)
|
||||||
|
val response = ApiClient.api.createGroupChatAi(trtcGroupId = groupId)
|
||||||
|
val groupChatResponse = response.body()?.data
|
||||||
|
val prompts = groupChatResponse?.prompts
|
||||||
|
|
||||||
|
if (prompts.isNullOrEmpty()) {
|
||||||
|
throw Exception("群聊中没有找到智能体,无法添加记忆")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用第一个智能体的 openId
|
||||||
|
prompts.firstOrNull()?.openId
|
||||||
|
?: throw Exception("无法获取智能体信息")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openId.isBlank()) {
|
||||||
|
throw Exception("智能体ID不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建智能体规则(群记忆)
|
||||||
|
val requestBody = CreatePromptRuleRequestBody(
|
||||||
|
rule = memoryText,
|
||||||
|
openId = openId
|
||||||
|
)
|
||||||
|
|
||||||
|
val response = ApiClient.api.createPromptRule(requestBody)
|
||||||
|
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
addMemorySuccess = true
|
||||||
|
Log.d("GroupChatInfoViewModel", "群记忆添加成功")
|
||||||
|
// 刷新记忆列表和配额
|
||||||
|
loadMemoryQuota(openId)
|
||||||
|
loadMemoryList(openId)
|
||||||
|
} else {
|
||||||
|
val errorResponse = parseErrorResponse(response.errorBody())
|
||||||
|
val errorMessage = errorResponse?.toServiceException()?.message
|
||||||
|
?: "添加群记忆失败: ${response.code()}"
|
||||||
|
throw Exception(errorMessage)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
addMemoryError = e.message ?: "添加群记忆失败"
|
||||||
|
Log.e("GroupChatInfoViewModel", "添加群记忆失败: ${e.message}", e)
|
||||||
|
} finally {
|
||||||
|
isAddingMemory = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取记忆配额信息
|
||||||
|
*/
|
||||||
|
fun loadMemoryQuota(openId: String? = null) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
isLoadingMemory = true
|
||||||
|
memoryError = null
|
||||||
|
|
||||||
|
val targetOpenId = openId ?: promptOpenId
|
||||||
|
if (targetOpenId.isNullOrBlank()) {
|
||||||
|
// 如果还没有获取到 openId,先获取
|
||||||
|
val response = ApiClient.api.createGroupChatAi(trtcGroupId = groupId)
|
||||||
|
val groupChatResponse = response.body()?.data
|
||||||
|
val prompts = groupChatResponse?.prompts
|
||||||
|
val fetchedOpenId = prompts?.firstOrNull()?.openId
|
||||||
|
?: throw Exception("无法获取智能体信息")
|
||||||
|
|
||||||
|
promptOpenId = fetchedOpenId
|
||||||
|
val quotaResponse = ApiClient.api.getPromptRuleQuota(fetchedOpenId)
|
||||||
|
if (quotaResponse.isSuccessful) {
|
||||||
|
memoryQuota = quotaResponse.body()?.data
|
||||||
|
} else {
|
||||||
|
throw Exception("获取配额信息失败: ${quotaResponse.code()}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val quotaResponse = ApiClient.api.getPromptRuleQuota(targetOpenId)
|
||||||
|
if (quotaResponse.isSuccessful) {
|
||||||
|
memoryQuota = quotaResponse.body()?.data
|
||||||
|
} else {
|
||||||
|
throw Exception("获取配额信息失败: ${quotaResponse.code()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
memoryError = e.message ?: "获取配额信息失败"
|
||||||
|
Log.e("GroupChatInfoViewModel", "获取配额信息失败: ${e.message}", e)
|
||||||
|
} finally {
|
||||||
|
isLoadingMemory = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取记忆列表
|
||||||
|
*/
|
||||||
|
fun loadMemoryList(openId: String? = null, page: Int = 1, pageSize: Int = 20) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
isLoadingMemory = true
|
||||||
|
memoryError = null
|
||||||
|
|
||||||
|
val targetOpenId = openId ?: promptOpenId
|
||||||
|
if (targetOpenId.isNullOrBlank()) {
|
||||||
|
// 如果还没有获取到 openId,先获取
|
||||||
|
val response = ApiClient.api.createGroupChatAi(trtcGroupId = groupId)
|
||||||
|
val groupChatResponse = response.body()?.data
|
||||||
|
val prompts = groupChatResponse?.prompts
|
||||||
|
val fetchedOpenId = prompts?.firstOrNull()?.openId
|
||||||
|
?: throw Exception("无法获取智能体信息")
|
||||||
|
|
||||||
|
promptOpenId = fetchedOpenId
|
||||||
|
val listResponse = ApiClient.api.getPromptRuleList(fetchedOpenId, page = page, pageSize = pageSize)
|
||||||
|
if (listResponse.isSuccessful) {
|
||||||
|
memoryList = listResponse.body()?.data?.list ?: emptyList()
|
||||||
|
} else {
|
||||||
|
throw Exception("获取记忆列表失败: ${listResponse.code()}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val listResponse = ApiClient.api.getPromptRuleList(targetOpenId, page = page, pageSize = pageSize)
|
||||||
|
if (listResponse.isSuccessful) {
|
||||||
|
memoryList = listResponse.body()?.data?.list ?: emptyList()
|
||||||
|
} else {
|
||||||
|
throw Exception("获取记忆列表失败: ${listResponse.code()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
memoryError = e.message ?: "获取记忆列表失败"
|
||||||
|
Log.e("GroupChatInfoViewModel", "获取记忆列表失败: ${e.message}", e)
|
||||||
|
} finally {
|
||||||
|
isLoadingMemory = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除记忆
|
||||||
|
*/
|
||||||
|
fun deleteMemory(ruleId: Int) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
isLoadingMemory = true
|
||||||
|
memoryError = null
|
||||||
|
|
||||||
|
val response = ApiClient.api.deletePromptRule(ruleId)
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
// 刷新记忆列表和配额
|
||||||
|
promptOpenId?.let { openId ->
|
||||||
|
loadMemoryQuota(openId)
|
||||||
|
loadMemoryList(openId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val errorResponse = parseErrorResponse(response.errorBody())
|
||||||
|
val errorMessage = errorResponse?.toServiceException()?.message
|
||||||
|
?: "删除记忆失败: ${response.code()}"
|
||||||
|
throw Exception(errorMessage)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
memoryError = e.message ?: "删除记忆失败"
|
||||||
|
Log.e("GroupChatInfoViewModel", "删除记忆失败: ${e.message}", e)
|
||||||
|
} finally {
|
||||||
|
isLoadingMemory = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新记忆
|
||||||
|
*/
|
||||||
|
fun updateMemory(ruleId: Int, newRuleText: String, targetOpenId: String? = null) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
isLoadingMemory = true
|
||||||
|
memoryError = null
|
||||||
|
|
||||||
|
val openId = targetOpenId ?: promptOpenId
|
||||||
|
?: throw Exception("无法获取智能体ID")
|
||||||
|
|
||||||
|
val requestBody = com.aiosman.ravenow.data.api.UpdatePromptRuleRequestBody(
|
||||||
|
id = ruleId,
|
||||||
|
rule = newRuleText,
|
||||||
|
openId = openId
|
||||||
|
)
|
||||||
|
|
||||||
|
val response = ApiClient.api.updatePromptRule(requestBody)
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
// 刷新记忆列表和配额
|
||||||
|
loadMemoryQuota(openId)
|
||||||
|
loadMemoryList(openId)
|
||||||
|
} else {
|
||||||
|
val errorResponse = parseErrorResponse(response.errorBody())
|
||||||
|
val errorMessage = errorResponse?.toServiceException()?.message
|
||||||
|
?: "更新记忆失败: ${response.code()}"
|
||||||
|
throw Exception(errorMessage)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
memoryError = e.message ?: "更新记忆失败"
|
||||||
|
Log.e("GroupChatInfoViewModel", "更新记忆失败: ${e.message}", e)
|
||||||
|
} finally {
|
||||||
|
isLoadingMemory = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,625 @@
|
|||||||
|
package com.aiosman.ravenow.ui.group
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun GroupMemoryManageContent(
|
||||||
|
groupId: String,
|
||||||
|
viewModel: GroupChatInfoViewModel,
|
||||||
|
onAddMemoryClick: () -> Unit = {},
|
||||||
|
onDismiss: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
val configuration = LocalConfiguration.current
|
||||||
|
val screenHeight = configuration.screenHeightDp.dp
|
||||||
|
val sheetHeight = screenHeight * 0.95f
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
// 编辑记忆的状态 - 存储正在编辑的记忆ID
|
||||||
|
var editingMemoryId by remember { mutableStateOf<Int?>(null) }
|
||||||
|
|
||||||
|
// 加载配额和列表数据
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
viewModel.loadMemoryQuota()
|
||||||
|
viewModel.loadMemoryList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val quota = viewModel.memoryQuota
|
||||||
|
val memoryList = viewModel.memoryList
|
||||||
|
val isLoading = viewModel.isLoadingMemory
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(sheetHeight)
|
||||||
|
.background(Color(0xFFFAF9FB))
|
||||||
|
) {
|
||||||
|
// 顶部栏:返回按钮 + 标题 + 加号按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(44.dp)
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
// 中间标题 - 绝对居中,不受其他组件影响
|
||||||
|
Text(
|
||||||
|
text = "记忆管理",
|
||||||
|
style = TextStyle(
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 17.sp,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
|
),
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
// 左侧返回按钮
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterStart)
|
||||||
|
.clip(RoundedCornerShape(296.dp))
|
||||||
|
.background(Color.White) // 浅灰色背景
|
||||||
|
.noRippleClickable { onDismiss() }
|
||||||
|
.padding(horizontal = 12.dp, vertical = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.drawable.rider_pro_back_icon),
|
||||||
|
contentDescription = "返回",
|
||||||
|
modifier = Modifier.size(16.dp),
|
||||||
|
colorFilter = ColorFilter.tint(Color.Black)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "返回",
|
||||||
|
style = TextStyle(
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Normal
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧圆形加号按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterEnd)
|
||||||
|
.size(32.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(Color.White)
|
||||||
|
.noRippleClickable { onAddMemoryClick() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "+",
|
||||||
|
style = TextStyle(
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Medium
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 浅黄色提示栏 - 显示真实的配额数据
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color(0xFFFBF8EF))
|
||||||
|
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Row(horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text("已付费:", style = TextStyle(color = Color(0x993C3C43), fontSize = 13.sp))
|
||||||
|
Spacer(Modifier.width(3.dp))
|
||||||
|
Text(
|
||||||
|
"${quota?.purchasedCount ?: 0}",
|
||||||
|
style = TextStyle(color = Color(0xFFFF8D28), fontSize = 13.sp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text("已使用:", style = TextStyle(color = Color(0x993C3C43), fontSize = 13.sp))
|
||||||
|
Spacer(Modifier.width(3.dp))
|
||||||
|
Text(
|
||||||
|
"${quota?.currentCount ?: 0}",
|
||||||
|
style = TextStyle(color = Color(0xFFFF8D28), fontSize = 13.sp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text("可用上限:", style = TextStyle(color = Color(0x993C3C43), fontSize = 13.sp))
|
||||||
|
Spacer(Modifier.width(3.dp))
|
||||||
|
Text(
|
||||||
|
"50",
|
||||||
|
style = TextStyle(color = Color(0xFFFF8D28), fontSize = 13.sp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记忆列表或空状态
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f)
|
||||||
|
) {
|
||||||
|
if (isLoading) {
|
||||||
|
// 加载中状态
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.size(40.dp),
|
||||||
|
color = Color(0xFFFF8D28)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (memoryList.isNotEmpty()) {
|
||||||
|
// 显示记忆列表
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 12.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
items(memoryList) { memory ->
|
||||||
|
MemoryItem(
|
||||||
|
memory = memory,
|
||||||
|
isEditing = editingMemoryId == memory.id,
|
||||||
|
onEdit = {
|
||||||
|
editingMemoryId = memory.id
|
||||||
|
},
|
||||||
|
onCancel = {
|
||||||
|
editingMemoryId = null
|
||||||
|
},
|
||||||
|
onSave = { newText ->
|
||||||
|
viewModel.updateMemory(memory.id, newText)
|
||||||
|
editingMemoryId = null
|
||||||
|
},
|
||||||
|
onDelete = {
|
||||||
|
viewModel.deleteMemory(memory.id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(vertical = 60.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.group),
|
||||||
|
contentDescription = "暂无记忆",
|
||||||
|
modifier = Modifier
|
||||||
|
.height(150.dp).width(180.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(10.dp))
|
||||||
|
Text(
|
||||||
|
text = "暂无记忆",
|
||||||
|
style = TextStyle(color = Color.Black, fontSize = 16.sp, fontWeight = FontWeight.SemiBold)
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(6.dp))
|
||||||
|
Text(
|
||||||
|
text = "点击上方按钮添加群记忆",
|
||||||
|
style = TextStyle(color = Color.Black, fontSize = 14.sp, fontWeight = FontWeight.Normal)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑记忆对话框
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun EditGroupMemoryDialog(
|
||||||
|
memory: com.aiosman.ravenow.data.api.PromptRule,
|
||||||
|
viewModel: GroupChatInfoViewModel,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onUpdateMemory: (String) -> Unit
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
var memoryText by remember { mutableStateOf(memory.rule) }
|
||||||
|
val maxLength = 500
|
||||||
|
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||||
|
|
||||||
|
val gradientColors = listOf(
|
||||||
|
Color(0xFF7C45ED),
|
||||||
|
Color(0xFF7C57EE),
|
||||||
|
Color(0xFF7BD8F8)
|
||||||
|
)
|
||||||
|
val gradientBrush = Brush.horizontalGradient(colors = gradientColors)
|
||||||
|
|
||||||
|
ModalBottomSheet(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
sheetState = sheetState,
|
||||||
|
containerColor = Color(0xFFFAF9FB),
|
||||||
|
dragHandle = {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(36.dp)
|
||||||
|
.height(5.dp)
|
||||||
|
.padding(top = 5.dp)
|
||||||
|
.background(
|
||||||
|
Color(0xFFCCCCCC),
|
||||||
|
RoundedCornerShape(100.dp)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 12.dp, vertical = 16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(88.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(brush = gradientBrush)
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(1.dp)
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.White)
|
||||||
|
.padding(12.dp),
|
||||||
|
contentAlignment = Alignment.TopStart
|
||||||
|
) {
|
||||||
|
BasicTextField(
|
||||||
|
value = memoryText,
|
||||||
|
onValueChange = { newText ->
|
||||||
|
if (newText.length <= maxLength) {
|
||||||
|
memoryText = newText
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cursorBrush = SolidColor(Color.Black),
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
textStyle = TextStyle(
|
||||||
|
fontSize = 13.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
lineHeight = 18.sp
|
||||||
|
),
|
||||||
|
decorationBox = { innerTextField ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
contentAlignment = Alignment.TopStart
|
||||||
|
) {
|
||||||
|
innerTextField()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
// 取消按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(34.dp)
|
||||||
|
.clip(RoundedCornerShape(653.8.dp))
|
||||||
|
.background(Color(0x147C7480))
|
||||||
|
.noRippleClickable { onDismiss() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "取消",
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 15.sp,
|
||||||
|
color = Color.Black
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(34.dp)
|
||||||
|
.clip(RoundedCornerShape(653.8.dp))
|
||||||
|
.background(Color(0xFF110C13))
|
||||||
|
.noRippleClickable {
|
||||||
|
if (memoryText.isNotBlank() && memoryText != memory.rule) {
|
||||||
|
onUpdateMemory(memoryText)
|
||||||
|
Toast.makeText(context, "记忆更新成功", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "保存",
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 15.sp,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记忆项组件
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun MemoryItem(
|
||||||
|
memory: com.aiosman.ravenow.data.api.PromptRule,
|
||||||
|
isEditing: Boolean = false,
|
||||||
|
onEdit: () -> Unit = {},
|
||||||
|
onCancel: () -> Unit = {},
|
||||||
|
onSave: (String) -> Unit = {},
|
||||||
|
onDelete: () -> Unit
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
var memoryText by remember { mutableStateOf(memory.rule) }
|
||||||
|
val maxLength = 500
|
||||||
|
|
||||||
|
// 渐变边框颜色
|
||||||
|
val gradientColors = listOf(
|
||||||
|
Color(0xFF7C45ED),
|
||||||
|
Color(0xFF7C57EE),
|
||||||
|
Color(0xFF7BD8F8)
|
||||||
|
)
|
||||||
|
val gradientBrush = Brush.horizontalGradient(colors = gradientColors)
|
||||||
|
|
||||||
|
// 当进入编辑模式时,重置文本
|
||||||
|
LaunchedEffect(isEditing) {
|
||||||
|
if (isEditing) {
|
||||||
|
memoryText = memory.rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEditing) {
|
||||||
|
// 编辑模式:显示编辑界面
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(Color.White)
|
||||||
|
.padding(horizontal = 12.dp, vertical = 16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
// 文本输入框 - 带渐变边框
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(88.dp)
|
||||||
|
) {
|
||||||
|
// 渐变边框层
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(brush = gradientBrush)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 内容层 - 白色背景,通过padding形成边框效果
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(1.dp)
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
.background(Color.White)
|
||||||
|
.padding(12.dp),
|
||||||
|
contentAlignment = Alignment.TopStart
|
||||||
|
) {
|
||||||
|
BasicTextField(
|
||||||
|
value = memoryText,
|
||||||
|
onValueChange = { newText ->
|
||||||
|
if (newText.length <= maxLength) {
|
||||||
|
memoryText = newText
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cursorBrush = SolidColor(Color.Black),
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
textStyle = TextStyle(
|
||||||
|
fontSize = 13.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
lineHeight = 18.sp
|
||||||
|
),
|
||||||
|
decorationBox = { innerTextField ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
contentAlignment = Alignment.TopStart
|
||||||
|
) {
|
||||||
|
innerTextField()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按钮行:取消和保存
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
// 取消按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(34.dp)
|
||||||
|
.clip(RoundedCornerShape(653.8.dp))
|
||||||
|
.background(Color(0x147C7480))
|
||||||
|
.noRippleClickable { onCancel() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "取消",
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 15.sp,
|
||||||
|
color = Color.Black
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(34.dp)
|
||||||
|
.clip(RoundedCornerShape(653.8.dp))
|
||||||
|
.background(Color(0xFF110C13))
|
||||||
|
.noRippleClickable {
|
||||||
|
if (memoryText.isNotBlank() && memoryText != memory.rule) {
|
||||||
|
onSave(memoryText)
|
||||||
|
Toast.makeText(context, "记忆更新成功", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "保存",
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 15.sp,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 显示模式:显示记忆内容
|
||||||
|
// 格式化日期:从 "2025-10-20T10:30:00Z" 格式转换为 "2025年10月20日"
|
||||||
|
val formattedDate = try {
|
||||||
|
if (memory.createdAt.length >= 10) {
|
||||||
|
val dateStr = memory.createdAt.substring(0, 10)
|
||||||
|
val parts = dateStr.split("-")
|
||||||
|
if (parts.size == 3) {
|
||||||
|
"${parts[0]}年${parts[1].toInt()}月${parts[2].toInt()}日"
|
||||||
|
} else {
|
||||||
|
dateStr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memory.createdAt
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
if (memory.createdAt.length >= 10) memory.createdAt.substring(0, 10) else memory.createdAt
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(Color.White)
|
||||||
|
.padding(horizontal = 12.dp, vertical = 16.dp)
|
||||||
|
) {
|
||||||
|
// 主文本 - 顶部
|
||||||
|
Text(
|
||||||
|
text = memory.rule,
|
||||||
|
style = TextStyle(
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 13.sp,
|
||||||
|
lineHeight = 18.sp
|
||||||
|
),
|
||||||
|
maxLines = 3,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// 底部行:日期 + 编辑删除按钮
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
|
) {
|
||||||
|
// 日期文本 - 左侧
|
||||||
|
Text(
|
||||||
|
text = formattedDate,
|
||||||
|
style = TextStyle(
|
||||||
|
color = Color(0x993C3C43),
|
||||||
|
fontSize = 11.sp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 编辑和删除图标 - 右侧
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// 编辑图标
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.mipmap.icons_infor_edit),
|
||||||
|
contentDescription = "编辑",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(20.dp)
|
||||||
|
.noRippleClickable { onEdit() },
|
||||||
|
colorFilter = ColorFilter.tint(Color.Black)
|
||||||
|
)
|
||||||
|
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.mipmap.iconsdelete),
|
||||||
|
contentDescription = "删除",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(20.dp)
|
||||||
|
.noRippleClickable { onDelete() },
|
||||||
|
colorFilter = ColorFilter.tint(Color(0xFFEE2A33))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -97,13 +97,13 @@ fun AgentChatListScreen() {
|
|||||||
Spacer(modifier = Modifier.height(39.dp))
|
Spacer(modifier = Modifier.height(39.dp))
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id = if(AppState.darkMode) R.mipmap.qs_znt_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.juhao_dark
|
||||||
else R.mipmap.invalid_name_5),
|
else R.mipmap.invalid_name_5),
|
||||||
contentDescription = "null data",
|
contentDescription = "null data",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(181.dp)
|
.size(width = 181.dp, height = 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(if (AppState.darkMode) 9.dp else 24.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.agent_chat_empty_title),
|
text = stringResource(R.string.agent_chat_empty_title),
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
|
|||||||
@@ -175,13 +175,13 @@ fun AllChatListScreen() {
|
|||||||
Spacer(modifier = Modifier.height(39.dp))
|
Spacer(modifier = Modifier.height(39.dp))
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id = if(AppState.darkMode) R.mipmap.qs_py_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.piao_dark
|
||||||
else R.mipmap.invalid_name_2),
|
else R.mipmap.invalid_name_2),
|
||||||
contentDescription = "null data",
|
contentDescription = "null data",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(181.dp)
|
.size(width = 181.dp, height = 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(if (AppState.darkMode) 9.dp else 24.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.friend_chat_empty_title),
|
text = stringResource(R.string.friend_chat_empty_title),
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
|
|||||||
@@ -85,13 +85,13 @@ fun FriendChatListScreen() {
|
|||||||
Spacer(modifier = Modifier.height(39.dp))
|
Spacer(modifier = Modifier.height(39.dp))
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id = if(AppState.darkMode) R.mipmap.qs_py_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.piao_dark
|
||||||
else R.mipmap.invalid_name_2),
|
else R.mipmap.invalid_name_2),
|
||||||
contentDescription = "null data",
|
contentDescription = "null data",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(181.dp)
|
.size(width = 181.dp, height = 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(if (AppState.darkMode) 9.dp else 24.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.friend_chat_empty_title),
|
text = stringResource(R.string.friend_chat_empty_title),
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
|
|||||||
@@ -77,13 +77,13 @@ fun GroupChatListScreen() {
|
|||||||
Spacer(modifier = Modifier.height(39.dp))
|
Spacer(modifier = Modifier.height(39.dp))
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id = if(AppState.darkMode) R.mipmap.qs_ql_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.fei_dark
|
||||||
else R.mipmap.invalid_name_12),
|
else R.mipmap.invalid_name_12),
|
||||||
contentDescription = "null data",
|
contentDescription = "null data",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(181.dp)
|
.size(width = 181.dp, height = 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(if (AppState.darkMode) 9.dp else 24.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.group_chat_empty),
|
text = stringResource(R.string.group_chat_empty),
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
|
|||||||
@@ -189,16 +189,17 @@ fun GalleryGrid(
|
|||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id = if(AppState.darkMode) R.mipmap.qs_dt_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.shuihu_dark
|
||||||
else R.mipmap.invalid_name_7),
|
else R.mipmap.invalid_name_7),
|
||||||
contentDescription = "暂无图片",
|
contentDescription = "暂无图片",
|
||||||
modifier = Modifier.size(181.dp),
|
modifier = Modifier
|
||||||
|
.size(width = 181.dp, height = 153.dp),
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(if(AppState.darkMode) 9.dp else 24.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = "故事还没开始",
|
text = "你的故事还没开始",
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
fontWeight = FontWeight.W600
|
fontWeight = FontWeight.W600
|
||||||
|
|||||||
@@ -220,7 +220,8 @@ fun EmptyAgentsView() {
|
|||||||
.align(Alignment.CenterHorizontally),
|
.align(Alignment.CenterHorizontally),
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
// 根据是否为深色模式调整间距
|
||||||
|
Spacer(modifier = Modifier.height(if(AppState.darkMode) 9.dp else 24.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = "专属AI等你召唤",
|
text = "专属AI等你召唤",
|
||||||
|
|||||||
@@ -123,14 +123,15 @@ fun LikeNoticeScreen() {
|
|||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(
|
painter = painterResource(
|
||||||
id =if(AppState.darkMode) R.mipmap.qst_z_qs_as_img
|
id = if(AppState.darkMode) R.mipmap.sanqiu_dark
|
||||||
else R.mipmap.invalid_name_6),
|
else R.mipmap.invalid_name_6),
|
||||||
contentDescription = "No Notice",
|
contentDescription = "No Notice",
|
||||||
modifier = Modifier.size(181.dp)
|
modifier = Modifier
|
||||||
|
.size(width = 181.dp, height = 153.dp)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(if (AppState.darkMode) 9.dp else 24.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "你的赞在路上~",
|
text = "你的赞在赶来的路上",
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.W600,
|
fontWeight = FontWeight.W600,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ fun SplashScreen() {
|
|||||||
) {
|
) {
|
||||||
// 居中的图标
|
// 居中的图标
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.mipmap.invalid_name),
|
painter = painterResource(id = R.mipmap.kp_logo_img),
|
||||||
contentDescription = "App Logo",
|
contentDescription = "App Logo",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
|
|||||||
BIN
app/src/main/res/mipmap-hdpi/ai_dark.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/fei_dark.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/frame_3.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/frame_4.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/icons_brain.png
Normal file
|
After Width: | Height: | Size: 551 B |
BIN
app/src/main/res/mipmap-hdpi/invalid_dark.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/mipmap-hdpi/juhao_dark.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-hdpi/piao_dark.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/sanqiu_dark.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/shuihu_dark.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/res/mipmap-hdpi/tietie_dark.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
app/src/main/res/mipmap-mdpi/ai_dark.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-mdpi/fei_dark.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/frame_3.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/frame_4.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/icons_brain.png
Normal file
|
After Width: | Height: | Size: 419 B |
BIN
app/src/main/res/mipmap-mdpi/invalid_dark.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/juhao_dark.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/piao_dark.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-mdpi/sanqiu_dark.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/shuihu_dark.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/tietie_dark.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/fei_dark.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/frame_3.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/frame_4.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-xhdpi/group.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-xhdpi/icons_brain.png
Normal file
|
After Width: | Height: | Size: 718 B |
BIN
app/src/main/res/mipmap-xhdpi/iconsdelete.png
Normal file
|
After Width: | Height: | Size: 312 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/juhao_dark.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/piao_dark.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/sanqiu_dark.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/shuihu_dark.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/mipmap-xhdpi/tietie_dark.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.3 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/fei_dark.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/frame_3.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/frame_4.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/group.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/icons_brain.png
Normal file
|
After Width: | Height: | Size: 980 B |
BIN
app/src/main/res/mipmap-xxhdpi/iconsdelete.png
Normal file
|
After Width: | Height: | Size: 438 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.0 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/juhao_dark.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/piao_dark.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/sanqiu_dark.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/shuihu_dark.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/tietie_dark.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 5.4 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/fei_dark.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/frame_3.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/frame_4.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/group.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/icons_brain.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/iconsdelete.png
Normal file
|
After Width: | Height: | Size: 575 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/juhao_dark.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/piao_dark.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/sanqiu_dark.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/shuihu_dark.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/tietie_dark.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
@@ -248,5 +248,38 @@
|
|||||||
<string name="select_apply_to_use_theme">「適用」を選択してこのテーマを使用</string>
|
<string name="select_apply_to_use_theme">「適用」を選択してこのテーマを使用</string>
|
||||||
<string name="tap_cancel_to_preview_other_themes">「キャンセル」をタップして他のテーマをプレビュー</string>
|
<string name="tap_cancel_to_preview_other_themes">「キャンセル」をタップして他のテーマをプレビュー</string>
|
||||||
|
|
||||||
|
<!-- Group Chat Info -->
|
||||||
|
<string name="group_chat_info_title">グループチャット情報</string>
|
||||||
|
<string name="group_chat_info_add_member">メンバーを追加</string>
|
||||||
|
<string name="group_chat_info_notification">通知</string>
|
||||||
|
<string name="group_chat_info_share">共有</string>
|
||||||
|
<string name="group_chat_info_unlock_extension">グループ拡張機能を解除</string>
|
||||||
|
<string name="group_chat_info_group_memory">グループメモリ</string>
|
||||||
|
<string name="group_chat_info_memory_description">AIは記憶に基づいてグループチャットであなたをより理解します</string>
|
||||||
|
<string name="group_chat_info_add_memory">メモリを追加</string>
|
||||||
|
<string name="group_chat_info_memory_manage">メモリ管理</string>
|
||||||
|
<string name="group_chat_info_group_settings">グループ設定</string>
|
||||||
|
<string name="group_chat_info_group_visibility">グループの可視性</string>
|
||||||
|
<string name="group_chat_info_locked">ロック中</string>
|
||||||
|
<string name="group_chat_info_member_manage">メンバー管理</string>
|
||||||
|
<string name="group_chat_info_wallpaper">グループチャット壁紙</string>
|
||||||
|
<string name="group_chat_info_dissolve">グループチャットを解散</string>
|
||||||
|
<string name="group_chat_info_add_group_memory">グループメモリを追加</string>
|
||||||
|
<string name="group_chat_info_member_count">%d人のメンバー</string>
|
||||||
|
<string name="group_chat_info_memory_input_hint">グループの記憶内容を入力、例えば、グループのメンバーは科学技術と設計を議論するのが好きである....</string>
|
||||||
|
<string name="group_chat_info_memory_cost">メモリを追加すると20コインを消費します</string>
|
||||||
|
<string name="group_chat_info_memory_optimization">AIは記憶に基づいて返信を最適化します</string>
|
||||||
|
<string name="group_chat_info_memory_editable">いつでも編集または削除できます</string>
|
||||||
|
<string name="group_chat_info_memory_add_success">グループメモリが正常に追加されました</string>
|
||||||
|
<string name="group_chat_info_permission_settings">グループ権限設定</string>
|
||||||
|
<string name="group_chat_info_public_group">公開グループ</string>
|
||||||
|
<string name="group_chat_info_public_group_desc">誰でも検索して参加できます</string>
|
||||||
|
<string name="group_chat_info_private_group">プライベートグループ</string>
|
||||||
|
<string name="group_chat_info_private_group_desc">招待のみ</string>
|
||||||
|
<string name="group_chat_info_private_group_cost">50コイン</string>
|
||||||
|
<string name="group_chat_info_balance">残高: %1$dコイン</string>
|
||||||
|
<string name="group_chat_info_unlock_cost">アンロック費用: %1$dコイン</string>
|
||||||
|
<string name="group_chat_info_done">完了</string>
|
||||||
|
<string name="group_chat_info_recharge_hint">チャージしてより多くのコインを獲得できます</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|||||||
@@ -152,8 +152,8 @@
|
|||||||
<string name="favourites_null">暂无数据</string>
|
<string name="favourites_null">暂无数据</string>
|
||||||
|
|
||||||
<string name="agent_chat_list_title">智能体聊天</string>
|
<string name="agent_chat_list_title">智能体聊天</string>
|
||||||
<string name="agent_chat_empty_title">AI 在等你的开场白</string>
|
<string name="agent_chat_empty_title">AI们在等你开启第一句对话</string>
|
||||||
<string name="agent_chat_empty_subtitle">去首页探索一下,主动发起对话!</string>
|
<string name="agent_chat_empty_subtitle">去首页探索一下,主动发起一场对话!</string>
|
||||||
<string name="agent_chat_me_prefix">我: </string>
|
<string name="agent_chat_me_prefix">我: </string>
|
||||||
<string name="agent_chat_image">[图片]</string>
|
<string name="agent_chat_image">[图片]</string>
|
||||||
<string name="agent_chat_voice">[语音]</string>
|
<string name="agent_chat_voice">[语音]</string>
|
||||||
@@ -163,12 +163,12 @@
|
|||||||
<string name="agent_chat_load_failed">加载失败</string>
|
<string name="agent_chat_load_failed">加载失败</string>
|
||||||
<string name="agent_chat_load_more_failed">加载更多失败</string>
|
<string name="agent_chat_load_more_failed">加载更多失败</string>
|
||||||
<string name="agent_chat_user_info_failed">获取用户信息失败: %s</string>
|
<string name="agent_chat_user_info_failed">获取用户信息失败: %s</string>
|
||||||
<string name="group_chat_empty">没有群聊,宇宙好安静</string>
|
<string name="group_chat_empty">没有群聊消息的宇宙太安静了</string>
|
||||||
<string name="group_chat_empty_title">没有群聊消息的宇宙太安静了</string>
|
<string name="group_chat_empty_title">没有群聊消息的宇宙太安静了</string>
|
||||||
<string name="group_chat_empty_subtitle">在首页探索感兴趣的主题房间</string>
|
<string name="group_chat_empty_subtitle">在首页探索感兴趣的主题房间</string>
|
||||||
<string name="group_chat_empty_join">去首页探索感兴趣的高能对话</string>
|
<string name="group_chat_empty_join">去首页探索感兴趣的主题房间</string>
|
||||||
<string name="friend_chat_empty_title">和朋友,还没有对话哦~</string>
|
<string name="friend_chat_empty_title">你和朋友,还没说第一句话呢</string>
|
||||||
<string name="friend_chat_empty_subtitle">点击好友头像,即刻发起聊天</string>
|
<string name="friend_chat_empty_subtitle">一段崭新的友谊 等待被唤醒</string>
|
||||||
<string name="friend_chat_me_prefix">我: </string>
|
<string name="friend_chat_me_prefix">我: </string>
|
||||||
<string name="friend_chat_load_failed">加载失败</string>
|
<string name="friend_chat_load_failed">加载失败</string>
|
||||||
<string name="create_group_chat">创建群聊</string>
|
<string name="create_group_chat">创建群聊</string>
|
||||||
@@ -250,4 +250,45 @@
|
|||||||
<string name="each_theme_unique_experience">每个主题都有自己独特的体验</string>
|
<string name="each_theme_unique_experience">每个主题都有自己独特的体验</string>
|
||||||
<string name="select_apply_to_use_theme">选择"应用"可选中这个主题</string>
|
<string name="select_apply_to_use_theme">选择"应用"可选中这个主题</string>
|
||||||
<string name="tap_cancel_to_preview_other_themes">轻触"取消"可预览其他主题</string>
|
<string name="tap_cancel_to_preview_other_themes">轻触"取消"可预览其他主题</string>
|
||||||
|
|
||||||
|
<!-- Group Chat Info -->
|
||||||
|
<string name="group_chat_info_title">群聊信息</string>
|
||||||
|
<string name="group_chat_info_add_member">添加成员</string>
|
||||||
|
<string name="group_chat_info_notification">通知</string>
|
||||||
|
<string name="group_chat_info_share">分享</string>
|
||||||
|
<string name="group_chat_info_unlock_extension">解锁群扩展</string>
|
||||||
|
<string name="group_chat_info_group_memory">群记忆</string>
|
||||||
|
<string name="group_chat_info_memory_description">AI 会根据记忆在群聊里更懂你</string>
|
||||||
|
<string name="group_chat_info_add_memory">添加记忆</string>
|
||||||
|
<string name="group_chat_info_memory_manage">记忆管理</string>
|
||||||
|
<string name="group_chat_info_group_settings">群资料设置</string>
|
||||||
|
<string name="group_chat_info_group_visibility">群可见性</string>
|
||||||
|
<string name="group_chat_info_locked">待解锁</string>
|
||||||
|
<string name="group_chat_info_member_manage">成员管理</string>
|
||||||
|
<string name="group_chat_info_wallpaper">群聊壁纸</string>
|
||||||
|
<string name="group_chat_info_dissolve">解散群聊</string>
|
||||||
|
<string name="group_chat_info_add_group_memory">添加群记忆</string>
|
||||||
|
<string name="group_chat_info_member_count">%d 位成员</string>
|
||||||
|
<string name="group_chat_info_memory_input_hint">输入群记忆内容,例如:群成员喜欢讨论科技和设计....</string>
|
||||||
|
<string name="group_chat_info_memory_cost">添加记忆需消耗 20 派币</string>
|
||||||
|
<string name="group_chat_info_memory_optimization">AI 将基于记忆优化回复</string>
|
||||||
|
<string name="group_chat_info_memory_editable">可随时编辑或删除</string>
|
||||||
|
<string name="group_chat_info_memory_add_success">群记忆添加成功</string>
|
||||||
|
<string name="group_chat_info_permission_settings">群权限设置</string>
|
||||||
|
<string name="group_chat_info_public_group">公开群组</string>
|
||||||
|
<string name="group_chat_info_public_group_desc">任何人都可搜索并加入</string>
|
||||||
|
<string name="group_chat_info_private_group">私密群组</string>
|
||||||
|
<string name="group_chat_info_private_group_desc">仅限邀请加入</string>
|
||||||
|
<string name="group_chat_info_private_group_cost">50 派币</string>
|
||||||
|
<string name="group_chat_info_balance">余额: %1$d 派币</string>
|
||||||
|
<string name="group_chat_info_unlock_cost">解锁费用: %1$d 派币</string>
|
||||||
|
<string name="group_chat_info_done">完成</string>
|
||||||
|
<string name="group_chat_info_recharge_hint">可通过充值获得更多派币</string>
|
||||||
|
|
||||||
|
<!-- Edit Profile Extras -->
|
||||||
|
<string name="mbti_type">MBTI 类型</string>
|
||||||
|
<string name="zodiac">星座</string>
|
||||||
|
<string name="save">保存</string>
|
||||||
|
<string name="choose_mbti">选择 MBTI</string>
|
||||||
|
<string name="choose_zodiac">选择星座</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -246,5 +246,43 @@
|
|||||||
<string name="select_apply_to_use_theme">Select "Apply" to use this theme</string>
|
<string name="select_apply_to_use_theme">Select "Apply" to use this theme</string>
|
||||||
<string name="tap_cancel_to_preview_other_themes">Tap "Cancel" to preview other themes</string>
|
<string name="tap_cancel_to_preview_other_themes">Tap "Cancel" to preview other themes</string>
|
||||||
|
|
||||||
|
<!-- Group Chat Info -->
|
||||||
|
<string name="group_chat_info_title">Group Chat Info</string>
|
||||||
|
<string name="group_chat_info_add_member">Add Member</string>
|
||||||
|
<string name="group_chat_info_notification">Notification</string>
|
||||||
|
<string name="group_chat_info_share">Share</string>
|
||||||
|
<string name="group_chat_info_unlock_extension">Unlock Group Extension</string>
|
||||||
|
<string name="group_chat_info_group_memory">Group Memory</string>
|
||||||
|
<string name="group_chat_info_memory_description">AI will understand you better in group chat based on memory</string>
|
||||||
|
<string name="group_chat_info_add_memory">Add Memory</string>
|
||||||
|
<string name="group_chat_info_memory_manage">Memory Management</string>
|
||||||
|
<string name="group_chat_info_group_settings">Group Settings</string>
|
||||||
|
<string name="group_chat_info_group_visibility">Group Visibility</string>
|
||||||
|
<string name="group_chat_info_locked">Locked</string>
|
||||||
|
<string name="group_chat_info_member_manage">Member Management</string>
|
||||||
|
<string name="group_chat_info_wallpaper">Group Chat Wallpaper</string>
|
||||||
|
<string name="group_chat_info_dissolve">Dissolve Group Chat</string>
|
||||||
|
<string name="group_chat_info_add_group_memory">Add Group Memory</string>
|
||||||
|
<string name="group_chat_info_member_count">%d members</string>
|
||||||
|
<string name="group_chat_info_memory_input_hint">Input group memory content, for example: Group members enjoy discussing technology and design …</string>
|
||||||
|
<string name="group_chat_info_memory_cost">Adding memory consumes 20 coins</string>
|
||||||
|
<string name="group_chat_info_memory_optimization">AI will optimize replies based on memory</string>
|
||||||
|
<string name="group_chat_info_memory_editable">Can be edited or deleted at any time</string>
|
||||||
|
<string name="group_chat_info_memory_add_success">Group memory added successfully</string>
|
||||||
|
<string name="group_chat_info_permission_settings">Group Permission Settings</string>
|
||||||
|
<string name="group_chat_info_public_group">Public Group</string>
|
||||||
|
<string name="group_chat_info_public_group_desc">Anyone can search and join</string>
|
||||||
|
<string name="group_chat_info_private_group">Private Group</string>
|
||||||
|
<string name="group_chat_info_private_group_desc">Invitation only</string>
|
||||||
|
<string name="group_chat_info_private_group_cost">50 coins</string>
|
||||||
|
<string name="group_chat_info_balance">Balance: %1$d coins</string>
|
||||||
|
<string name="group_chat_info_unlock_cost">Unlock cost: %1$d coins</string>
|
||||||
|
<string name="group_chat_info_done">Done</string>
|
||||||
|
<string name="group_chat_info_recharge_hint">You can recharge to get more coins</string>
|
||||||
|
<!-- Edit Profile Extras -->
|
||||||
|
<string name="mbti_type">MBTI</string>
|
||||||
|
<string name="zodiac">Zodiac</string>
|
||||||
|
<string name="save">Save</string>
|
||||||
|
<string name="choose_mbti">Choose MBTI</string>
|
||||||
|
<string name="choose_zodiac">Choose Zodiac</string>
|
||||||
</resources>
|
</resources>
|
||||||