Merge branch 'main' into zhong_1

This commit is contained in:
2025-11-10 21:06:07 +08:00
committed by GitHub
28 changed files with 719 additions and 292 deletions

View File

@@ -21,6 +21,8 @@ object AccountEditViewModel : ViewModel() {
var name by mutableStateOf("")
var bio by mutableStateOf("")
var imageUrl by mutableStateOf<Uri?>(null)
var bannerImageUrl by mutableStateOf<Uri?>(null)
var bannerFile by mutableStateOf<File?>(null)
val accountService: AccountService = AccountServiceImpl()
var profile by mutableStateOf<AccountProfileEntity?>(null)
var croppedBitmap by mutableStateOf<Bitmap?>(null)
@@ -82,6 +84,30 @@ object AccountEditViewModel : ViewModel() {
it.compress(Bitmap.CompressFormat.JPEG, 100, file.outputStream())
UploadImage(file, "avatar.jpg", "", "jpg")
}
// 处理背景图更新
val newBanner = bannerImageUrl?.let { uri ->
bannerFile?.let { file ->
val cursor = context.contentResolver.query(uri, null, null, null, null)
var uploadBanner: UploadImage? = null
cursor?.use { cur ->
val columnIndex = cur.getColumnIndex("_display_name")
if (cur.moveToFirst() && columnIndex != -1) {
val displayName = cur.getString(columnIndex)
val extension = displayName.substringAfterLast(".")
Log.d("AccountEditViewModel", "Banner file name: $displayName, extension: $extension")
uploadBanner = UploadImage(file, displayName, uri.toString(), extension)
} else {
// 如果无法获取文件名,使用默认值
val displayName = "banner.jpg"
val extension = "jpg"
uploadBanner = UploadImage(file, displayName, uri.toString(), extension)
}
}
uploadBanner
}
}
// 去除换行符,确保昵称和个人简介不包含换行
val cleanName = name.trim().replace("\n", "").replace("\r", "")
val cleanBio = bio.trim().replace("\n", "").replace("\r", "")
@@ -89,7 +115,7 @@ object AccountEditViewModel : ViewModel() {
val newName = if (cleanName == profile?.nickName) null else cleanName
accountService.updateProfile(
avatar = newAvatar,
banner = null,
banner = newBanner,
nickName = newName,
bio = cleanBio
)
@@ -100,6 +126,9 @@ object AccountEditViewModel : ViewModel() {
com.aiosman.ravenow.AppStore.setUserZodiac(uid, zodiac)
}
} catch (_: Exception) { }
// 清除背景图状态
bannerImageUrl = null
bannerFile = null
// 刷新用户资料
reloadProfile()
// 刷新个人资料页面的用户资料
@@ -116,6 +145,8 @@ object AccountEditViewModel : ViewModel() {
name = ""
bio = ""
imageUrl = null
bannerImageUrl = null
bannerFile = null
croppedBitmap = null
isUpdating = false
isLoading = false

View File

@@ -32,6 +32,7 @@ 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.AppState
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R
@@ -80,6 +81,10 @@ fun MbtiSelectScreen() {
isSelected = mbti == currentMbti,
onClick = {
model.mbti = mbti
// 立即保存到本地存储,确保选择后立即生效
AppState.UserId?.let { uid ->
com.aiosman.ravenow.AppStore.setUserMbti(uid, mbti)
}
navController.navigateUp()
}
)

View File

@@ -29,24 +29,55 @@ 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.AppState
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(
"白羊座", "金牛座", "双子座", "巨蟹座",
"狮子座", "处女座", "天秤座", "天蝎座",
"射手座", "摩羯座", "水瓶座", "双鱼座"
// 星座资源ID列表
val ZODIAC_SIGN_RES_IDS = listOf(
R.string.zodiac_aries,
R.string.zodiac_taurus,
R.string.zodiac_gemini,
R.string.zodiac_cancer,
R.string.zodiac_leo,
R.string.zodiac_virgo,
R.string.zodiac_libra,
R.string.zodiac_scorpio,
R.string.zodiac_sagittarius,
R.string.zodiac_capricorn,
R.string.zodiac_aquarius,
R.string.zodiac_pisces
)
/**
* 根据存储的星座字符串可能是任何语言找到对应的资源ID
* 如果找不到返回null
*/
@Composable
fun findZodiacResId(storedZodiac: String?): Int? {
if (storedZodiac.isNullOrEmpty()) return null
// 尝试在所有语言的资源中查找匹配
ZODIAC_SIGN_RES_IDS.forEachIndexed { index, resId ->
val zodiacText = stringResource(resId)
if (zodiacText == storedZodiac) {
return resId
}
}
// 如果找不到精确匹配尝试通过资源ID索引查找兼容旧数据
// 这里可以根据需要添加更多兼容逻辑
return null
}
@Composable
fun ZodiacSelectScreen() {
val navController = LocalNavController.current
val appColors = LocalAppTheme.current
val model = AccountEditViewModel
val currentZodiac = model.zodiac
val currentZodiacResId = findZodiacResId(model.zodiac)
Column(
modifier = Modifier
@@ -70,12 +101,20 @@ fun ZodiacSelectScreen() {
modifier = Modifier.fillMaxSize(),
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 16.dp, vertical = 8.dp)
) {
items(ZODIAC_SIGNS) { zodiac ->
items(ZODIAC_SIGN_RES_IDS.size) { index ->
val zodiacResId = ZODIAC_SIGN_RES_IDS[index]
val zodiacText = stringResource(zodiacResId)
ZodiacItem(
zodiac = zodiac,
isSelected = zodiac == currentZodiac,
zodiac = zodiacText,
zodiacResId = zodiacResId,
isSelected = zodiacResId == currentZodiacResId,
onClick = {
model.zodiac = zodiac
// 保存当前语言的星座文本
model.zodiac = zodiacText
// 立即保存到本地存储,确保选择后立即生效
AppState.UserId?.let { uid ->
com.aiosman.ravenow.AppStore.setUserZodiac(uid, zodiacText)
}
navController.navigateUp()
}
)
@@ -88,6 +127,7 @@ fun ZodiacSelectScreen() {
@Composable
fun ZodiacItem(
zodiac: String,
zodiacResId: Int,
isSelected: Boolean,
onClick: () -> Unit
) {

View File

@@ -72,6 +72,7 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.SolidColor
import com.aiosman.ravenow.ConstVars
import com.aiosman.ravenow.ui.composables.pickupAndCompressLauncher
import android.widget.Toast
import java.io.File
/**
@@ -97,6 +98,10 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
quality = 100
) { uri, file ->
// 处理选中的图片
// 保存到 ViewModel 中,等待保存时一起上传
model.bannerImageUrl = uri
model.bannerFile = file
// 如果提供了回调,也调用它(用于个人主页直接更新)
onUpdateBanner?.invoke(uri, file, context)
}
@@ -104,10 +109,21 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
// 去除换行符,确保昵称不包含换行
val cleanValue = value.replace("\n", "").replace("\r", "")
model.name = cleanValue
// 实时验证,但不显示错误(只在保存时显示)
usernameError = when {
cleanValue.trim().isEmpty() -> "昵称不能为空"
cleanValue.length < 3 -> "昵称长度不能小于3"
cleanValue.length > 20 -> "昵称长度不能大于20"
cleanValue.trim().isEmpty() -> context.getString(R.string.error_nickname_empty)
cleanValue.length < 3 -> context.getString(R.string.error_nickname_too_short)
cleanValue.length > 20 -> context.getString(R.string.error_nickname_too_long)
else -> null
}
}
fun validateNickname(): String? {
val cleanValue = model.name.replace("\n", "").replace("\r", "")
return when {
cleanValue.trim().isEmpty() -> context.getString(R.string.error_nickname_empty)
cleanValue.length < 3 -> context.getString(R.string.error_nickname_too_short)
cleanValue.length > 20 -> context.getString(R.string.error_nickname_too_long)
else -> null
}
}
@@ -118,8 +134,17 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
// 去除换行符,确保个人简介不包含换行
val cleanValue = value.replace("\n", "").replace("\r", "")
model.bio = cleanValue
// 实时验证,但不显示错误(只在保存时显示)
bioError = when {
cleanValue.length > 100 -> "个人简介长度不能大于100"
cleanValue.length > 100 -> context.getString(R.string.error_bio_too_long)
else -> null
}
}
fun validateBio(): String? {
val cleanValue = model.bio.replace("\n", "").replace("\r", "")
return when {
cleanValue.length > 100 -> context.getString(R.string.error_bio_too_long)
else -> null
}
}
@@ -146,21 +171,21 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
model.reloadProfile()
}
// 设置状态栏为透明,使用浅色图标(因为顶部背景是深色图片)
// 设置状态栏为透明,根据暗色模式决定图标颜色
val systemUiController = rememberSystemUiController()
LaunchedEffect(Unit) {
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = false)
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = !AppState.darkMode)
}
StatusBarMaskLayout(
modifier = Modifier.background(Color(0xFFFAF9FB)),
darkIcons = false, // 浅色图标(白色),因为顶部背景是深
modifier = Modifier.background(appColors.background),
darkIcons = !AppState.darkMode, // 根据暗色模式决定图标颜
maskBoxBackgroundColor = Color.Transparent
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFFFAF9FB))
.background(appColors.background)
) {
when {
model.isLoading -> {
@@ -179,7 +204,8 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
modifier = Modifier.fillMaxSize()
) {
// 顶部背景区域(圆角在底部,覆盖状态栏)
val banner = model.profile?.banner
// 优先显示新选择的背景图,如果没有则显示原有的背景图
val banner = model.bannerImageUrl?.toString() ?: model.profile?.banner
val statusBarPadding = WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
Box(
modifier = Modifier
@@ -230,21 +256,13 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
) {
// 更换封面图标
Icon(
painter = painterResource(
id = if (AppState.darkMode) {
// TODO: 添加更换封面暗色模式图标
R.mipmap.frame_4 // 临时占位,需替换为实际图标
} else {
// TODO: 添加更换封面亮色模式图标
R.mipmap.fengm // 临时占位,需替换为实际图标
}
),
painter = painterResource(id = R.mipmap.fengm),
contentDescription = null,
modifier = Modifier.size(16.dp),
tint = Color.White
)
Text(
text = "更换封面",
text = stringResource(R.string.change_cover),
fontSize = 12.sp,
color = Color.White
)
@@ -288,7 +306,7 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
// 标题
Text(
text = "编辑资料",
text = stringResource(R.string.edit_profile_info),
fontSize = 17.sp,
fontWeight = FontWeight.SemiBold,
color = Color.White,
@@ -318,7 +336,7 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
modifier = Modifier
.size(96.dp)
.clip(CircleShape)
.border(2.4.dp, Color(0xFFFAF9FB), CircleShape),
.border(2.4.dp, appColors.background, CircleShape),
contentDescription = "",
contentScale = ContentScale.Crop
)
@@ -338,15 +356,7 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
contentAlignment = Alignment.Center
) {
Icon(
painter = painterResource(
id = if (AppState.darkMode) {
// TODO: 添加编辑头像暗色模式图标
R.mipmap.frame_4 // 临时占位,需替换为实际图标
} else {
// TODO: 添加编辑头像亮色模式图标
R.mipmap.bi // 临时占位,需替换为实际图标
}
),
painter = painterResource(id = R.mipmap.bi),
contentDescription = "Edit Avatar",
modifier = Modifier.size(16.dp),
tint = Color.White
@@ -365,7 +375,7 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
) {
// 昵称输入框
ProfileInfoCard(
label = "昵称",
label = stringResource(R.string.nickname),
value = model.name,
placeholder = "Value",
onValueChange = { onNicknameChange(it) },
@@ -376,7 +386,7 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
// 个人简介输入框
ProfileInfoCard(
label = "个人简介",
label = stringResource(R.string.personal_intro),
value = model.bio,
placeholder = "Welcome to my fantiac word i will show you something about magic",
onValueChange = { onBioChange(it) },
@@ -390,11 +400,11 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(16.dp))
.background(Color.White)
.background(appColors.secondaryBackground)
) {
// MBTI 类型
ProfileSelectItem(
label = "MBTI 类型",
label = stringResource(R.string.mbti_type),
value = model.mbti ?: "ENFP",
iconColor = Color(0xFF7C45ED),
iconResDark = null, // TODO: 添加MBTI暗色模式图标
@@ -411,14 +421,19 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
modifier = Modifier
.fillMaxWidth()
.height(0.3.dp)
.background(Color(0x41413C43).copy(alpha = 0.2f))
.background(appColors.divider)
.padding(horizontal = 16.dp)
)
// 星座(使用当前图标)
ProfileSelectItem(
label = "星座",
value = model.zodiac ?: "白羊座",
label = stringResource(R.string.zodiac),
value = model.zodiac?.let { storedZodiac ->
// 尝试找到对应的资源ID并显示当前语言的文本
findZodiacResId(storedZodiac)?.let { resId ->
stringResource(resId)
} ?: storedZodiac // 如果找不到,显示原始存储的值
} ?: stringResource(R.string.zodiac_aries),
iconColor = Color(0xFFFFCC00),
iconResDark = R.mipmap.frame_4, // 星座暗色模式图标
iconResLight = R.mipmap.xingzuo, // 星座亮色模式图标
@@ -448,26 +463,43 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
)
)
.debouncedClickable(
enabled = validate() && !model.isUpdating,
enabled = !model.isUpdating,
debounceTime = 1000L
) {
if (validate() && !model.isUpdating) {
model.viewModelScope.launch {
model.isUpdating = true
model.updateUserProfile(context)
model.viewModelScope.launch(Dispatchers.Main) {
debouncedNavigation {
navController.navigateUp()
}
model.isUpdating = false
if (model.isUpdating) return@debouncedClickable
// 点击保存时重新验证
val nicknameErrorMsg = validateNickname()
val bioErrorMsg = validateBio()
// 如果有错误,显示对应的错误提示
when {
nicknameErrorMsg != null -> {
Toast.makeText(context, nicknameErrorMsg, Toast.LENGTH_SHORT).show()
return@debouncedClickable
}
bioErrorMsg != null -> {
Toast.makeText(context, bioErrorMsg, Toast.LENGTH_SHORT).show()
return@debouncedClickable
}
}
// 验证通过,执行保存
model.viewModelScope.launch {
model.isUpdating = true
model.updateUserProfile(context)
model.viewModelScope.launch(Dispatchers.Main) {
debouncedNavigation {
navController.navigateUp()
}
model.isUpdating = false
}
}
},
contentAlignment = Alignment.Center
) {
Text(
text = "保存",
text = stringResource(R.string.save),
fontSize = 17.sp,
fontWeight = FontWeight.Normal,
color = Color.White
@@ -483,7 +515,7 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
contentAlignment = Alignment.Center
) {
Text(
text = "加载用户资料失败,请重试",
text = stringResource(R.string.error_load_profile_failed),
color = appColors.text
)
}
@@ -505,13 +537,12 @@ fun ProfileInfoCard(
isMultiline: Boolean = false
) {
val appColors = LocalAppTheme.current
Box(
modifier = Modifier
.fillMaxWidth()
.height(if (isMultiline) 66.dp else 56.dp) // 昵称框高度56dp个人简介66dp
.clip(RoundedCornerShape(16.dp))
.background(Color.White),
.background(appColors.secondaryBackground),
contentAlignment = if (isMultiline) Alignment.TopStart else Alignment.CenterStart
) {
Row(
@@ -526,7 +557,7 @@ fun ProfileInfoCard(
text = label,
fontSize = 17.sp,
fontWeight = FontWeight.Normal,
color = Color.Black,
color = appColors.text,
modifier = Modifier.width(100.dp)
)
@@ -541,7 +572,7 @@ fun ProfileInfoCard(
text = placeholder,
fontSize = if (isMultiline) 15.sp else 17.sp,
fontWeight = FontWeight.Normal,
color = Color(0x993C3C43),
color = appColors.secondaryText,
modifier = Modifier.fillMaxWidth()
)
}
@@ -553,9 +584,9 @@ fun ProfileInfoCard(
textStyle = androidx.compose.ui.text.TextStyle(
fontSize = if (isMultiline) 15.sp else 17.sp,
fontWeight = FontWeight.Normal,
color = Color.Black
color = appColors.text
),
cursorBrush = SolidColor(Color.Black),
cursorBrush = SolidColor(appColors.text),
maxLines = if (isMultiline) Int.MAX_VALUE else 1,
singleLine = !isMultiline
)
@@ -576,6 +607,7 @@ fun ProfileSelectItem(
iconResDark: Int? = null,
iconResLight: Int? = null
) {
val appColors = LocalAppTheme.current
Row(
modifier = Modifier
.fillMaxWidth()
@@ -593,7 +625,8 @@ fun ProfileSelectItem(
Icon(
painter = painterResource(
id = if (AppState.darkMode) {
iconResDark ?: R.mipmap.frame_4 // 使用传入的暗色模式图标,或默认占位
// 暗色模式下使用和亮色模式一样的图标
iconResLight ?: iconResDark ?: R.mipmap.naoz
} else {
iconResLight ?: R.mipmap.naoz // 使用传入的亮色模式图标,或默认占位
}
@@ -607,7 +640,7 @@ fun ProfileSelectItem(
text = label,
fontSize = 17.sp,
fontWeight = FontWeight.Normal,
color = Color.Black
color = appColors.text
)
}
@@ -619,14 +652,14 @@ fun ProfileSelectItem(
text = value,
fontSize = 17.sp,
fontWeight = FontWeight.Normal,
color = Color(0x993C3C43)
color = appColors.secondaryText
)
Icon(
imageVector = Icons.Default.ArrowForward,
contentDescription = null,
modifier = Modifier.size(8.dp),
tint = Color(0x4D3C3C43)
tint = appColors.secondaryText
)
}
}

View File

@@ -10,6 +10,7 @@ import androidx.compose.animation.togetherWith
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.LocalAppTheme
@@ -36,6 +37,13 @@ fun AnimatedCounter(count: Int, modifier: Modifier = Modifier, fontSize: Int = 2
)
}
) { targetCount ->
Text(text = "$targetCount", modifier = modifier, fontSize = fontSize.sp, color = AppColors.text)
Text(
text = "$targetCount",
modifier = modifier,
fontSize = fontSize.sp,
color = AppColors.text,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}

View File

@@ -426,7 +426,6 @@ fun MomentOperateBtn(count: String, content: @Composable () -> Unit) {
fontSize = 14,
modifier = Modifier
.padding(start = 7.dp)
.width(24.dp)
)
}
}

View File

@@ -24,6 +24,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
@@ -131,17 +133,25 @@ fun FollowerListScreen(userId: Int) {
)
Spacer(modifier = Modifier.size(9.dp)) // 调整间距为9dp
androidx.compose.material.Text(
text = "还没有人关注你呢",
text = stringResource(R.string.follower_empty_title),
color = appColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.size(8.dp))
androidx.compose.material.Text(
text = "试着发信号出来,某人就会被吸引啦~",
text = stringResource(R.string.follower_empty_subtitle),
color = appColors.text,
fontSize = 14.sp,
fontWeight = FontWeight.W400
fontWeight = FontWeight.W400,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}
}

View File

@@ -25,6 +25,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.paging.compose.collectAsLazyPagingItems
@@ -122,17 +124,25 @@ fun FollowerNoticeScreen() {
)
Spacer(modifier = Modifier.height(if (AppState.darkMode) 9.dp else 24.dp))
androidx.compose.material.Text(
text = "还没有人关注你呢",
text = stringResource(R.string.follower_empty_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.size(8.dp))
androidx.compose.material.Text(
text = "试着发信号出来,某人就会被吸引啦~",
text = stringResource(R.string.follower_empty_subtitle),
color = AppColors.text,
fontSize = 14.sp,
fontWeight = FontWeight.W400
fontWeight = FontWeight.W400,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}
}

View File

@@ -24,6 +24,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
@@ -133,17 +135,25 @@ fun FollowingListScreen(userId: Int) {
)
Spacer(modifier = Modifier.size(9.dp)) // 调整间距为9dp
androidx.compose.material.Text(
text = "还没有关注任何灵魂",
text = stringResource(R.string.following_empty_title),
color = appColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.size(8.dp))
androidx.compose.material.Text(
text = "探索一下,总有一个你想靠近的光点 ✨",
text = stringResource(R.string.following_empty_subtitle),
color = appColors.secondaryText,
fontSize = 14.sp,
fontWeight = FontWeight.W400
fontWeight = FontWeight.W400,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}
}

View File

@@ -519,14 +519,31 @@ fun SideMenuContent(
var messageNotificationEnabled by remember { mutableStateOf(true) }
var darkModeEnabled by remember { mutableStateOf(AppState.darkMode) }
// 菜单背景色 #FAF9FB
val menuBackgroundColor = Color(0xFFFAF9FB)
// 同步暗色模式状态
LaunchedEffect(AppState.darkMode) {
darkModeEnabled = AppState.darkMode
}
// 菜单背景色 - 根据暗色模式适配
val menuBackgroundColor = if (darkModeEnabled) {
appColors.secondaryBackground // 暗色模式:深灰色
} else {
Color(0xFFFAF9FB) // 亮色模式:浅灰色
}
// 遮罩颜色 黑色透明度0.6
val overlayColor = Color.Black.copy(alpha = 0.6f)
// 卡片背景色 白色
val cardBackgroundColor = Color.White
// 跟随系统文字颜色 #979499
val followSystemTextColor = Color(0xFF979499)
// 卡片背景色 - 根据暗色模式适配
val cardBackgroundColor = if (darkModeEnabled) {
appColors.background // 暗色模式:深色背景
} else {
Color.White // 亮色模式:白色
}
// 文字颜色 - 根据暗色模式适配
val textColor = appColors.text
// 图标颜色 - 根据暗色模式适配
val iconColor = appColors.text
// 跟随系统文字颜色 - 根据暗色模式适配
val followSystemTextColor = appColors.secondaryText
// 开关开启颜色 #7C45ED
val switchActiveColor = Color(0xFF7C45ED)
@@ -579,14 +596,14 @@ fun SideMenuContent(
painter = painterResource(id = R.mipmap.sao),
contentDescription = null,
modifier = Modifier.size(24.dp),
colorFilter = ColorFilter.tint(Color.Black)
colorFilter = ColorFilter.tint(iconColor)
)
}
// 绝对定位的"扫一扫"文字上方71.5dp右侧66dp
Text(
text = stringResource(R.string.scan_qr),
fontSize = 14.sp,
color = Color.Black,
color = textColor,
modifier = Modifier
.align(Alignment.TopEnd)
.offset(x = (-66).dp, y = 91.5.dp)
@@ -602,7 +619,7 @@ fun SideMenuContent(
.noRippleClickable {
// TODO: 实现QR码功能
},
colorFilter = ColorFilter.tint(Color.Black)
colorFilter = ColorFilter.tint(iconColor)
)
// 菜单选项卡片组 - 第一组卡片上方距离上方108pt绝对定位
@@ -616,6 +633,8 @@ fun SideMenuContent(
// 第一组卡片:编辑资料、账号安全、收藏
MenuCard(
backgroundColor = cardBackgroundColor,
textColor = textColor,
iconColor = iconColor,
width = 270.dp,
height = 164.dp,
items = listOf(
@@ -655,6 +674,8 @@ fun SideMenuContent(
// 第二组卡片:暗色模式、消息通知
MenuCard(
backgroundColor = cardBackgroundColor,
textColor = textColor,
iconColor = iconColor,
width = 270.dp,
height = 112.dp, // 根据设计图第二组卡片高度为112dp
items = listOf(
@@ -709,6 +730,8 @@ fun SideMenuContent(
// 第三组卡片:关于派派、反馈、退出登录
MenuCard(
backgroundColor = cardBackgroundColor,
textColor = textColor,
iconColor = iconColor,
width = 270.dp,
height = 164.dp,
items = listOf(
@@ -776,6 +799,8 @@ data class MenuItem(
@Composable
fun MenuCard(
backgroundColor: Color,
textColor: Color,
iconColor: Color,
items: List<MenuItem>,
width: androidx.compose.ui.unit.Dp? = null,
height: androidx.compose.ui.unit.Dp? = null
@@ -794,14 +819,15 @@ fun MenuCard(
.then(if (height != null) Modifier.weight(1f) else Modifier),
contentAlignment = Alignment.Center
) {
MenuItemRow(item = item, compact = height != null) // 传递compact参数
MenuItemRow(item = item, compact = height != null, textColor = textColor, iconColor = iconColor) // 传递颜色参数
}
}
}
}
@Composable
fun MenuItemRow(item: MenuItem, compact: Boolean = false) {
fun MenuItemRow(item: MenuItem, compact: Boolean = false, textColor: Color, iconColor: Color) {
val appColors = LocalAppTheme.current
Row(
modifier = Modifier
.fillMaxWidth()
@@ -825,12 +851,12 @@ fun MenuItemRow(item: MenuItem, compact: Boolean = false) {
painter = painterResource(id = item.icon),
contentDescription = null,
modifier = Modifier.size(24.dp),
colorFilter = ColorFilter.tint(Color.Black)
colorFilter = ColorFilter.tint(iconColor)
)
Text(
text = item.label,
fontSize = 14.sp,
color = Color.Black
color = textColor
)
}
@@ -841,7 +867,7 @@ fun MenuItemRow(item: MenuItem, compact: Boolean = false) {
painter = painterResource(id = R.drawable.rave_now_nav_right),
contentDescription = null,
modifier = Modifier.size(24.dp),
colorFilter = ColorFilter.tint(Color(0xFF111213))
colorFilter = ColorFilter.tint(appColors.text)
)
}
}

View File

@@ -50,6 +50,8 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
@@ -981,9 +983,13 @@ fun ChatRoomCard(
Text(
text = "${chatRoom.memberCount} ${stringResource(R.string.chatting_now)}",
fontSize = 12.sp,
modifier = Modifier.alpha(0.6f),
modifier = Modifier
.alpha(0.6f)
.weight(1f),
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
fontWeight = androidx.compose.ui.text.font.FontWeight.W500,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}

View File

@@ -34,6 +34,7 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
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
@@ -108,13 +109,21 @@ fun AgentChatListScreen() {
text = stringResource(R.string.agent_chat_empty_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.agent_chat_empty_subtitle),
color = AppColors.secondaryText,
fontSize = 14.sp
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}
else {
@@ -130,13 +139,21 @@ fun AgentChatListScreen() {
text = stringResource(R.string.friend_chat_no_network_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.friend_chat_no_network_subtitle),
color = AppColors.secondaryText,
fontSize = 14.sp
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(16.dp))
ReloadButton(

View File

@@ -186,13 +186,21 @@ fun AllChatListScreen() {
text = stringResource(R.string.friend_chat_empty_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.friend_chat_empty_subtitle),
color = AppColors.secondaryText,
fontSize = 14.sp
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
} else {
Spacer(modifier = Modifier.height(39.dp))
@@ -207,13 +215,21 @@ fun AllChatListScreen() {
text = stringResource(R.string.friend_chat_no_network_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.friend_chat_no_network_subtitle),
color = AppColors.secondaryText,
fontSize = 14.sp
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(16.dp))
ReloadButton(

View File

@@ -96,13 +96,21 @@ fun FriendChatListScreen() {
text = stringResource(R.string.friend_chat_empty_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.friend_chat_empty_subtitle),
color = AppColors.secondaryText,
fontSize = 14.sp
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}else {
Spacer(modifier = Modifier.height(39.dp))
@@ -117,13 +125,21 @@ fun FriendChatListScreen() {
text = stringResource(R.string.friend_chat_no_network_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.friend_chat_no_network_subtitle),
color = AppColors.secondaryText,
fontSize = 14.sp
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(16.dp))
ReloadButton(

View File

@@ -23,6 +23,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -88,13 +89,21 @@ fun GroupChatListScreen() {
text = stringResource(R.string.group_chat_empty),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.group_chat_empty_join),
color = AppColors.secondaryText,
fontSize = 14.sp
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}else {
Spacer(modifier = Modifier.height(39.dp))
@@ -109,13 +118,21 @@ fun GroupChatListScreen() {
text = stringResource(R.string.friend_chat_no_network_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.friend_chat_no_network_subtitle),
color = AppColors.secondaryText,
fontSize = 14.sp
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(16.dp))
ReloadButton(

View File

@@ -72,8 +72,8 @@ fun MomentsList() {
val navigationBarPaddings =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp
val statusBarPaddingValues = WindowInsets.systemBars.asPaddingValues()
// 现在有6个tab推荐、短视频、新闻、探索、关注、热门
val tabCount = 6
// 根据登录状态设置标签页数量游客模式5个tab非游客模式6个tab
val tabCount = if (AppStore.isGuest) 5 else 6
var pagerState = rememberPagerState { tabCount }
var scope = rememberCoroutineScope()
Column(
@@ -174,14 +174,14 @@ fun MomentsList() {
}
)
} else {
// 热门标签 (游客模式)
// 热门标签 (游客模式) - 在游客模式下热门标签对应第3页
UnderlineTabItem(
text = stringResource(R.string.index_hot),
isSelected = pagerState.currentPage == 4,
isSelected = pagerState.currentPage == 3,
onClick = {
tabDebouncer {
scope.launch {
pagerState.animateScrollToPage(4)
pagerState.animateScrollToPage(3)
}
}
}
@@ -189,14 +189,15 @@ fun MomentsList() {
}
// 新闻标签
// 新闻标签 - 在游客模式下对应第4页非游客模式下对应第5页
val newsPageIndex = if (AppStore.isGuest) 4 else 5
UnderlineTabItem(
text = stringResource(R.string.tab_news),
isSelected = pagerState.currentPage == 5,
isSelected = pagerState.currentPage == newsPageIndex,
onClick = {
tabDebouncer {
scope.launch {
pagerState.animateScrollToPage(5)
pagerState.animateScrollToPage(newsPageIndex)
}
}
}
@@ -250,12 +251,18 @@ fun MomentsList() {
}
}
4 -> {
// 热门页面 (仅非游客用户)
HotMomentsList()
// 热门页面 (仅非游客用户) 或 新闻页面 (游客用户)
if (AppStore.isGuest) {
NewsScreen()
} else {
HotMomentsList()
}
}
5 -> {
// 新闻页面
NewsScreen()
// 新闻页面 (仅非游客用户)
if (!AppStore.isGuest) {
NewsScreen()
}
}
}
}

View File

@@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
import androidx.compose.foundation.lazy.staggeredgrid.items
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
@@ -137,8 +139,18 @@ fun DiscoverView() {
val debouncer = rememberDebouncer()
val textContent = momentItem.momentTextContent
// 对于英文和日文,每行字符数会更少,使用更保守的估算
val estimatedCharsPerLine = if (textContent.isNotEmpty()) {
// 检测是否包含非中文字符(英文、日文等)
val hasNonChinese = textContent.any {
val code = it.code
!(code >= 0x4E00 && code <= 0x9FFF) // 不在中文字符范围内
}
if (hasNonChinese) 15 else 20 // 英文/日文每行更少字符
} else {
20
}
val textLines = if (textContent.isNotEmpty()) {
val estimatedCharsPerLine = 20
val estimatedLines = (textContent.length / estimatedCharsPerLine) + 1
minOf(estimatedLines, 2) // 最多2行
} else {
@@ -146,21 +158,20 @@ fun DiscoverView() {
}
val baseHeight = 200.dp
val singleLineTextHeight = 20.dp
val doubleLineTextHeight = 40.dp
val singleLineTextHeight = 24.dp // 增加高度以适应英文/日文
val doubleLineTextHeight = 44.dp // 增加高度以适应英文/日文
val authorInfoHeight = 25.dp
val paddingHeight = 10.dp
val paddingHeight2 =3.dp
val paddingHeight2 = 3.dp
val totalHeight = baseHeight + when (textLines) {
0 -> authorInfoHeight + paddingHeight
1 -> singleLineTextHeight + authorInfoHeight + paddingHeight
else -> doubleLineTextHeight + authorInfoHeight +paddingHeight2
else -> doubleLineTextHeight + authorInfoHeight + paddingHeight2
}
Box(
modifier = Modifier
.fillMaxWidth()
.height(totalHeight)
.padding(2.dp)
.noRippleClickable {
debouncer {
@@ -173,7 +184,9 @@ fun DiscoverView() {
}
) {
Column(
modifier = Modifier.fillMaxSize().background(AppColors.secondaryBackground, RoundedCornerShape(12.dp))
modifier = Modifier
.fillMaxWidth()
.background(AppColors.secondaryBackground, RoundedCornerShape(12.dp))
) {
CustomAsyncImage(
imageUrl = momentItem.images[0].thumbnail,
@@ -193,9 +206,9 @@ fun DiscoverView() {
Column(
modifier = Modifier
.fillMaxWidth()
.height(totalHeight - baseHeight)
.padding(horizontal = 8.dp, vertical = 8.dp)
) {
// 文本内容区域,限制最大高度
if (momentItem.momentTextContent.isNotEmpty()) {
androidx.compose.material3.Text(
text = momentItem.momentTextContent,
@@ -203,13 +216,19 @@ fun DiscoverView() {
fontSize = 12.sp,
color = AppColors.text,
maxLines = 2,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
lineHeight = 16.sp // 设置行高以适应不同语言
)
}
// 使用 Spacer 确保头像昵称栏始终在底部,有足够的空间
Spacer(modifier = Modifier.weight(1f))
// 头像昵称栏,确保始终完整显示,设置最小高度避免被挤压
Row(
modifier = Modifier
.fillMaxWidth()
.heightIn(min = 25.dp) // 最小高度确保完整显示,自适应避免被挤压
.padding(top = 5.dp),
verticalAlignment = Alignment.CenterVertically
) {
@@ -225,7 +244,9 @@ fun DiscoverView() {
androidx.compose.material3.Text(
text = momentItem.nickname,
modifier = Modifier.padding(start = 4.dp),
modifier = Modifier
.padding(start = 4.dp)
.weight(1f),
fontSize = 11.sp,
color = AppColors.text.copy(alpha = 0.6f),
maxLines = 1,

View File

@@ -604,9 +604,19 @@ fun TopNavigationBar(
val appColors = LocalAppTheme.current
val numberFormat = remember { NumberFormat.getNumberInstance(Locale.getDefault()) }
// 根据背景透明度决定图标颜色透明度为1时变黑否则为白色
val iconColor = if (backgroundAlpha >= 1f) Color.Black else Color.White
val cardBorderColor = if (backgroundAlpha >= 1f) Color.Black else Color.White
// 根据背景透明度和暗色模式决定图标颜色
// 暗色模式下:图标始终为白色
// 亮色模式下根据背景透明度决定透明度为1时变黑否则为白色
val iconColor = if (AppState.darkMode) {
Color.White // 暗色模式下图标始终为白色
} else {
if (backgroundAlpha >= 1f) Color.Black else Color.White
}
val cardBorderColor = if (AppState.darkMode) {
Color.White // 暗色模式下边框应为白色
} else {
if (backgroundAlpha >= 1f) Color.Black else Color.White
}
Box(
modifier = Modifier
@@ -625,25 +635,31 @@ fun TopNavigationBar(
val baseColor = remember(backgroundAlpha) {
val smoothProgress = backgroundAlpha.coerceIn(0f, 1f)
// 初始状态:半透明深色,让白色图标清晰可见
val initialDarkAlpha = 0.12f
// 使用平滑的插值函数,让整个过渡更自然
val easedProgress = smoothProgress * smoothProgress * (3f - 2f * smoothProgress) // smoothstep
// 颜色值:从黑色(0)平滑过渡到白色(1)
val colorValue = easedProgress
// 透明度:从初始值(0.12f)逐渐减少到0
// 当smoothProgress从0到1时alpha从initialDarkAlpha减少到0
val alpha = initialDarkAlpha * (1f - easedProgress)
Color(
red = colorValue,
green = colorValue,
blue = colorValue,
alpha = alpha.coerceIn(0f, initialDarkAlpha)
)
if (AppState.darkMode) {
// 暗色模式下从黑色透明度0逐渐变为黑色透明度1
val alpha = smoothProgress.coerceIn(0f, 1f)
Color.Black.copy(alpha = alpha)
} else {
// 亮色模式:初始状态:半透明深色,让白色图标清晰可见
val initialDarkAlpha = 0.12f
// 使用平滑的插值函数,让整个过渡更自然
val easedProgress = smoothProgress * smoothProgress * (3f - 2f * smoothProgress) // smoothstep
// 颜色值:从黑色(0)平滑过渡到白色(1)
val colorValue = easedProgress
// 透明度:从初始值(0.12f)逐渐减少到0
// 当smoothProgress从0到1时alpha从initialDarkAlpha减少到0
val alpha = initialDarkAlpha * (1f - easedProgress)
Color(
red = colorValue,
green = colorValue,
blue = colorValue,
alpha = alpha.coerceIn(0f, initialDarkAlpha)
)
}
}
Box(
@@ -703,7 +719,7 @@ fun TopNavigationBar(
text = numberFormat.format(interactionCount),
fontSize = 14.sp,
fontWeight = FontWeight.W500,
color = Color.Black, // 文字始终为黑色
color = if (AppState.darkMode) Color.White else Color.Black, // 暗色模式下为白色,亮色模式下为黑色
textAlign = TextAlign.Center
)
}
@@ -744,6 +760,9 @@ fun TopNavigationBar(
// 如果不是主页面,显示返回按钮和用户信息
if (!isMain) {
val statusBarPadding = WindowInsets.systemBars.asPaddingValues()
// 判断是否有背景图
val hasBanner = profile?.banner != null
Row(
modifier = Modifier
.align(Alignment.TopStart)
@@ -751,6 +770,8 @@ fun TopNavigationBar(
.padding(top = statusBarPadding.calculateTopPadding()),
verticalAlignment = Alignment.CenterVertically
) {
// 返回按钮:深色模式下为白色,亮色模式下为黑色
val backButtonColor = if (AppState.darkMode) Color.White else Color.Black
Image(
painter = painterResource(id = R.drawable.rider_pro_back_icon),
contentDescription = "Back",
@@ -759,25 +780,19 @@ fun TopNavigationBar(
navController.navigateUp()
}
.size(24.dp),
colorFilter = ColorFilter.tint(Color.White)
)
Spacer(modifier = Modifier.width(8.dp))
CustomAsyncImage(
LocalContext.current,
profile?.avatar,
modifier = Modifier
.size(32.dp)
.clip(CircleShape),
contentDescription = "",
contentScale = ContentScale.Crop
)
Spacer(modifier = Modifier.width(16.dp))
Text(
text = profile?.nickName ?: "",
fontSize = 16.sp,
fontWeight = FontWeight.W600,
color = Color.White
colorFilter = ColorFilter.tint(backButtonColor) // 深色模式下为白色,亮色模式下为黑色
)
// 未设置背景的用户(自己的主页且没有背景图)显示昵称
if (isSelf && !hasBanner && profile != null) {
Spacer(modifier = Modifier.width(8.dp))
Text(
text = profile.nickName ?: "",
fontSize = 16.sp,
fontWeight = FontWeight.W600,
color = backButtonColor // 深色模式下为白色,亮色模式下为黑色
)
}
}
}
}

View File

@@ -42,6 +42,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
@@ -199,19 +201,27 @@ fun GalleryGrid(
Spacer(modifier = Modifier.height(if(AppState.darkMode) 9.dp else 24.dp))
Text(
text = "你的故事还没开始",
text = stringResource(R.string.your_story_not_started),
fontSize = 16.sp,
color = AppColors.text,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "发布一条动态,和世界打个招呼吧",
text = stringResource(R.string.publish_moment_greeting),
fontSize = 14.sp,
color = AppColors.secondaryText,
fontWeight = FontWeight.W400
fontWeight = FontWeight.W400,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}
} else {

View File

@@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Divider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -27,27 +26,25 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.R
@Composable
fun GroupChatEmptyContent() {
var selectedSegment by remember { mutableStateOf(0) } // 0: 全部, 1: 公开, 2: 私有
val AppColors = LocalAppTheme.current
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
// 分割线(紧贴上方栏)
Divider(
color = Color(0xFFF0F0F0), // 更浅的灰色
thickness = 1.dp,
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
// 分段控制器
@@ -71,10 +68,14 @@ fun GroupChatEmptyContent() {
// 空状态文本
Text(
text = "空空如也~",
text = stringResource(R.string.empty_nothing),
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF000000)
color = AppColors.text,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
}
@@ -86,6 +87,7 @@ private fun SegmentedControl(
onSegmentSelected: (Int) -> Unit,
modifier: Modifier = Modifier
) {
val AppColors = LocalAppTheme.current
Row(
modifier = modifier
.height(32.dp),
@@ -94,30 +96,33 @@ private fun SegmentedControl(
) {
// 全部
SegmentButton(
text = "全部",
text = stringResource(R.string.chat_all),
isSelected = selectedIndex == 0,
onClick = { onSegmentSelected(0) },
width = 54.dp
width = 54.dp,
appColors = AppColors
)
Spacer(modifier = Modifier.width(8.dp))
// 公开
SegmentButton(
text = "公开",
text = stringResource(R.string.public_label),
isSelected = selectedIndex == 1,
onClick = { onSegmentSelected(1) },
width = 59.dp
width = 59.dp,
appColors = AppColors
)
Spacer(modifier = Modifier.width(8.dp))
// 私有
SegmentButton(
text = "私有",
text = stringResource(R.string.private_label),
isSelected = selectedIndex == 2,
onClick = { onSegmentSelected(2) },
width = 54.dp
width = 54.dp,
appColors = AppColors
)
}
}
@@ -127,7 +132,8 @@ private fun SegmentButton(
text: String,
isSelected: Boolean,
onClick: () -> Unit,
width: androidx.compose.ui.unit.Dp
width: androidx.compose.ui.unit.Dp,
appColors: com.aiosman.ravenow.AppThemeData
) {
Box(
modifier = Modifier
@@ -135,7 +141,7 @@ private fun SegmentButton(
.height(32.dp)
.background(
color = if (isSelected) {
Color(0xFF110C13) // RGB(17, 12, 19)
appColors.checkedBackground // 使用选中背景色(暗色模式下是白色,亮色模式下是黑色)
} else {
Color(0x147C7480) // RGB(124, 116, 128, alpha 0.08)
},
@@ -148,7 +154,11 @@ private fun SegmentButton(
text = text,
fontSize = 13.sp,
fontWeight = FontWeight.Normal,
color = if (isSelected) Color(0xFFFFFFFF) else Color(0xFF000000)
color = if (isSelected) {
appColors.checkedText // 选中时使用选中文本颜色(暗色模式下是黑色,亮色模式下是白色)
} else {
appColors.text // 未选中时使用文本颜色
}
)
}
}

View File

@@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Divider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -35,6 +34,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -209,13 +209,6 @@ fun AgentEmptyContentWithSegments() {
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
// 分割线(紧贴上方栏)
Divider(
color = Color(0xFFF0F0F0), // 更浅的灰色
thickness = 1.dp,
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
// 分段控制器
@@ -247,19 +240,27 @@ fun AgentEmptyContentWithSegments() {
Spacer(modifier = Modifier.height(if(AppState.darkMode) 9.dp else 24.dp))
Text(
text = "专属AI等你召唤",
text = stringResource(R.string.exclusive_ai_waiting),
fontSize = 16.sp,
color = AppColors.text,
fontWeight = FontWeight.W600
fontWeight = FontWeight.W600,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "AI将成为你的伙伴而不是工具",
text = stringResource(R.string.ai_companion_not_tool),
fontSize = 14.sp,
color = AppColors.secondaryText,
fontWeight = FontWeight.W400
fontWeight = FontWeight.W400,
textAlign = TextAlign.Center,
modifier = Modifier.padding(horizontal = 24.dp),
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
} else {
Image(
@@ -303,6 +304,7 @@ private fun AgentSegmentedControl(
onSegmentSelected: (Int) -> Unit,
modifier: Modifier = Modifier
) {
val AppColors = LocalAppTheme.current
Row(
modifier = modifier
.height(32.dp),
@@ -311,30 +313,33 @@ private fun AgentSegmentedControl(
) {
// 全部
AgentSegmentButton(
text = "全部",
text = stringResource(R.string.chat_all),
isSelected = selectedIndex == 0,
onClick = { onSegmentSelected(0) },
width = 54.dp
width = 54.dp,
appColors = AppColors
)
Spacer(modifier = Modifier.width(8.dp))
// 公开
AgentSegmentButton(
text = "公开",
text = stringResource(R.string.public_label),
isSelected = selectedIndex == 1,
onClick = { onSegmentSelected(1) },
width = 59.dp
width = 59.dp,
appColors = AppColors
)
Spacer(modifier = Modifier.width(8.dp))
// 私有
AgentSegmentButton(
text = "私有",
text = stringResource(R.string.private_label),
isSelected = selectedIndex == 2,
onClick = { onSegmentSelected(2) },
width = 54.dp
width = 54.dp,
appColors = AppColors
)
}
}
@@ -344,7 +349,8 @@ private fun AgentSegmentButton(
text: String,
isSelected: Boolean,
onClick: () -> Unit,
width: androidx.compose.ui.unit.Dp
width: androidx.compose.ui.unit.Dp,
appColors: com.aiosman.ravenow.AppThemeData
) {
Box(
modifier = Modifier
@@ -352,7 +358,7 @@ private fun AgentSegmentButton(
.height(32.dp)
.background(
color = if (isSelected) {
Color(0xFF110C13) // RGB(17, 12, 19)
appColors.checkedBackground // 使用选中背景色(暗色模式下是白色,亮色模式下是黑色)
} else {
Color(0x147C7480) // RGB(124, 116, 128, alpha 0.08)
},
@@ -365,7 +371,11 @@ private fun AgentSegmentButton(
text = text,
fontSize = 13.sp,
fontWeight = FontWeight.Normal,
color = if (isSelected) Color(0xFFFFFFFF) else Color(0xFF000000)
color = if (isSelected) {
appColors.checkedText // 选中时使用选中文本颜色(暗色模式下是黑色,亮色模式下是白色)
} else {
appColors.text // 未选中时使用文本颜色
}
)
}
}

View File

@@ -10,21 +10,14 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
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.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
@@ -52,7 +45,7 @@ fun UserContentPageIndicator(
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
// 图片/相册 Tab
// 动态 Tab
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
@@ -64,15 +57,24 @@ fun UserContentPageIndicator(
}
.padding(vertical = 12.dp)
) {
Icon(
painter = painterResource(id = R.drawable.rider_pro_images),
contentDescription = "Gallery",
tint = if (pagerState.currentPage == 0) AppColors.text else AppColors.text.copy(alpha = 0.6f),
modifier = Modifier.size(24.dp)
Text(
text = stringResource(R.string.index_dynamic),
fontSize = 16.sp,
fontWeight = if (pagerState.currentPage == 0) FontWeight.SemiBold else FontWeight.Medium,
color = if (pagerState.currentPage == 0) AppColors.text else AppColors.secondaryText
)
Spacer(modifier = Modifier.height(if (pagerState.currentPage == 0) 6.dp else 4.dp))
if (pagerState.currentPage == 0) {
Box(
modifier = Modifier
.width(20.dp)
.height(2.dp)
.background(AppColors.text)
)
}
}
// Agent Tab (只在非智能体用户时显示)
// 智能体 Tab (只在非智能体用户时显示)
if (showAgentTab) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
@@ -85,40 +87,54 @@ fun UserContentPageIndicator(
}
.padding(vertical = 12.dp)
) {
Icon(
painter = painterResource(id = R.drawable.rider_pro_nav_ai),
contentDescription = "Agents",
tint = if (pagerState.currentPage == 1) AppColors.text else AppColors.text.copy(alpha = 0.6f),
modifier = Modifier.size(24.dp)
Text(
text = stringResource(R.string.chat_ai),
fontSize = 16.sp,
fontWeight = if (pagerState.currentPage == 1) FontWeight.SemiBold else FontWeight.Medium,
color = if (pagerState.currentPage == 1) AppColors.text else AppColors.secondaryText
)
Spacer(modifier = Modifier.height(if (pagerState.currentPage == 1) 6.dp else 4.dp))
if (pagerState.currentPage == 1) {
Box(
modifier = Modifier
.width(20.dp)
.height(2.dp)
.background(AppColors.text)
)
}
}
}
// 群聊 Tab (只在非智能体用户时显示)
if (showAgentTab) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.weight(1f)
.noRippleClickable {
scope.launch {
pagerState.scrollToPage(2)
}
}
.padding(vertical = 12.dp)
) {
Text(
text = stringResource(R.string.chat_group),
fontSize = 16.sp,
fontWeight = if (pagerState.currentPage == 2) FontWeight.SemiBold else FontWeight.Medium,
color = if (pagerState.currentPage == 2) AppColors.text else AppColors.secondaryText
)
Spacer(modifier = Modifier.height(if (pagerState.currentPage == 2) 6.dp else 4.dp))
if (pagerState.currentPage == 2) {
Box(
modifier = Modifier
.width(20.dp)
.height(2.dp)
.background(AppColors.text)
)
}
}
}
}
// 下划线指示器
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
) {
Box(
modifier = Modifier
.weight(1f)
.height(2.dp)
.background(
if (pagerState.currentPage == 0) AppColors.text else Color.Transparent
)
)
if (showAgentTab) {
Box(
modifier = Modifier
.weight(1f)
.height(2.dp)
.background(
if (pagerState.currentPage == 1) AppColors.text else Color.Transparent
)
)
}
}
}
}
}

View File

@@ -27,6 +27,7 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
@@ -117,15 +118,15 @@ fun UserItem(
text = postCount.toString(),
fontWeight = FontWeight.Medium,
fontSize = 15.sp,
color = Color(0xFF000000),
color = AppColors.text,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(2.dp))
Text(
text = "帖子",
text = stringResource(R.string.posts),
fontWeight = FontWeight.Normal,
fontSize = 11.sp,
color = Color(0xFF000000),
color = AppColors.text,
textAlign = TextAlign.Center
)
}
@@ -152,15 +153,15 @@ fun UserItem(
text = formattedFollowerCount,
fontWeight = FontWeight.Medium,
fontSize = 15.sp,
color = Color(0xFF000000),
color = AppColors.text,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(2.dp))
Text(
text = "粉丝",
text = stringResource(R.string.followers_upper),
fontWeight = FontWeight.Normal,
fontSize = 11.sp,
color = Color(0xFF000000),
color = AppColors.text,
textAlign = TextAlign.Center
)
}
@@ -188,15 +189,15 @@ fun UserItem(
text = accountProfileEntity.followingCount.toString(),
fontWeight = FontWeight.Medium,
fontSize = 15.sp,
color = Color(0xFF000000),
color = AppColors.text,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(2.dp))
Text(
text = "关注",
text = stringResource(R.string.following_upper),
fontWeight = FontWeight.Normal,
fontSize = 11.sp,
color = Color(0xFF000000),
color = AppColors.text,
textAlign = TextAlign.Center
)
}
@@ -216,7 +217,7 @@ fun UserItem(
fontWeight = FontWeight.Bold,
fontSize = 22.sp,
letterSpacing = (-0.3).sp,
color = Color(0xFF000000)
color = AppColors.text
)
Spacer(modifier = Modifier.height(4.dp))
@@ -226,7 +227,7 @@ fun UserItem(
Text(
text = accountProfileEntity.bio,
fontSize = 13.sp,
color = Color(0x993C3C43), // 60/255, 60/255, 67/255, alpha 0.6
color = AppColors.secondaryText,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
@@ -234,7 +235,7 @@ fun UserItem(
Text(
text = "Welcome to my fantiac word i will show you something about magic",
fontSize = 13.sp,
color = Color(0x993C3C43),
color = AppColors.secondaryText,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
@@ -257,7 +258,7 @@ fun UserItem(
ProfileTag(
text = mbti,
backgroundColor = Color(0x33FF8D28), // 255/255, 141/255, 40/255, alpha 0.2
textColor = Color(0xFF000000)
textColor = AppColors.text
)
}
@@ -266,19 +267,19 @@ fun UserItem(
ProfileTag(
text = zodiac,
backgroundColor = Color(0x33FFCC00), // 255/255, 204/255, 0/255, alpha 0.2
textColor = Color(0xFF000000)
textColor = AppColors.text
)
}
// 编辑标签(仅自己可见)
if (isSelf) {
ProfileTag(
text = "编辑",
text = stringResource(R.string.edit_profile),
backgroundColor = Color(0x14947A80), // 124/255, 116/255, 128/255, alpha 0.08
textColor = Color(0xFF9284BD), // 146/255, 132/255, 189/255
textColor = AppColors.text,
leadingIcon = {
EditIcon(
color = Color(0xFF9284BD),
color = AppColors.text,
modifier = Modifier.size(16.dp)
)
},
@@ -333,7 +334,7 @@ private fun EditIcon(
) {
Image(
painter = painterResource(id = R.mipmap.bi),
contentDescription = "编辑",
contentDescription = stringResource(R.string.edit_profile),
modifier = modifier,
colorFilter = ColorFilter.tint(color)
)

View File

@@ -204,7 +204,7 @@ fun EmailSignupScreen() {
email = it
},
label = stringResource(R.string.login_email_label),
hint = "输入电子邮件",
hint = stringResource(R.string.text_hint_email),
error = emailError,
leadingIcon = {
Image(

View File

@@ -26,6 +26,8 @@ import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -68,6 +70,7 @@ import androidx.compose.ui.res.stringResource
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.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -160,8 +163,9 @@ fun NewPostScreen() {
Row(
modifier = Modifier
.padding(start = 16.dp)
.width(100.dp)
.height(40.dp)
.widthIn(min = 100.dp, max = 200.dp)
.wrapContentWidth()
.clip(RoundedCornerShape(20.dp))
.background(
brush = Brush.linearGradient(
@@ -189,6 +193,8 @@ fun NewPostScreen() {
modifier = Modifier
.padding(start = 2.dp),
color = Color.White,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}

View File

@@ -12,6 +12,7 @@
<string name="users">ユーザー</string>
<string name="like_upper">いいね</string>
<string name="followers_upper">フォロワー</string>
<string name="posts">投稿</string>
<string name="favourites_upper">お気に入り</string>
<string name="favourites_null">あれ、何もない。..</string>
<string name="notifications_upper">通知</string>
@@ -51,6 +52,10 @@
<string name="error_not_accept_term">最高のサービスを提供するために、登録前に利用規約を読み、同意してください。</string>
<string name="empty_my_post_title">まだ投稿がありません</string>
<string name="empty_my_post_content">今すぐモーメントを投稿</string>
<string name="story_not_started">ストーリーはまだ始まっていません</string>
<string name="your_story_not_started">あなたのストーリーはまだ始まっていません</string>
<string name="publish_moment_greeting">モーメントを投稿して、世界に挨拶しましょう</string>
<string name="no_image">画像がありません</string>
<string name="edit_profile">プロフィールを編集</string>
<string name="share">シェア</string>
<string name="logout">ログアウト</string>
@@ -142,17 +147,21 @@
<string name="agent_desc_hint">例:経験豊富な営業担当者で、ユーモアと生きた事例を使って、複雑な製品を顧客が理解しやすい形に変えるのが得意</string>
<string name="agent_create">エージェントを作成</string>
<string name="moment_content_hint">投稿のインスピレーションが必要ですかAIがお手伝いします</string>
<string name="moment_ai_co">AIの文案最適化</string>
<string name="moment_ai_co">文案最適化</string>
<string name="moment_ai_delete">削除</string>
<string name="moment_ai_apply">適用</string>
<string name="chat_ai">AI</string>
<string name="chat_group">グループ</string>
<string name="chat_friend">友達</string>
<string name="chat_all">すべて</string>
<string name="public_label">公開</string>
<string name="private_label">プライベート</string>
<string name="chatting_now">人はおしゃべりをしている…</string>
<string name="agent_chat_list_title">AIエージェントチャット</string>
<string name="agent_chat_empty_title">AIエージェントチャットがありません</string>
<string name="agent_chat_empty_subtitle">AIエージェントと対話してみましょう</string>
<string name="exclusive_ai_waiting">専属AIがあなたを待っています</string>
<string name="ai_companion_not_tool">AIはあなたのパートナーとなり、ツールではありません</string>
<string name="agent_chat_me_prefix">私: </string>
<string name="agent_chat_image">[画像]</string>
<string name="agent_chat_voice">[音声]</string>
@@ -164,10 +173,15 @@
<string name="agent_chat_user_info_failed">ユーザー情報の取得に失敗しました: %s</string>
<string name="group_chat_empty">グループチャットがありません</string>
<string name="group_chat_empty_join">まだどのグループチャットにも参加していません</string>
<string name="empty_nothing">何もありません~</string>
<string name="group_chat_empty_title">グループチャットメッセージのない宇宙は静かすぎます</string>
<string name="group_chat_empty_subtitle">ホームで興味のあるテーマルームを探してみましょう</string>
<string name="friend_chat_empty_title">まだ友達とチャットしていません~</string>
<string name="friend_chat_empty_subtitle">友達のアバターをクリックして、すぐにチャットを始めましょう。</string>
<string name="following_empty_title">まだ誰もフォローしていません</string>
<string name="following_empty_subtitle">探索してみてください。近づきたい光が見つかります ✨</string>
<string name="follower_empty_title">まだ誰もあなたをフォローしていません</string>
<string name="follower_empty_subtitle">信号を送ってみてください。誰かが引き寄せられるでしょう~</string>
<string name="friend_chat_me_prefix">私: </string>
<string name="friend_chat_load_failed">読み込みに失敗しました</string>
<string name="create_group_chat">グループチャットを作成</string>

View File

@@ -12,6 +12,7 @@
<string name="users">用户</string>
<string name="like_upper"></string>
<string name="followers_upper">粉丝</string>
<string name="posts">帖子</string>
<string name="favourites_upper">收藏</string>
<string name="notifications_upper">消息</string>
<string name="following_upper">关注11</string>
@@ -50,6 +51,10 @@
<string name="error_not_accept_term">"为了提供更好的服务,请您在注册前仔细阅读并同意《用户协议》。 "</string>
<string name="empty_my_post_title">还没有发布任何动态</string>
<string name="empty_my_post_content">发布一个动态吧</string>
<string name="story_not_started">故事还没开始</string>
<string name="your_story_not_started">你的故事还没开始</string>
<string name="publish_moment_greeting">发布一条动态,和世界打个招呼吧</string>
<string name="no_image">暂无图片</string>
<string name="edit_profile">编辑</string>
<string name="share">分享</string>
<string name="logout">登出</string>
@@ -151,11 +156,15 @@
<string name="chat_group">群聊</string>
<string name="chat_friend">朋友</string>
<string name="chat_all">全部</string>
<string name="public_label">公开</string>
<string name="private_label">私有</string>
<string name="favourites_null">咦,什么都没有...</string>
<string name="agent_chat_list_title">智能体聊天</string>
<string name="agent_chat_empty_title">AI 在等你的开场白</string>
<string name="agent_chat_empty_subtitle">去首页探索一下,主动发起对话!</string>
<string name="exclusive_ai_waiting">专属AI等你召唤</string>
<string name="ai_companion_not_tool">AI将成为你的伙伴而不是工具</string>
<string name="agent_chat_me_prefix">我: </string>
<string name="agent_chat_image">[图片]</string>
<string name="agent_chat_voice">[语音]</string>
@@ -167,10 +176,15 @@
<string name="agent_chat_user_info_failed">获取用户信息失败: %s</string>
<string name="group_chat_empty">没有群聊,宇宙好安静</string>
<string name="group_chat_empty_title">没有群聊消息的宇宙太安静了</string>
<string name="empty_nothing">空空如也~</string>
<string name="group_chat_empty_subtitle">在首页探索感兴趣的主题房间</string>
<string name="group_chat_empty_join">去首页探索感兴趣的高能对话</string>
<string name="friend_chat_empty_title">和朋友,还没有对话哦~</string>
<string name="friend_chat_empty_subtitle">点击好友头像,即刻发起聊天</string>
<string name="following_empty_title">还没有关注任何灵魂</string>
<string name="following_empty_subtitle">探索一下,总有一个你想靠近的光点 ✨</string>
<string name="follower_empty_title">还没有人关注你呢</string>
<string name="follower_empty_subtitle">试着发信号出来,某人就会被吸引啦~</string>
<string name="friend_chat_me_prefix">我: </string>
<string name="friend_chat_load_failed">加载失败</string>
<string name="create_group_chat">创建群聊</string>
@@ -286,6 +300,32 @@
<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="change_cover">更换封面</string>
<string name="personal_intro">个人简介</string>
<string name="error_nickname_empty">昵称不能为空</string>
<string name="error_nickname_too_short">昵称长度不能小于3</string>
<string name="error_nickname_too_long">昵称长度不能大于20</string>
<string name="error_bio_too_long">个人简介长度不能大于100</string>
<string name="error_load_profile_failed">加载用户资料失败,请重试</string>
<string name="save">保存</string>
<string name="choose_mbti">选择 MBTI</string>
<string name="choose_zodiac">选择星座</string>
<string name="zodiac_aries">白羊座</string>
<string name="zodiac_taurus">金牛座</string>
<string name="zodiac_gemini">双子座</string>
<string name="zodiac_cancer">巨蟹座</string>
<string name="zodiac_leo">狮子座</string>
<string name="zodiac_virgo">处女座</string>
<string name="zodiac_libra">天秤座</string>
<string name="zodiac_scorpio">天蝎座</string>
<string name="zodiac_sagittarius">射手座</string>
<string name="zodiac_capricorn">摩羯座</string>
<string name="zodiac_aquarius">水瓶座</string>
<string name="zodiac_pisces">双鱼座</string>
<!-- 群聊成员 -->
<string name="group_members_title">群聊成员</string>

View File

@@ -11,6 +11,7 @@
<string name="users">Users</string>
<string name="like_upper">LIKE</string>
<string name="followers_upper">FOLLOWERS</string>
<string name="posts">Posts</string>
<string name="favourites_upper">FAVOURITES</string>
<string name="favourites_null">Well,nothing </string>
<string name="notifications_upper">NOTIFICATIONS</string>
@@ -50,6 +51,10 @@
<string name="error_not_accept_term">To provide you with the best service, please read and agree to our User Agreement before registering.</string>
<string name="empty_my_post_title">You haven\'t left any tracks yet</string>
<string name="empty_my_post_content">Post a moment now</string>
<string name="story_not_started">Your story hasn\'t started yet</string>
<string name="your_story_not_started">Your story hasn\'t started yet</string>
<string name="publish_moment_greeting">Post a moment and say hello to the world</string>
<string name="no_image">No image</string>
<string name="edit_profile">Edit profile</string>
<string name="share">share</string>
<string name="logout">Logout</string>
@@ -141,7 +146,7 @@
<string name="agent_desc_hint">Example: An experienced salesperson who is good at transforming complex products into topics that customers can easily understand and be interested in through humorous language and vivid cases</string>
<string name="agent_create">Create Agent</string>
<string name="moment_content_hint">Need some inspiration for your post? Let AI assist you!</string>
<string name="moment_ai_co">AI copywriting optimization</string>
<string name="moment_ai_co">copywriting optimization</string>
<string name="moment_ai_delete">Delete</string>
<string name="moment_ai_apply">Apply</string>
<string name="chat_ai">Ai</string>
@@ -149,9 +154,13 @@
<string name="chat_friend">Friends</string>
<string name="chatting_now">people chatting now…</string>
<string name="chat_all">All</string>
<string name="public_label">Public</string>
<string name="private_label">Private</string>
<string name="agent_chat_list_title">Agent Chat</string>
<string name="agent_chat_empty_title">No Agent Chat</string>
<string name="agent_chat_empty_subtitle">Start chatting with agents</string>
<string name="exclusive_ai_waiting">Exclusive AI waiting for you</string>
<string name="ai_companion_not_tool">AI will be your companion, not a tool</string>
<string name="agent_chat_me_prefix">Me: </string>
<string name="agent_chat_image">[Image]</string>
<string name="agent_chat_voice">[Voice]</string>
@@ -163,10 +172,15 @@
<string name="agent_chat_user_info_failed">Failed to get user info: %s</string>
<string name="group_chat_empty">No group chats</string>
<string name="group_chat_empty_join">You have not joined any group chats yet</string>
<string name="empty_nothing">Nothing here~</string>
<string name="group_chat_empty_title">The universe is too quiet without group chat messages</string>
<string name="group_chat_empty_subtitle">Explore interesting theme rooms on the homepage</string>
<string name="friend_chat_empty_title">Have not chatted with friends yet~</string>
<string name="friend_chat_empty_subtitle">Click on the avatar of friend to start chatting instantly.</string>
<string name="following_empty_title">Not following anyone yet</string>
<string name="following_empty_subtitle">Explore and you\'ll find a light you want to get close to ✨</string>
<string name="follower_empty_title">No one is following you yet</string>
<string name="follower_empty_subtitle">Try sending out a signal, someone will be attracted to you~</string>
<string name="friend_chat_me_prefix">Me: </string>
<string name="friend_chat_load_failed">Failed to load</string>
<string name="create_group_chat">Create Group Chat</string>
@@ -294,9 +308,28 @@
<!-- Edit Profile Extras -->
<string name="mbti_type">MBTI</string>
<string name="zodiac">Zodiac</string>
<string name="change_cover">Change Cover</string>
<string name="personal_intro">Personal Introduction</string>
<string name="error_nickname_empty">Nickname cannot be empty</string>
<string name="error_nickname_too_short">Nickname length cannot be less than 3</string>
<string name="error_nickname_too_long">Nickname length cannot be greater than 20</string>
<string name="error_bio_too_long">Bio length cannot be greater than 100</string>
<string name="error_load_profile_failed">Failed to load user profile, please try again</string>
<string name="save">Save</string>
<string name="choose_mbti">Choose MBTI</string>
<string name="choose_zodiac">Choose Zodiac</string>
<string name="zodiac_aries">Aries</string>
<string name="zodiac_taurus">Taurus</string>
<string name="zodiac_gemini">Gemini</string>
<string name="zodiac_cancer">Cancer</string>
<string name="zodiac_leo">Leo</string>
<string name="zodiac_virgo">Virgo</string>
<string name="zodiac_libra">Libra</string>
<string name="zodiac_scorpio">Scorpio</string>
<string name="zodiac_sagittarius">Sagittarius</string>
<string name="zodiac_capricorn">Capricorn</string>
<string name="zodiac_aquarius">Aquarius</string>
<string name="zodiac_pisces">Pisces</string>
<!-- Side Menu -->
<string name="scan_qr">Scan QR</string>