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 58827ef..31a4d70 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
@@ -87,8 +87,8 @@ import com.aiosman.ravenow.ui.composables.toolbar.rememberCollapsingToolbarScaff
import com.aiosman.ravenow.ui.index.IndexViewModel
import com.aiosman.ravenow.ui.index.tabs.profile.composable.GalleryGrid
import com.aiosman.ravenow.ui.post.MenuActionItem
+import com.aiosman.ravenow.ui.index.tabs.profile.composable.GroupChatEmptyContent
import com.aiosman.ravenow.ui.index.tabs.profile.composable.OtherProfileAction
-import com.aiosman.ravenow.ui.index.tabs.profile.composable.SelfProfileAction
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserAgentsList
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserAgentsRow
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserContentPageIndicator
@@ -129,7 +129,8 @@ fun ProfileV3(
postCount: Long? = null, // 新增参数用于传递帖子总数
) {
val model = MyProfileViewModel
- val pagerState = rememberPagerState(pageCount = { if (isAiAccount) 1 else 2 })
+ // Tabs: 动态、(可选)智能体、群聊
+ val pagerState = rememberPagerState(pageCount = { if (isAiAccount) 2 else 3 })
val enabled by remember { mutableStateOf(true) }
val statusBarPaddingValues = WindowInsets.systemBars.asPaddingValues()
var expanded by remember { mutableStateOf(false) }
@@ -370,41 +371,34 @@ fun ProfileV3(
profile?.let {
UserItem(
accountProfileEntity = it,
- postCount = postCount ?: if (isSelf) MyProfileViewModel.momentLoader.total else moments.size.toLong()
+ postCount = postCount ?: if (isSelf) MyProfileViewModel.momentLoader.total else moments.size.toLong(),
+ isSelf = isSelf,
+ onEditClick = {
+ navController.navigate(NavigationRoute.AccountEdit.route)
+ }
)
}
}
Spacer(modifier = Modifier.height(20.dp))
- // 操作按钮
+ // 操作按钮(仅其他用户显示)
profile?.let {
- Box(
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = 16.dp)
- ) {
- if (isSelf) {
- SelfProfileAction(
- onEditProfile = {
- navController.navigate(NavigationRoute.AccountEdit.route)
+ if (!isSelf && it.id != AppState.UserId) {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp)
+ ) {
+ OtherProfileAction(
+ it,
+ onFollow = {
+ onFollowClick()
},
- onPremiumClick = {
- navController.navigate(NavigationRoute.VipSelPage.route)
+ onChat = {
+ onChatClick()
}
)
- } else {
- if (it.id != AppState.UserId) {
- OtherProfileAction(
- it,
- onFollow = {
- onFollowClick()
- },
- onChat = {
- onChatClick()
- }
- )
- }
}
}
}
@@ -458,36 +452,44 @@ fun ProfileV3(
pagerState = pagerState,
showAgentTab = !isAiAccount
)
- Spacer(modifier = Modifier.height(8.dp))
HorizontalPager(
state = pagerState,
modifier = Modifier.height(500.dp) // 固定滚动高度
) { idx ->
when (idx) {
- 0 ->
- GalleryGrid(moments = moments)
- 1 ->
- UserAgentsList(
- agents = agents,
- onAgentClick = onAgentClick,
- onAvatarClick = { agent ->
- // 导航到智能体个人主页,需要通过openId获取用户ID
- scope.launch {
- try {
- val userService = com.aiosman.ravenow.data.UserServiceImpl()
- val profile = userService.getUserProfileByOpenId(agent.openId)
- navController.navigate(
- NavigationRoute.AccountProfile.route
- .replace("{id}", profile.id.toString())
- .replace("{isAiAccount}", "true")
- )
- } catch (e: Exception) {
- // 处理错误
+ 0 -> GalleryGrid(moments = moments)
+ 1 -> {
+ if (!isAiAccount) {
+ UserAgentsList(
+ agents = agents,
+ onAgentClick = onAgentClick,
+ onAvatarClick = { agent ->
+ // 导航到智能体个人主页,需要通过openId获取用户ID
+ scope.launch {
+ try {
+ val userService = com.aiosman.ravenow.data.UserServiceImpl()
+ val profile = userService.getUserProfileByOpenId(agent.openId)
+ navController.navigate(
+ NavigationRoute.AccountProfile.route
+ .replace("{id}", profile.id.toString())
+ .replace("{isAiAccount}", "true")
+ )
+ } catch (e: Exception) {
+ // 处理错误
+ }
}
- }
- },
- modifier = Modifier.fillMaxSize()
- )
+ },
+ modifier = Modifier.fillMaxSize()
+ )
+ } else {
+ GroupChatPlaceholder()
+ }
+ }
+ 2 -> {
+ if (!isAiAccount) {
+ GroupChatPlaceholder()
+ }
+ }
}
}
}
@@ -582,6 +584,11 @@ fun ProfileV3(
}
}
+@Composable
+private fun GroupChatPlaceholder() {
+ GroupChatEmptyContent()
+}
+
//顶部导航栏组件
@Composable
fun TopNavigationBar(
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
new file mode 100644
index 0000000..2c5fa48
--- /dev/null
+++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/profile/composable/GroupChatEmptyContent.kt
@@ -0,0 +1,167 @@
+package com.aiosman.ravenow.ui.index.tabs.profile.composable
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Divider
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+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.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.aiosman.ravenow.R
+
+@Composable
+fun GroupChatEmptyContent() {
+ var selectedSegment by remember { mutableStateOf(0) } // 0: 全部, 1: 公开, 2: 私有
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(horizontal = 16.dp)
+ ) {
+ // 分割线(紧贴上方栏)
+ Divider(
+ color = Color(0xFFF0F0F0), // 更浅的灰色
+ thickness = 1.dp,
+ modifier = Modifier.fillMaxWidth()
+ )
+
+ Spacer(modifier = Modifier.height(16.dp))
+
+ // 分段控制器
+ SegmentedControl(
+ selectedIndex = selectedSegment,
+ onSegmentSelected = { selectedSegment = it },
+ modifier = Modifier.fillMaxWidth()
+ )
+
+ Spacer(modifier = Modifier.height(8.dp))
+
+ // 空状态内容(居中)
+ Column(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ // 空状态插图
+ EmptyStateIllustration()
+
+ Spacer(modifier = Modifier.height(9.dp))
+
+ // 空状态文本
+ Text(
+ text = "空空如也~",
+ fontSize = 16.sp,
+ fontWeight = FontWeight.SemiBold,
+ color = Color(0xFF000000)
+ )
+ }
+ }
+}
+
+@Composable
+private fun SegmentedControl(
+ selectedIndex: Int,
+ onSegmentSelected: (Int) -> Unit,
+ modifier: Modifier = Modifier
+) {
+ Row(
+ modifier = modifier
+ .height(32.dp),
+ horizontalArrangement = Arrangement.Start,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ // 全部
+ SegmentButton(
+ text = "全部",
+ isSelected = selectedIndex == 0,
+ onClick = { onSegmentSelected(0) },
+ width = 54.dp
+ )
+
+ Spacer(modifier = Modifier.width(8.dp))
+
+ // 公开
+ SegmentButton(
+ text = "公开",
+ isSelected = selectedIndex == 1,
+ onClick = { onSegmentSelected(1) },
+ width = 59.dp
+ )
+
+ Spacer(modifier = Modifier.width(8.dp))
+
+ // 私有
+ SegmentButton(
+ text = "私有",
+ isSelected = selectedIndex == 2,
+ onClick = { onSegmentSelected(2) },
+ width = 54.dp
+ )
+ }
+}
+
+@Composable
+private fun SegmentButton(
+ text: String,
+ isSelected: Boolean,
+ onClick: () -> Unit,
+ width: androidx.compose.ui.unit.Dp
+) {
+ Box(
+ modifier = Modifier
+ .width(width)
+ .height(32.dp)
+ .background(
+ color = if (isSelected) {
+ Color(0xFF110C13) // RGB(17, 12, 19)
+ } else {
+ Color(0x147C7480) // RGB(124, 116, 128, alpha 0.08)
+ },
+ shape = RoundedCornerShape(1000.dp)
+ )
+ .clickable(onClick = onClick),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(
+ text = text,
+ fontSize = 13.sp,
+ fontWeight = FontWeight.Normal,
+ color = if (isSelected) Color(0xFFFFFFFF) else Color(0xFF000000)
+ )
+ }
+}
+
+@Composable
+private fun EmptyStateIllustration() {
+ Image(
+ painter = painterResource(id = R.mipmap.l_empty_img),
+ contentDescription = "空状态",
+ modifier = Modifier
+ .width(181.dp)
+ .height(153.dp),
+ contentScale = ContentScale.Fit
+ )
+}
+
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 30884d2..d91db42 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,6 +17,7 @@ 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
@@ -60,15 +61,14 @@ fun UserAgentsList(
) {
val AppColors = LocalAppTheme.current
- LazyColumn(
- modifier = modifier.fillMaxSize(),
- verticalArrangement = Arrangement.spacedBy(8.dp)
- ) {
- if (agents.isEmpty()) {
- item {
- EmptyAgentsView()
- }
- } else {
+ if (agents.isEmpty()) {
+ // 使用带分段控制器的空状态布局
+ AgentEmptyContentWithSegments()
+ } else {
+ LazyColumn(
+ modifier = modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
items(agents) { agent ->
UserAgentCard(
agent = agent,
@@ -76,11 +76,11 @@ fun UserAgentsList(
onAvatarClick = onAvatarClick
)
}
- }
-
- // 底部间距
- item {
- Spacer(modifier = Modifier.height(120.dp))
+
+ // 底部间距
+ item {
+ Spacer(modifier = Modifier.height(120.dp))
+ }
}
}
}
@@ -198,6 +198,178 @@ fun UserAgentCard(
}
}
+@Composable
+fun AgentEmptyContentWithSegments() {
+ var selectedSegment by remember { mutableStateOf(0) } // 0: 全部, 1: 公开, 2: 私有
+ val AppColors = LocalAppTheme.current
+ val isNetworkAvailable = NetworkUtils.isNetworkAvailable(LocalContext.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))
+
+ // 分段控制器
+ AgentSegmentedControl(
+ selectedIndex = selectedSegment,
+ onSegmentSelected = { selectedSegment = it },
+ modifier = Modifier.fillMaxWidth()
+ )
+
+ Spacer(modifier = Modifier.height(8.dp))
+
+ // 空状态内容(使用智能体原本的图标和文字)
+ Column(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ if (isNetworkAvailable) {
+ Image(
+ painter = painterResource(
+ id = if(AppState.darkMode) R.mipmap.ai_dark
+ else R.mipmap.ai),
+ contentDescription = "暂无Agent",
+ modifier = Modifier
+ .size(width = 181.dp, height = 153.dp)
+ .align(Alignment.CenterHorizontally),
+ )
+
+ // 根据是否为深色模式调整间距
+ Spacer(modifier = Modifier.height(if(AppState.darkMode) 9.dp else 24.dp))
+
+ Text(
+ text = "专属AI等你召唤",
+ fontSize = 16.sp,
+ color = AppColors.text,
+ fontWeight = FontWeight.W600
+ )
+
+ Spacer(modifier = Modifier.height(8.dp))
+
+ Text(
+ text = "AI将成为你的伙伴,而不是工具",
+ fontSize = 14.sp,
+ color = AppColors.secondaryText,
+ fontWeight = FontWeight.W400
+ )
+ } else {
+ Image(
+ painter = painterResource(id = R.mipmap.invalid_name_10),
+ contentDescription = "network error",
+ modifier = Modifier.size(181.dp),
+ )
+
+ Spacer(modifier = Modifier.height(24.dp))
+
+ Text(
+ text = stringResource(R.string.friend_chat_no_network_title),
+ fontSize = 16.sp,
+ color = AppColors.text,
+ fontWeight = FontWeight.W600
+ )
+
+ Spacer(modifier = Modifier.height(8.dp))
+
+ Text(
+ text = stringResource(R.string.friend_chat_no_network_subtitle),
+ fontSize = 14.sp,
+ color = AppColors.secondaryText,
+ fontWeight = FontWeight.W400
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ ReloadButton(
+ onClick = {
+ MyProfileViewModel.ResetModel()
+ MyProfileViewModel.loadProfile(pullRefresh = true)
+ }
+ )
+ }
+ }
+ }
+}
+
+@Composable
+private fun AgentSegmentedControl(
+ selectedIndex: Int,
+ onSegmentSelected: (Int) -> Unit,
+ modifier: Modifier = Modifier
+) {
+ Row(
+ modifier = modifier
+ .height(32.dp),
+ horizontalArrangement = Arrangement.Start,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ // 全部
+ AgentSegmentButton(
+ text = "全部",
+ isSelected = selectedIndex == 0,
+ onClick = { onSegmentSelected(0) },
+ width = 54.dp
+ )
+
+ Spacer(modifier = Modifier.width(8.dp))
+
+ // 公开
+ AgentSegmentButton(
+ text = "公开",
+ isSelected = selectedIndex == 1,
+ onClick = { onSegmentSelected(1) },
+ width = 59.dp
+ )
+
+ Spacer(modifier = Modifier.width(8.dp))
+
+ // 私有
+ AgentSegmentButton(
+ text = "私有",
+ isSelected = selectedIndex == 2,
+ onClick = { onSegmentSelected(2) },
+ width = 54.dp
+ )
+ }
+}
+
+@Composable
+private fun AgentSegmentButton(
+ text: String,
+ isSelected: Boolean,
+ onClick: () -> Unit,
+ width: androidx.compose.ui.unit.Dp
+) {
+ Box(
+ modifier = Modifier
+ .width(width)
+ .height(32.dp)
+ .background(
+ color = if (isSelected) {
+ Color(0xFF110C13) // RGB(17, 12, 19)
+ } else {
+ Color(0x147C7480) // RGB(124, 116, 128, alpha 0.08)
+ },
+ shape = RoundedCornerShape(1000.dp)
+ )
+ .clickable(onClick = onClick),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(
+ text = text,
+ fontSize = 13.sp,
+ fontWeight = FontWeight.Normal,
+ color = if (isSelected) Color(0xFFFFFFFF) else Color(0xFF000000)
+ )
+ }
+}
+
@Composable
fun EmptyAgentsView() {
val AppColors = LocalAppTheme.current
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 ec7b99a..75a3583 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
@@ -1,26 +1,38 @@
package com.aiosman.ravenow.ui.index.tabs.profile.composable
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.stringResource
+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
+import com.aiosman.ravenow.AppStore
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R
@@ -29,23 +41,52 @@ import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.rememberDebouncer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
+import java.text.NumberFormat
+import java.util.Locale
@Composable
fun UserItem(
accountProfileEntity: AccountProfileEntity,
- postCount: Long = 0
+ postCount: Long = 0,
+ isSelf: Boolean = false,
+ onEditClick: () -> Unit = {}
) {
val navController = LocalNavController.current
val AppColors = LocalAppTheme.current
val followerDebouncer = rememberDebouncer()
val followingDebouncer = rememberDebouncer()
+
+ // 获取 MBTI 和星座信息
+ val mbti = remember(accountProfileEntity.id) {
+ AppStore.getUserMbti(accountProfileEntity.id)
+ }
+ val zodiac = remember(accountProfileEntity.id) {
+ AppStore.getUserZodiac(accountProfileEntity.id)
+ }
+
+ // 格式化粉丝数
+ val numberFormat = remember { NumberFormat.getNumberInstance(Locale.getDefault()) }
+ val formattedFollowerCount = remember(accountProfileEntity.followerCount) {
+ if (accountProfileEntity.followerCount >= 10000) {
+ val wan = accountProfileEntity.followerCount / 10000.0
+ if (wan >= 100) {
+ "${wan.toInt()}万"
+ } else {
+ String.format("%.1f万", wan)
+ }
+ } else {
+ numberFormat.format(accountProfileEntity.followerCount)
+ }
+ }
Column(
modifier = Modifier
.fillMaxWidth()
) {
+ // 顶部:头像和统计数据
Row(
- verticalAlignment = Alignment.CenterVertically
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
// 头像
CustomAsyncImage(
@@ -53,39 +94,47 @@ fun UserItem(
accountProfileEntity.avatar,
modifier = Modifier
.clip(CircleShape)
- .size(48.dp),
+ .size(96.dp),
contentDescription = "",
contentScale = ContentScale.Crop
)
- Spacer(modifier = Modifier.width(32.dp))
- //个人统计
+
+ // 统计数据
Row(
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier.weight(1f)
+ modifier = Modifier.weight(1f),
+ horizontalArrangement = Arrangement.spacedBy(0.dp),
+ verticalAlignment = Alignment.CenterVertically
) {
// 帖子数
Column(
+ modifier = Modifier
+ .width(80.dp)
+ .height(40.dp),
horizontalAlignment = Alignment.CenterHorizontally,
- modifier = Modifier.weight(1f)
+ verticalArrangement = Arrangement.Center
) {
Text(
text = postCount.toString(),
- fontWeight = FontWeight.W600,
- fontSize = 16.sp,
- color = AppColors.text
+ fontWeight = FontWeight.Medium,
+ fontSize = 15.sp,
+ color = Color(0xFF000000),
+ textAlign = TextAlign.Center
)
- Spacer(modifier = Modifier.height(8.dp))
+ Spacer(modifier = Modifier.height(2.dp))
Text(
text = "帖子",
- color = AppColors.text
+ fontWeight = FontWeight.Normal,
+ fontSize = 11.sp,
+ color = Color(0xFF000000),
+ textAlign = TextAlign.Center
)
}
// 粉丝数
Column(
- horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
- .weight(1f)
+ .width(80.dp)
+ .height(40.dp)
.noRippleClickable {
followerDebouncer {
navController.navigate(
@@ -95,26 +144,33 @@ fun UserItem(
)
)
}
- }
+ },
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.Center
) {
Text(
- text = accountProfileEntity.followerCount.toString(),
- fontWeight = FontWeight.W600,
- fontSize = 16.sp,
- color = AppColors.text
+ text = formattedFollowerCount,
+ fontWeight = FontWeight.Medium,
+ fontSize = 15.sp,
+ color = Color(0xFF000000),
+ textAlign = TextAlign.Center
)
- Spacer(modifier = Modifier.height(8.dp))
+ Spacer(modifier = Modifier.height(2.dp))
Text(
text = "粉丝",
- color = AppColors.text
+ fontWeight = FontWeight.Normal,
+ fontSize = 11.sp,
+ color = Color(0xFF000000),
+ textAlign = TextAlign.Center
)
}
// 关注数
Column(
- horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
- .weight(1f)
+ .width(80.dp)
+ .height(40.dp)
+ .offset(x = 6.dp)
.noRippleClickable {
followingDebouncer {
navController.navigate(
@@ -124,49 +180,161 @@ fun UserItem(
)
)
}
- }
+ },
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.Center
) {
Text(
text = accountProfileEntity.followingCount.toString(),
- fontWeight = FontWeight.W600,
- fontSize = 16.sp,
- color = AppColors.text
+ fontWeight = FontWeight.Medium,
+ fontSize = 15.sp,
+ color = Color(0xFF000000),
+ textAlign = TextAlign.Center
)
- Spacer(modifier = Modifier.height(8.dp))
+ Spacer(modifier = Modifier.height(2.dp))
Text(
text = "关注",
- color = AppColors.text
+ fontWeight = FontWeight.Normal,
+ fontSize = 11.sp,
+ color = Color(0xFF000000),
+ textAlign = TextAlign.Center
)
}
}
}
+
Spacer(modifier = Modifier.height(12.dp))
- // 昵称
- Text(
- text = accountProfileEntity.nickName,
- fontWeight = FontWeight.W600,
- fontSize = 16.sp,
- color = AppColors.text
- )
- Spacer(modifier = Modifier.height(4.dp))
- // 个人简介
- if (accountProfileEntity.bio.isNotEmpty()){
+
+ // 中间:昵称、简介、创建者信息
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ ) {
+ // 昵称
Text(
- text = accountProfileEntity.bio,
- fontSize = 14.sp,
- color = AppColors.secondaryText,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis
+ text = accountProfileEntity.nickName,
+ fontWeight = FontWeight.Bold,
+ fontSize = 22.sp,
+ letterSpacing = (-0.3).sp,
+ color = Color(0xFF000000)
)
- }else{
+
+ Spacer(modifier = Modifier.height(4.dp))
+
+ // 个人简介
+ if (accountProfileEntity.bio.isNotEmpty()) {
+ Text(
+ text = accountProfileEntity.bio,
+ fontSize = 13.sp,
+ color = Color(0x993C3C43), // 60/255, 60/255, 67/255, alpha 0.6
+ maxLines = 2,
+ overflow = TextOverflow.Ellipsis
+ )
+ } else {
+ Text(
+ text = "Welcome to my fantiac word i will show you something about magic",
+ fontSize = 13.sp,
+ color = Color(0x993C3C43),
+ maxLines = 2,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+
+ // 创建者信息(如果是 AI 账户,可以显示创建者)
+ // 注意:当前 AccountProfileEntity 没有创建者字段,这里暂时留空
+ // 如果需要显示,需要从其他地方获取创建者信息
+ }
+
+ Spacer(modifier = Modifier.height(12.dp))
+
+ // 底部:标签按钮
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ // MBTI 标签
+ if (!mbti.isNullOrEmpty()) {
+ ProfileTag(
+ text = mbti,
+ backgroundColor = Color(0x33FF8D28), // 255/255, 141/255, 40/255, alpha 0.2
+ textColor = Color(0xFF000000)
+ )
+ }
+
+ // 星座标签
+ if (!zodiac.isNullOrEmpty()) {
+ ProfileTag(
+ text = zodiac,
+ backgroundColor = Color(0x33FFCC00), // 255/255, 204/255, 0/255, alpha 0.2
+ textColor = Color(0xFF000000)
+ )
+ }
+
+ // 编辑标签(仅自己可见)
+ if (isSelf) {
+ ProfileTag(
+ text = "编辑",
+ backgroundColor = Color(0x14947A80), // 124/255, 116/255, 128/255, alpha 0.08
+ textColor = Color(0xFF9284BD), // 146/255, 132/255, 189/255
+ leadingIcon = {
+ EditIcon(
+ color = Color(0xFF9284BD),
+ modifier = Modifier.size(16.dp)
+ )
+ },
+ onClick = onEditClick
+ )
+ }
+ }
+ }
+}
+
+@Composable
+private fun ProfileTag(
+ text: String,
+ backgroundColor: Color,
+ textColor: Color,
+ leadingIcon: (@Composable () -> Unit)? = null,
+ onClick: (() -> Unit)? = null
+) {
+ Box(
+ modifier = Modifier
+ .height(25.dp)
+ .clip(RoundedCornerShape(12.dp))
+ .background(backgroundColor)
+ .then(
+ if (onClick != null) {
+ Modifier.clickable(onClick = onClick)
+ } else {
+ Modifier
+ }
+ )
+ .padding(horizontal = 8.dp, vertical = 4.dp),
+ contentAlignment = Alignment.Center
+ ) {
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ leadingIcon?.invoke()
Text(
- text = "No bio here.",
- fontSize = 14.sp,
- color = AppColors.secondaryText,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis
+ text = text,
+ fontSize = 12.sp,
+ color = textColor
)
}
}
-
+}
+
+@Composable
+private fun EditIcon(
+ color: Color,
+ modifier: Modifier = Modifier
+) {
+ Image(
+ painter = painterResource(id = R.mipmap.bi),
+ contentDescription = "编辑",
+ modifier = modifier,
+ colorFilter = ColorFilter.tint(color)
+ )
}
diff --git a/app/src/main/res/drawable/icons_circle_camera.png b/app/src/main/res/drawable/icons_circle_camera.png
new file mode 100644
index 0000000..1604630
Binary files /dev/null and b/app/src/main/res/drawable/icons_circle_camera.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icons_block.png b/app/src/main/res/mipmap-hdpi/icons_block.png
new file mode 100644
index 0000000..a044809
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icons_block.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icons_padlock.png b/app/src/main/res/mipmap-hdpi/icons_padlock.png
new file mode 100644
index 0000000..9b66dec
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icons_padlock.png differ
diff --git a/app/src/main/res/mipmap-hdpi/icons_remove.png b/app/src/main/res/mipmap-hdpi/icons_remove.png
new file mode 100644
index 0000000..b597232
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icons_remove.png differ
diff --git a/app/src/main/res/mipmap-hdpi/l_empty_img.png b/app/src/main/res/mipmap-hdpi/l_empty_img.png
new file mode 100644
index 0000000..eca7860
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/l_empty_img.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_email_light.png b/app/src/main/res/mipmap-mdpi/icon_email_light.png
new file mode 100644
index 0000000..1a3b78e
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_email_light.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_eyes_closed_light.png b/app/src/main/res/mipmap-mdpi/icon_eyes_closed_light.png
new file mode 100644
index 0000000..0a985c3
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_eyes_closed_light.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_lock_light.png b/app/src/main/res/mipmap-mdpi/icon_lock_light.png
new file mode 100644
index 0000000..ebd5db1
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_lock_light.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icons_block.png b/app/src/main/res/mipmap-mdpi/icons_block.png
new file mode 100644
index 0000000..d9b9e33
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icons_block.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icons_padlock.png b/app/src/main/res/mipmap-mdpi/icons_padlock.png
new file mode 100644
index 0000000..e5852c6
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icons_padlock.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icons_remove.png b/app/src/main/res/mipmap-mdpi/icons_remove.png
new file mode 100644
index 0000000..523091b
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icons_remove.png differ
diff --git a/app/src/main/res/mipmap-mdpi/l_empty_img.png b/app/src/main/res/mipmap-mdpi/l_empty_img.png
new file mode 100644
index 0000000..f0eb680
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/l_empty_img.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_email_light.png b/app/src/main/res/mipmap-xhdpi/icon_email_light.png
new file mode 100644
index 0000000..54148ed
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_email_light.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_eyes_closed_light.png b/app/src/main/res/mipmap-xhdpi/icon_eyes_closed_light.png
new file mode 100644
index 0000000..eff9952
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_eyes_closed_light.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icon_lock_light.png b/app/src/main/res/mipmap-xhdpi/icon_lock_light.png
new file mode 100644
index 0000000..c36298a
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_lock_light.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icons_block.png b/app/src/main/res/mipmap-xhdpi/icons_block.png
new file mode 100644
index 0000000..317e8d0
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icons_block.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icons_padlock.png b/app/src/main/res/mipmap-xhdpi/icons_padlock.png
new file mode 100644
index 0000000..454c390
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icons_padlock.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/icons_remove.png b/app/src/main/res/mipmap-xhdpi/icons_remove.png
new file mode 100644
index 0000000..a33ec95
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icons_remove.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/l_empty_img.png b/app/src/main/res/mipmap-xhdpi/l_empty_img.png
new file mode 100644
index 0000000..55906f2
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/l_empty_img.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_email_light.png b/app/src/main/res/mipmap-xxhdpi/icon_email_light.png
new file mode 100644
index 0000000..27551c0
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_email_light.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_eyes_closed_light.png b/app/src/main/res/mipmap-xxhdpi/icon_eyes_closed_light.png
new file mode 100644
index 0000000..3f18bea
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_eyes_closed_light.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_lock_light.png b/app/src/main/res/mipmap-xxhdpi/icon_lock_light.png
new file mode 100644
index 0000000..1355549
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_lock_light.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icons_block.png b/app/src/main/res/mipmap-xxhdpi/icons_block.png
new file mode 100644
index 0000000..955b413
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icons_block.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icons_padlock.png b/app/src/main/res/mipmap-xxhdpi/icons_padlock.png
new file mode 100644
index 0000000..9da8a62
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icons_padlock.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icons_remove.png b/app/src/main/res/mipmap-xxhdpi/icons_remove.png
new file mode 100644
index 0000000..73a03ce
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icons_remove.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/l_empty_img.png b/app/src/main/res/mipmap-xxhdpi/l_empty_img.png
new file mode 100644
index 0000000..65d8bc3
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/l_empty_img.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/icons_block.png b/app/src/main/res/mipmap-xxxhdpi/icons_block.png
new file mode 100644
index 0000000..e13dcb3
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icons_block.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/icons_padlock.png b/app/src/main/res/mipmap-xxxhdpi/icons_padlock.png
new file mode 100644
index 0000000..492b16a
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icons_padlock.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/icons_remove.png b/app/src/main/res/mipmap-xxxhdpi/icons_remove.png
new file mode 100644
index 0000000..da1adc6
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icons_remove.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/l_empty_img.png b/app/src/main/res/mipmap-xxxhdpi/l_empty_img.png
new file mode 100644
index 0000000..412d54d
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/l_empty_img.png differ
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 79684f9..2cd8e9d 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -23,10 +23,11 @@
ログイン
レッツ・レヴ・ナウ
または
- ログイン状態を保持する
+ ログインを記憶
パスワードをお忘れですか?
パスワード
メールアドレス
+ パスワードの確認
メールアドレスは必須です
パスワードは必須です
メールアドレスを入力してください
@@ -91,7 +92,7 @@
メールの送信に失敗しました。ネットワーク接続を確認するか、後でもう一度お試しください。
%1d秒前
%1d分前
- 同意する
+ パイパイに同意する
Rave Nowのプライバシーポリシー
ギャラリー
チャット
@@ -114,9 +115,10 @@
この投稿を報告する理由は?
閉じる
ブロック済み
+ ブロック済みユーザー
フィードバック
Rave Nowについて
- アカウントとセキュリティ
+ アカウントセキュリティ
アカウントを削除
本当にアカウントを削除しますか?この操作は元に戻せません。
確認のためパスワードを入力してください
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index cf26ca3..13398da 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -22,10 +22,11 @@
登录
确认
其他账号登录
- 记住我
+ 记住登录
忘记密码
密码
邮箱
+ 确认密码
邮箱是必填项
密码是必填项
输入邮箱
@@ -92,7 +93,7 @@
邮件发送失败,请检查您的网络连接或稍后重试。
%1d秒前
%1d分钟前
- 同意
+ 我同意派派的
用户协议
图片
私信
@@ -116,8 +117,9 @@
关闭
关于Rave Now
已拉黑
+ 被屏蔽的用户
反馈
- 账户与安全
+ 账号安全
删除账户
注销账号为不可逆的操作,请确认
输入密码以确认
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9a3cf4f..f2bcb18 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -22,10 +22,11 @@
Log in
Let\'s Rave Now
or
- Remember me.
+ Remember login
Forgot password?
What\'s your password
What\'s your email
+ Confirm password
Email is required
Password is required
Enter your email
@@ -90,7 +91,7 @@
Failed to send email. Please check your network connection or try again later.
%1d seconds ago
%1d minutes ago
- I agree to the
+ I agree to Paipai\'s
Rave Now’s Privacy Policy
Gallery
CHAT
@@ -113,9 +114,10 @@
Reason for reporting this post?
Close
Blocked
+ Blocked Users
Feedback
About Rave Now
- Account and security
+ Account Security
Remove Account
Are you sure you want to remove your account? This action cannot be undone.
Please enter your password to confirm