新增苹果账户登录;新增拉黑功能;UI调整

This commit is contained in:
2025-10-23 17:56:24 +08:00
parent 2a5174cbb6
commit 13ed16078b
23 changed files with 452 additions and 58 deletions

View File

@@ -16,9 +16,9 @@ sealed class NavigationItem(
) {
data object Home : NavigationItem("Home",
icon = { R.drawable.rider_pro_nav_home },
selectedIcon = { R.mipmap.bars_x_buttons_home_s },
label = { stringResource(R.string.main_home) }
icon = { R.mipmap.bars_x_buttons_home_n_copy },
selectedIcon = { R.mipmap.bars_x_buttons_home_n_copy_2 },
label = { stringResource(R.string.main_ai) }
)
data object Ai : NavigationItem("Ai",

View File

@@ -0,0 +1,178 @@
package com.aiosman.ravenow.ui.index.tabs.profile
import androidx.compose.foundation.background
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.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
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.unit.dp
import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.R
import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
/**
* 拉黑确认弹窗
*/
@Composable
fun BlockConfirmDialog(
userProfile: AccountProfileEntity?,
onConfirmBlock: () -> Unit = {},
onDismiss: () -> Unit = {}
) {
val AppColors = LocalAppTheme.current
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.BottomCenter
) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(
color = AppColors.background,
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
)
.padding(24.dp)
) {
// 用户头像
Box(
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(bottom = 16.dp)
) {
CustomAsyncImage(
LocalContext.current,
userProfile?.avatar,
modifier = Modifier
.size(60.dp)
.clip(CircleShape)
.background(
color = AppColors.background,
shape = CircleShape
),
contentDescription = "用户头像",
contentScale = ContentScale.Crop
)
}
// 确认文本
Text(
text = stringResource(R.string.confirm_block_user, userProfile?.nickName ?: "该用户"),
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = AppColors.text,
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(bottom = 24.dp)
)
// 说明信息
Column(
modifier = Modifier.padding(bottom = 32.dp)
) {
// 第一条说明
Row(
modifier = Modifier.padding(bottom = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = painterResource(id = R.mipmap.icons_infor_off_eye),
contentDescription = "",
tint = AppColors.text,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = stringResource(R.string.block_description_1),
fontSize = 14.sp,
color = AppColors.text,
lineHeight = 20.sp
)
}
// 第二条说明
Row(
modifier = Modifier.padding(bottom = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = painterResource(id = R.drawable.rider_pro_notice_mute),
contentDescription = "",
tint = AppColors.text,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = stringResource(R.string.block_description_2),
fontSize = 14.sp,
color = AppColors.text,
lineHeight = 20.sp
)
}
// 第三条说明
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = painterResource(id = R.mipmap.icons_infor_off_bell),
contentDescription = "",
tint = AppColors.text,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = stringResource(R.string.block_description_3),
fontSize = 14.sp,
color = AppColors.text,
lineHeight = 20.sp
)
}
}
// 确认拉黑按钮
androidx.compose.material3.Button(
onClick = {
onConfirmBlock()
onDismiss()
},
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
colors = androidx.compose.material3.ButtonDefaults.buttonColors(
containerColor = AppColors.text
),
shape = RoundedCornerShape(24.dp)
) {
Text(
stringResource(R.string.block),
color = AppColors.background,
fontSize = 16.sp,
fontWeight = FontWeight.Bold
)
}
}
}
}

View File

@@ -99,6 +99,8 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import androidx.compose.foundation.rememberScrollState
import androidx.compose.ui.res.stringResource
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
@Composable
fun ProfileV3(
@@ -127,6 +129,8 @@ fun ProfileV3(
var showAgentMenu by remember { mutableStateOf(false) }
var contextAgent by remember { mutableStateOf<AgentEntity?>(null) }
var showDeleteConfirmDialog by remember { mutableStateOf(false) }
var showOtherUserMenu by remember { mutableStateOf(false) }
var showBlockConfirmDialog by remember { mutableStateOf(false) }
val context = LocalContext.current
val scope = rememberCoroutineScope()
val navController = LocalNavController.current
@@ -154,11 +158,15 @@ fun ProfileV3(
val toolbarAlpha by remember {
derivedStateOf {
if (!isSelf) {
1f
} else {
val maxScroll = 500f // 最大滚动距离,可调整
val progress = (scrollState.value.coerceAtMost(maxScroll.toInt()) / maxScroll).coerceIn(0f, 1f)
progress
}
}
}
// observe list scrolling
val reachedListBottom by remember {
@@ -478,7 +486,10 @@ fun ProfileV3(
isSelf = isSelf,
profile = profile,
navController = navController,
alpha = toolbarAlpha
alpha = toolbarAlpha,
onMenuClick = {
showOtherUserMenu = true
}
)
PullRefreshIndicator(
@@ -486,6 +497,68 @@ fun ProfileV3(
refreshState,
Modifier.align(Alignment.TopCenter)
)
// 其他用户菜单弹窗
if (showOtherUserMenu) {
ModalBottomSheet(
onDismissRequest = { showOtherUserMenu = false },
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
containerColor = Color.Transparent, // 设置容器背景透明
contentColor = Color.Transparent, // 设置内容背景透明
dragHandle = null, // 移除拖拽手柄
windowInsets = androidx.compose.foundation.layout.WindowInsets(0) // 移除窗口边距
) {
Box(
modifier = Modifier
.fillMaxWidth()
.background(Color.Transparent)
) {
OtherUserMenuModal(
onBlockClick = {
showBlockConfirmDialog = true
},
onReportClick = {
// 实现举报逻辑
},
onCancelClick = {
showOtherUserMenu = false
},
onDismiss = { showOtherUserMenu = false }
)
}
}
// 拉黑确认弹窗
if (showBlockConfirmDialog) {
ModalBottomSheet(
onDismissRequest = {
showBlockConfirmDialog = false
},
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
containerColor = Color.Transparent,
contentColor = Color.Transparent,
dragHandle = null,
windowInsets = androidx.compose.foundation.layout.WindowInsets(0)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.background(Color.Transparent)
) {
BlockConfirmDialog(
userProfile = profile,
onConfirmBlock = {
// 实现拉黑逻辑
},
onDismiss = {
showBlockConfirmDialog = false
showOtherUserMenu = false
}
)
}
}
}
}
}
}
@@ -496,14 +569,14 @@ fun TopNavigationBar(
isSelf: Boolean,
profile: AccountProfileEntity?,
navController: androidx.navigation.NavController,
alpha: Float
alpha: Float,
onMenuClick: () -> Unit = {}
) {
val appColors = LocalAppTheme.current
Box(
modifier = Modifier
.fillMaxWidth()
.graphicsLayer { this.alpha = alpha } // 应用透明度
.graphicsLayer { this.alpha = alpha }
) {
Column(
modifier = Modifier
@@ -555,6 +628,21 @@ fun TopNavigationBar(
.size(24.dp)
.padding(16.dp)
)
} else if (!isSelf) {
Box(
modifier = Modifier
.noRippleClickable {
onMenuClick()
}
.padding(16.dp)
) {
Icon(
painter = painterResource(id = R.drawable.rider_pro_more_horizon),
contentDescription = "菜单",
tint = appColors.text,
modifier = Modifier.size(24.dp)
)
}
}
}
Spacer(modifier = Modifier.height(8.dp))
@@ -661,7 +749,7 @@ fun AgentMenuModal(
if (isSelf) {
MenuActionItem(
icon = R.drawable.rider_pro_moment_delete,
text = "删除"
text = stringResource(R.string.delete)
) {
onDeleteClick()
}
@@ -737,3 +825,96 @@ fun DeleteConfirmDialog(
containerColor = AppColors.background
)
}
/**
* 其他用户主页菜单弹窗
*/
@Composable
fun OtherUserMenuModal(
onBlockClick: () -> Unit = {},
onReportClick: () -> Unit = {},
onCancelClick: () -> Unit = {},
onDismiss: () -> Unit = {}
) {
val AppColors = LocalAppTheme.current
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.BottomCenter
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
.padding(bottom = 11.dp)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(
color = AppColors.background,
shape = RoundedCornerShape(8.dp)
)
) {
// 拉黑选项
androidx.compose.material3.TextButton(
onClick = {
onBlockClick()
},
modifier = Modifier.fillMaxWidth()
) {
Text(
stringResource(R.string.block),
color = AppColors.error,
fontWeight = FontWeight.Bold,
fontSize = 16.sp
)
}
// 分割线
androidx.compose.material3.HorizontalDivider(
color = AppColors.divider,
thickness = 0.5.dp
)
// 举报选项
androidx.compose.material3.TextButton(
onClick = {
onReportClick()
onDismiss()
},
modifier = Modifier.fillMaxWidth()
) {
Text(
stringResource(R.string.report),
color = AppColors.error,
fontWeight = FontWeight.Bold,
fontSize = 16.sp
)
}
}
Spacer(modifier = Modifier.height(8.dp))
// 取消按钮
androidx.compose.material3.TextButton(
onClick = {
onCancelClick()
onDismiss()
},
modifier = Modifier
.fillMaxWidth()
.background(
color = AppColors.background,
shape = RoundedCornerShape(8.dp)
)
) {
Text(
stringResource(R.string.cancel),
color = AppColors.text,
fontSize = 16.sp
)
}
}
}
}

View File

@@ -6,6 +6,7 @@ import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.rememberScrollableState
import androidx.compose.foundation.gestures.scrollable
@@ -272,16 +273,10 @@ fun LoginPage() {
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
.padding(top = 100.dp),
.padding(top = 60.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.join_party_carnival),
fontSize = 14.sp,
color = AppColors.text
)
Box(
modifier = Modifier
.size(30.dp)
@@ -302,17 +297,8 @@ fun LoginPage() {
)
}
}
Box(
modifier = Modifier.fillMaxSize()
) {
val lottieFile = if (AppState.darkMode) "login.lottie" else "login_light.lottie"
LottieAnimation(
composition = rememberLottieComposition(LottieCompositionSpec.Asset(lottieFile)).value,
iterations = LottieConstants.IterateForever,
modifier = Modifier.fillMaxSize()
.padding(30.dp)
)
}
Spacer(modifier = Modifier.height(20.dp))
Column(
modifier = Modifier
@@ -321,6 +307,25 @@ fun LoginPage() {
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.weight(1f))
Box(
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
) {
val lottieFile = if (AppState.darkMode) "login.lottie" else "login_light.lottie"
LottieAnimation(
composition = rememberLottieComposition(LottieCompositionSpec.Asset(lottieFile)).value,
iterations = LottieConstants.IterateForever,
modifier = Modifier.fillMaxSize()
)
}
Text(
text = stringResource(R.string.join_party_carnival),
fontSize = 17.sp,
fontWeight = FontWeight.W600,
color = AppColors.text
)
// Image(
// painter = painterResource(id = R.mipmap.invalid_name),
// contentDescription = "Rave Now",
@@ -343,7 +348,7 @@ fun LoginPage() {
// color = AppColors.text
// )
//注册tab
Spacer(modifier = Modifier.height(8.dp))
Spacer(modifier = Modifier.height(48.dp))
ActionButton(
modifier = Modifier.fillMaxWidth(),
text = stringResource(R.string.sign_up_upper),
@@ -354,25 +359,32 @@ fun LoginPage() {
NavigationRoute.EmailSignUp.route,
)
}
// if (showGoogleLogin) {
// Spacer(modifier = Modifier.height(16.dp))
// ActionButton(
// modifier = Modifier.fillMaxWidth(),
// text = stringResource(R.string.sign_in_with_google),
// color = AppColors.text,
// leading = {
// Image(
// painter = painterResource(id = R.drawable.rider_pro_google),
// contentDescription = "Google",
// modifier = Modifier.size(36.dp)
// )
// },
// expandText = true,
// contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp)
// ) {
// googleLogin()
// }
// }
//苹果登录tab
Spacer(modifier = Modifier.height(16.dp))
ActionButton(
modifier = Modifier
.fillMaxWidth()
.border(
width = 1.dp,
color = if (AppState.darkMode) Color.White else Color.Black,
shape = RoundedCornerShape(24.dp)
),
text = stringResource(R.string.sign_in_with_apple),
color = if (AppState.darkMode) Color.White else Color.Black,
backgroundColor = if (AppState.darkMode) Color.Black else Color.White,
leading = {
Image(
painter = painterResource(id = R.mipmap.apple_logo_medium),
contentDescription = "Apple",
modifier = Modifier.size(36.dp),
colorFilter = ColorFilter.tint(if (AppState.darkMode) Color.White else Color.Black)
)
},
expandText = true,
contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp)
) {
}
//登录tab
Spacer(modifier = Modifier.height(24.dp))
Text(

View File

@@ -211,7 +211,7 @@ fun SignupScreen() {
)
Spacer(modifier = Modifier.width(8.dp))
},
text = stringResource(R.string.sign_in_with_google),
text = stringResource(R.string.sign_in_with_apple),
) {
googleLogin()

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

View File

@@ -33,7 +33,7 @@
<string name="text_hint_password">パスワードを入力してください</string>
<string name="sign_up_upper">サインアップ</string>
<string name="sign_in_with_email">メールで接続</string>
<string name="sign_in_with_google">Googleで接続</string>
<string name="sign_in_with_apple">Appleで接続</string>
<string name="back_upper">戻る</string>
<string name="text_hint_confirm_password">パスワードを再入力してください</string>
<string name="login_confirm_password_label">パスワードの確認</string>
@@ -192,6 +192,8 @@
<string name="agent_createing">作成中…</string>
<string name="agent_find">発見</string>
<string name="text_error_password_too_long">パスワードは%1$d文字を超えることはできません</string>
<string name="block">ブロック</string>
<!-- Create Bottom Sheet -->
<string name="create_title">作成</string>
@@ -227,5 +229,11 @@
<string name="tab_recommend">おすすめ</string>
<string name="tab_short_video">ショート動画</string>
<string name="tab_news">ニュース</string>
<!-- Block Confirm Dialog -->
<string name="confirm_block_user">%1$sをブロックしますか</string>
<string name="block_description_1">相手はあなたにメッセージを送信したり、あなたのプロフィールやコンテンツを見つけることができなくなります</string>
<string name="block_description_2">相手はあなたにブロックされた通知を受け取りません</string>
<string name="block_description_3">「設定」でいつでもブロックを解除できます</string>
</resources>

View File

@@ -32,7 +32,7 @@
<string name="text_hint_password">输入密码</string>
<string name="sign_up_upper">注册</string>
<string name="sign_in_with_email">使用邮箱注册</string>
<string name="sign_in_with_google">使用 Google 账号登录</string>
<string name="sign_in_with_apple">使用Apple登录</string>
<string name="back_upper">返回</string>
<string name="text_hint_confirm_password">再次输入密码</string>
<string name="login_confirm_password_label">再次输入密码</string>
@@ -127,7 +127,7 @@
<string name="index_following">关注</string>
<string name="index_hot">热门</string>
<string name="main_home">首页</string>
<string name="main_ai">智能体</string>
<string name="main_ai">AI</string>
<string name="main_message">消息</string>
<string name="main_profile">我的</string>
<string name="agent_mine">我的</string>
@@ -195,6 +195,8 @@
<string name="agent_find">发现</string>
<string name="text_error_password_too_long">密码不能超过 %1$d 个字符</string>
<string name="chatting_now">人正在热聊…</string>
<string name="block">拉黑</string>
<!-- Create Bottom Sheet -->
<string name="create_title">创建</string>
@@ -231,4 +233,10 @@
<string name="tab_short_video">短视频</string>
<string name="tab_news">新闻</string>
<!-- Block Confirm Dialog -->
<string name="confirm_block_user">确认拉黑%s</string>
<string name="block_description_1">对方将无法发消息给你,也无法找到你的主页或内容</string>
<string name="block_description_2">对方不会收到自己被你拉黑的通知</string>
<string name="block_description_3">你可以随时"设置"中取消拉黑TA</string>
</resources>

View File

@@ -32,7 +32,7 @@
<string name="text_hint_password">Enter your password</string>
<string name="sign_up_upper">Sign Up</string>
<string name="sign_in_with_email">Connect with Email</string>
<string name="sign_in_with_google">Connect with Google</string>
<string name="sign_in_with_apple">Continue with Apple</string>
<string name="back_upper">BACK</string>
<string name="text_hint_confirm_password">Enter your password again</string>
<string name="login_confirm_password_label">Confirm password</string>
@@ -125,7 +125,7 @@
<string name="index_following">Following</string>
<string name="index_hot">Hot</string>
<string name="main_home">Home</string>
<string name="main_ai">Agent</string>
<string name="main_ai">AI</string>
<string name="main_message">Message</string>
<string name="main_profile">Profile</string>
<string name="agent_mine">Mine</string>
@@ -191,6 +191,7 @@
<string name="agent_createing">Creating…</string>
<string name="agent_find">Discover</string>
<string name="text_error_password_too_long">Password cannot exceed %1$d characters</string>
<string name="block">Block</string>
<!-- Create Bottom Sheet -->
<string name="create_title">Create</string>
@@ -226,4 +227,10 @@
<string name="tab_recommend">Recommend</string>
<string name="tab_short_video">Short Video</string>
<string name="tab_news">News</string>
<!-- Block Confirm Dialog -->
<string name="confirm_block_user">Confirm block %1$s?</string>
<string name="block_description_1">They won\'t be able to send you messages or find your profile or content</string>
<string name="block_description_2">They won\'t receive a notification that you blocked them</string>
<string name="block_description_3">You can unblock them anytime in "Settings"</string>
</resources>