diff --git a/app/src/main/java/com/aiosman/ravenow/ui/account/AccountEditViewModel.kt b/app/src/main/java/com/aiosman/ravenow/ui/account/AccountEditViewModel.kt index 6a552d8..18431f7 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/account/AccountEditViewModel.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/account/AccountEditViewModel.kt @@ -21,6 +21,8 @@ object AccountEditViewModel : ViewModel() { var name by mutableStateOf("") var bio by mutableStateOf("") var imageUrl by mutableStateOf(null) + var bannerImageUrl by mutableStateOf(null) + var bannerFile by mutableStateOf(null) val accountService: AccountService = AccountServiceImpl() var profile by mutableStateOf(null) var croppedBitmap by mutableStateOf(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 diff --git a/app/src/main/java/com/aiosman/ravenow/ui/account/MbtiSelectScreen.kt b/app/src/main/java/com/aiosman/ravenow/ui/account/MbtiSelectScreen.kt index 7748ade..cf49830 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/account/MbtiSelectScreen.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/account/MbtiSelectScreen.kt @@ -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() } ) diff --git a/app/src/main/java/com/aiosman/ravenow/ui/account/ZodiacSelectScreen.kt b/app/src/main/java/com/aiosman/ravenow/ui/account/ZodiacSelectScreen.kt index 464fcfd..3a1a494 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/account/ZodiacSelectScreen.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/account/ZodiacSelectScreen.kt @@ -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 ) { diff --git a/app/src/main/java/com/aiosman/ravenow/ui/account/edit2.kt b/app/src/main/java/com/aiosman/ravenow/ui/account/edit2.kt index c6d2179..69fc020 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/account/edit2.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/account/edit2.kt @@ -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 ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/composables/AnimatedCounter.kt b/app/src/main/java/com/aiosman/ravenow/ui/composables/AnimatedCounter.kt index 8f32742..9cdf71f 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/composables/AnimatedCounter.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/composables/AnimatedCounter.kt @@ -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 + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/ravenow/ui/composables/Moment.kt b/app/src/main/java/com/aiosman/ravenow/ui/composables/Moment.kt index e80046b..a62af99 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/composables/Moment.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/composables/Moment.kt @@ -426,7 +426,6 @@ fun MomentOperateBtn(count: String, content: @Composable () -> Unit) { fontSize = 14, modifier = Modifier .padding(start = 7.dp) - .width(24.dp) ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowerList.kt b/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowerList.kt index b240c99..d6bd19f 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowerList.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowerList.kt @@ -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 ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowerNotice.kt b/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowerNotice.kt index bdfbf41..554433b 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowerNotice.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowerNotice.kt @@ -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 ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowingList.kt b/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowingList.kt index c097e13..79c6b9f 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowingList.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/follower/FollowingList.kt @@ -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 ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/Index.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/Index.kt index 6f3b64a..ff7ce38 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/Index.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/Index.kt @@ -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, 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) ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/ai/Agent.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/ai/Agent.kt index 90f9c62..9527d0d 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/ai/Agent.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/ai/Agent.kt @@ -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 ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/AgentChatListScreen.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/AgentChatListScreen.kt index f9c06f5..79c53ff 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/AgentChatListScreen.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/AgentChatListScreen.kt @@ -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( diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/AllChatListScreen.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/AllChatListScreen.kt index 9322516..edb66e9 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/AllChatListScreen.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/AllChatListScreen.kt @@ -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( diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/FriendChatListScreen.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/FriendChatListScreen.kt index 27ff6e1..0c89b6d 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/FriendChatListScreen.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/FriendChatListScreen.kt @@ -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( diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/GroupChatListScreen.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/GroupChatListScreen.kt index ec2b1d5..63c9b2a 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/GroupChatListScreen.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/message/tab/GroupChatListScreen.kt @@ -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( diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/moment/Moment.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/moment/Moment.kt index 0e44896..8c708ed 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/moment/Moment.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/moment/Moment.kt @@ -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() + } } } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/moment/tabs/hot/Moment.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/moment/tabs/hot/Moment.kt index db0f8e1..a7cdad2 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/moment/tabs/hot/Moment.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/moment/tabs/hot/Moment.kt @@ -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, diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/ProfileV3.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/ProfileV3.kt index 31a4d70..f4e093e 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/ProfileV3.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/ProfileV3.kt @@ -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 // 深色模式下为白色,亮色模式下为黑色 + ) + } } } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GalleryItem.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GalleryItem.kt index fc459ed..a979a28 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GalleryItem.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GalleryItem.kt @@ -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 { diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GroupChatEmptyContent.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GroupChatEmptyContent.kt index 2c5fa48..5e49597 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GroupChatEmptyContent.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GroupChatEmptyContent.kt @@ -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 // 未选中时使用文本颜色 + } ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserAgentsList.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserAgentsList.kt index d91db42..0129493 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserAgentsList.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserAgentsList.kt @@ -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 // 未选中时使用文本颜色 + } ) } } diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserContentPageIndicator.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserContentPageIndicator.kt index 8e448a5..2e0c241 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserContentPageIndicator.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserContentPageIndicator.kt @@ -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 - ) - ) - } - } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserItem.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserItem.kt index 75a3583..fee8e8f 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserItem.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/UserItem.kt @@ -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) ) diff --git a/app/src/main/java/com/aiosman/ravenow/ui/login/emailsignup.kt b/app/src/main/java/com/aiosman/ravenow/ui/login/emailsignup.kt index cce0820..cf23088 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/login/emailsignup.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/login/emailsignup.kt @@ -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( diff --git a/app/src/main/java/com/aiosman/ravenow/ui/post/NewPost.kt b/app/src/main/java/com/aiosman/ravenow/ui/post/NewPost.kt index ff1cdf7..a651ccf 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/post/NewPost.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/post/NewPost.kt @@ -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 ) } diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 09d7a69..1116912 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -12,6 +12,7 @@ ユーザー いいね フォロワー + 投稿 お気に入り あれ、何もない。.. 通知 @@ -51,6 +52,10 @@ 最高のサービスを提供するために、登録前に利用規約を読み、同意してください。 まだ投稿がありません 今すぐモーメントを投稿 + ストーリーはまだ始まっていません + あなたのストーリーはまだ始まっていません + モーメントを投稿して、世界に挨拶しましょう + 画像がありません プロフィールを編集 シェア ログアウト @@ -142,17 +147,21 @@ 例:経験豊富な営業担当者で、ユーモアと生きた事例を使って、複雑な製品を顧客が理解しやすい形に変えるのが得意 エージェントを作成 投稿のインスピレーションが必要ですか?AIがお手伝いします! - AIの文案最適化 + 文案最適化 削除 適用 AI グループ 友達 すべて + 公開 + プライベート 人はおしゃべりをしている… AIエージェントチャット AIエージェントチャットがありません AIエージェントと対話してみましょう + 専属AIがあなたを待っています + AIはあなたのパートナーとなり、ツールではありません 私: [画像] [音声] @@ -164,10 +173,15 @@ ユーザー情報の取得に失敗しました: %s グループチャットがありません まだどのグループチャットにも参加していません + 何もありません~ グループチャットメッセージのない宇宙は静かすぎます ホームで興味のあるテーマルームを探してみましょう まだ友達とチャットしていません~ 友達のアバターをクリックして、すぐにチャットを始めましょう。 + まだ誰もフォローしていません + 探索してみてください。近づきたい光が見つかります ✨ + まだ誰もあなたをフォローしていません + 信号を送ってみてください。誰かが引き寄せられるでしょう~ 私: 読み込みに失敗しました グループチャットを作成 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 289e3bf..f536b55 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -12,6 +12,7 @@ 用户 粉丝 + 帖子 收藏 消息 关注11 @@ -50,6 +51,10 @@ "为了提供更好的服务,请您在注册前仔细阅读并同意《用户协议》。 " 还没有发布任何动态 发布一个动态吧 + 故事还没开始 + 你的故事还没开始 + 发布一条动态,和世界打个招呼吧 + 暂无图片 编辑 分享 登出 @@ -151,11 +156,15 @@ 群聊 朋友 全部 + 公开 + 私有 咦,什么都没有... 智能体聊天 AI 在等你的开场白 去首页探索一下,主动发起对话! + 专属AI等你召唤 + AI将成为你的伙伴,而不是工具 我: [图片] [语音] @@ -167,10 +176,15 @@ 获取用户信息失败: %s 没有群聊,宇宙好安静 没有群聊消息的宇宙太安静了 + 空空如也~ 在首页探索感兴趣的主题房间 去首页探索感兴趣的高能对话 和朋友,还没有对话哦~ 点击好友头像,即刻发起聊天 + 还没有关注任何灵魂 + 探索一下,总有一个你想靠近的光点 ✨ + 还没有人关注你呢 + 试着发信号出来,某人就会被吸引啦~ 我: 加载失败 创建群聊 @@ -286,6 +300,32 @@ 解锁费用: %1$d 派币 完成 可通过充值获得更多派币 + + + MBTI 类型 + 星座 + 更换封面 + 个人简介 + 昵称不能为空 + 昵称长度不能小于3 + 昵称长度不能大于20 + 个人简介长度不能大于100 + 加载用户资料失败,请重试 + 保存 + 选择 MBTI + 选择星座 + 白羊座 + 金牛座 + 双子座 + 巨蟹座 + 狮子座 + 处女座 + 天秤座 + 天蝎座 + 射手座 + 摩羯座 + 水瓶座 + 双鱼座 群聊成员 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0611e82..35affe3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,6 +11,7 @@ Users LIKE FOLLOWERS + Posts FAVOURITES Well,nothing NOTIFICATIONS @@ -50,6 +51,10 @@ To provide you with the best service, please read and agree to our User Agreement before registering. You haven\'t left any tracks yet Post a moment now + Your story hasn\'t started yet + Your story hasn\'t started yet + Post a moment and say hello to the world + No image Edit profile share Logout @@ -141,7 +146,7 @@ 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 Create Agent Need some inspiration for your post? Let AI assist you! - AI copywriting optimization + copywriting optimization Delete Apply Ai @@ -149,9 +154,13 @@ Friends people chatting now… All + Public + Private Agent Chat No Agent Chat Start chatting with agents + Exclusive AI waiting for you + AI will be your companion, not a tool Me: [Image] [Voice] @@ -163,10 +172,15 @@ Failed to get user info: %s No group chats You have not joined any group chats yet + Nothing here~ The universe is too quiet without group chat messages Explore interesting theme rooms on the homepage Have not chatted with friends yet~ Click on the avatar of friend to start chatting instantly. + Not following anyone yet + Explore and you\'ll find a light you want to get close to ✨ + No one is following you yet + Try sending out a signal, someone will be attracted to you~ Me: Failed to load Create Group Chat @@ -294,9 +308,28 @@ MBTI Zodiac + Change Cover + Personal Introduction + Nickname cannot be empty + Nickname length cannot be less than 3 + Nickname length cannot be greater than 20 + Bio length cannot be greater than 100 + Failed to load user profile, please try again Save Choose MBTI Choose Zodiac + Aries + Taurus + Gemini + Cancer + Leo + Virgo + Libra + Scorpio + Sagittarius + Capricorn + Aquarius + Pisces Scan QR