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