我的(侧边栏)ui调整
@@ -1,6 +1,12 @@
|
|||||||
package com.aiosman.ravenow.ui.index
|
package com.aiosman.ravenow.ui.index
|
||||||
|
|
||||||
import androidx.compose.animation.animateColorAsState
|
import androidx.compose.animation.animateColorAsState
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.animation.core.FastOutLinearInEasing
|
||||||
|
import androidx.compose.animation.core.LinearOutSlowInEasing
|
||||||
|
import androidx.compose.animation.core.updateTransition
|
||||||
|
import androidx.compose.animation.core.animateFloat
|
||||||
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
@@ -11,15 +17,21 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.asPaddingValues
|
||||||
|
import androidx.compose.foundation.layout.systemBars
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
|
import androidx.compose.foundation.layout.requiredHeight
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.requiredWidth
|
import androidx.compose.foundation.layout.requiredWidth
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
@@ -42,8 +54,10 @@ import androidx.compose.runtime.CompositionLocalProvider
|
|||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
@@ -59,7 +73,11 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.LayoutDirection
|
import androidx.compose.ui.unit.LayoutDirection
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.zIndex
|
||||||
import com.aiosman.ravenow.AppState
|
import com.aiosman.ravenow.AppState
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
import com.aiosman.ravenow.AppStore
|
import com.aiosman.ravenow.AppStore
|
||||||
import com.aiosman.ravenow.GuestLoginCheckOut
|
import com.aiosman.ravenow.GuestLoginCheckOut
|
||||||
import com.aiosman.ravenow.GuestLoginCheckOutScene
|
import com.aiosman.ravenow.GuestLoginCheckOutScene
|
||||||
@@ -123,151 +141,16 @@ fun IndexScreen() {
|
|||||||
gesturesEnabled = drawerState.isOpen,
|
gesturesEnabled = drawerState.isOpen,
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
||||||
Column(
|
SideMenuContent(
|
||||||
modifier = Modifier
|
onClose = {
|
||||||
.requiredWidth(250.dp)
|
coroutineScope.launch {
|
||||||
.fillMaxHeight()
|
drawerState.close()
|
||||||
.background(
|
|
||||||
AppColors.background
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Spacer(modifier = Modifier.height(88.dp))
|
|
||||||
NavItem(
|
|
||||||
iconRes = R.drawable.rave_now_nav_account,
|
|
||||||
label = stringResource(R.string.account_and_security),
|
|
||||||
modifier = Modifier.noRippleClickable {
|
|
||||||
coroutineScope.launch {
|
|
||||||
drawerState.close()
|
|
||||||
navController.navigate(NavigationRoute.AccountSetting.route)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
},
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
navController = navController,
|
||||||
NavItem(
|
context = context,
|
||||||
iconRes = R.drawable.rider_pro_favourited,
|
isDrawerOpen = drawerState.isOpen
|
||||||
label = stringResource(R.string.favourites),
|
)
|
||||||
modifier = Modifier.noRippleClickable {
|
|
||||||
coroutineScope.launch {
|
|
||||||
drawerState.close()
|
|
||||||
navController.navigate(NavigationRoute.FavouriteList.route)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
NavItem(
|
|
||||||
iconRes = R.drawable.rave_now_nav_night,
|
|
||||||
label = stringResource(R.string.dark_mode),
|
|
||||||
rightContent = {
|
|
||||||
Switch(
|
|
||||||
checked = AppState.darkMode,
|
|
||||||
onCheckedChange = {
|
|
||||||
AppState.switchTheme()
|
|
||||||
},
|
|
||||||
|
|
||||||
colors = SwitchDefaults.colors(
|
|
||||||
checkedThumbColor = Color.White,
|
|
||||||
checkedTrackColor = AppColors.main,
|
|
||||||
uncheckedThumbColor = Color.White,
|
|
||||||
uncheckedTrackColor = AppColors.main.copy(alpha = 0.5f),
|
|
||||||
uncheckedBorderColor = Color.Transparent
|
|
||||||
),
|
|
||||||
modifier = Modifier.scale(0.8f)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
// divider
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(top = 16.dp, bottom = 16.dp, start = 16.dp, end = 16.dp)
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(1.dp)
|
|
||||||
.background(AppColors.divider)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
NavItem(
|
|
||||||
iconRes = R.drawable.rave_now_nav_about,
|
|
||||||
label = stringResource(R.string.blocked),
|
|
||||||
modifier = Modifier.noRippleClickable {
|
|
||||||
coroutineScope.launch {
|
|
||||||
drawerState.close()
|
|
||||||
navController.navigate(NavigationRoute.AboutScreen.route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
NavItem(
|
|
||||||
iconRes = R.drawable.rave_now_nav_about,
|
|
||||||
label = stringResource(R.string.feedback),
|
|
||||||
modifier = Modifier.noRippleClickable {
|
|
||||||
coroutineScope.launch {
|
|
||||||
drawerState.close()
|
|
||||||
navController.navigate(NavigationRoute.AboutScreen.route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
NavItem(
|
|
||||||
iconRes = R.drawable.rave_now_nav_about,
|
|
||||||
label = stringResource(R.string.about_rave_now),
|
|
||||||
modifier = Modifier.noRippleClickable {
|
|
||||||
coroutineScope.launch {
|
|
||||||
drawerState.close()
|
|
||||||
navController.navigate(NavigationRoute.AboutScreen.route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
// divider
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(top = 16.dp, bottom = 16.dp, start = 16.dp, end = 16.dp)
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(1.dp)
|
|
||||||
.background(AppColors.divider)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NavItem(
|
|
||||||
// iconRes = R.drawable.rave_now_nav_switch,
|
|
||||||
// label = "Switch Account"
|
|
||||||
// )
|
|
||||||
// Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
NavItem(
|
|
||||||
iconRes = R.drawable.rave_now_nav_logout,
|
|
||||||
label = stringResource(R.string.logout),
|
|
||||||
modifier = Modifier.noRippleClickable {
|
|
||||||
coroutineScope.launch {
|
|
||||||
drawerState.close()
|
|
||||||
// 只有非游客用户才需要取消注册推送设备
|
|
||||||
if (!AppStore.isGuest) {
|
|
||||||
Messaging.unregisterDevice(context)
|
|
||||||
}
|
|
||||||
AppStore.apply {
|
|
||||||
token = null
|
|
||||||
rememberMe = false
|
|
||||||
isGuest = false // 清除游客状态
|
|
||||||
saveData()
|
|
||||||
}
|
|
||||||
// 删除推送渠道
|
|
||||||
|
|
||||||
navController.navigate(NavigationRoute.Login.route) {
|
|
||||||
popUpTo(NavigationRoute.Login.route) {
|
|
||||||
inclusive = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AppState.ReloadAppState(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
@@ -447,7 +330,6 @@ fun IndexScreen() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -624,3 +506,343 @@ fun NavItem(
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SideMenuContent(
|
||||||
|
onClose: () -> Unit,
|
||||||
|
navController: androidx.navigation.NavController,
|
||||||
|
context: android.content.Context,
|
||||||
|
isDrawerOpen: Boolean
|
||||||
|
) {
|
||||||
|
val appColors = LocalAppTheme.current
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
var messageNotificationEnabled by remember { mutableStateOf(true) }
|
||||||
|
var darkModeEnabled by remember { mutableStateOf(AppState.darkMode) }
|
||||||
|
|
||||||
|
// 菜单背景色 #FAF9FB
|
||||||
|
val menuBackgroundColor = Color(0xFFFAF9FB)
|
||||||
|
// 遮罩颜色 黑色透明度0.6
|
||||||
|
val overlayColor = Color.Black.copy(alpha = 0.6f)
|
||||||
|
// 卡片背景色 白色
|
||||||
|
val cardBackgroundColor = Color.White
|
||||||
|
// 跟随系统文字颜色 #979499
|
||||||
|
val followSystemTextColor = Color(0xFF979499)
|
||||||
|
// 开关开启颜色 #7C45ED
|
||||||
|
val switchActiveColor = Color(0xFF7C45ED)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
// 左侧半透明遮罩(平滑淡入淡出)
|
||||||
|
val overlayTransition = updateTransition(targetState = isDrawerOpen, label = "overlay")
|
||||||
|
val overlayAlpha by overlayTransition.animateFloat(
|
||||||
|
transitionSpec = {
|
||||||
|
if (targetState) {
|
||||||
|
tween(durationMillis = 400, easing = LinearOutSlowInEasing)
|
||||||
|
} else {
|
||||||
|
tween(durationMillis = 300, easing = FastOutLinearInEasing)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label = "overlayAlpha"
|
||||||
|
) { open -> if (open) 0.6f else 0f }
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color.Black.copy(alpha = overlayAlpha))
|
||||||
|
)
|
||||||
|
|
||||||
|
// 右侧菜单面板
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.requiredWidth(302.dp)
|
||||||
|
.requiredHeight(874.dp)
|
||||||
|
.align(Alignment.CenterEnd)
|
||||||
|
.background(menuBackgroundColor)
|
||||||
|
) {
|
||||||
|
// 顶部状态栏间距
|
||||||
|
val statusBarHeight = WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
|
||||||
|
|
||||||
|
// 扫一扫功能入口 - 右边距离右边66pt
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
.offset(x = (-112).dp, y = 88.dp)
|
||||||
|
.noRippleClickable {
|
||||||
|
// TODO: 实现扫一扫功能
|
||||||
|
},
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// 扫一扫图标(使用现有图标或占位)
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.sao),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
colorFilter = ColorFilter.tint(Color.Black)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// 绝对定位的"扫一扫"文字:上方71.5dp,右侧66dp
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.scan_qr),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = Color.Black,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
.offset(x = (-66).dp, y = 91.5.dp)
|
||||||
|
)
|
||||||
|
// QR码图标 - 右边距离右边112dp,上边距离上边68pt
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.qr_code_icon),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(24.dp)
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
.offset(x = (-26).dp, y = 88.dp)
|
||||||
|
.noRippleClickable {
|
||||||
|
// TODO: 实现QR码功能
|
||||||
|
},
|
||||||
|
colorFilter = ColorFilter.tint(Color.Black)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 菜单选项卡片组 - 第一组卡片上方距离上方108pt(绝对定位)
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.offset(y = 128.dp) // 直接距离顶部128dp(整体下移20dp)
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
// 第一组卡片:编辑资料、账号安全、收藏
|
||||||
|
MenuCard(
|
||||||
|
backgroundColor = cardBackgroundColor,
|
||||||
|
width = 270.dp,
|
||||||
|
height = 164.dp,
|
||||||
|
items = listOf(
|
||||||
|
MenuItem(
|
||||||
|
icon = R.mipmap.icons_edited_data,
|
||||||
|
label = stringResource(R.string.edit_profile_info),
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
onClose()
|
||||||
|
navController.navigate(NavigationRoute.AccountEdit.route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
MenuItem(
|
||||||
|
icon = R.mipmap.icons_account_and_security,
|
||||||
|
label = stringResource(R.string.account_and_security),
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
onClose()
|
||||||
|
navController.navigate(NavigationRoute.AccountSetting.route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
MenuItem(
|
||||||
|
icon = R.mipmap.collect,
|
||||||
|
label = stringResource(R.string.favourites),
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
onClose()
|
||||||
|
navController.navigate(NavigationRoute.FavouriteList.route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 第二组卡片:暗色模式、消息通知
|
||||||
|
MenuCard(
|
||||||
|
backgroundColor = cardBackgroundColor,
|
||||||
|
width = 270.dp,
|
||||||
|
height = 112.dp, // 根据设计图,第二组卡片高度为112dp
|
||||||
|
items = listOf(
|
||||||
|
MenuItem(
|
||||||
|
icon = R.mipmap.icons_dark_mode,
|
||||||
|
label = stringResource(R.string.dark_mode),
|
||||||
|
rightContent = {
|
||||||
|
Switch(
|
||||||
|
checked = darkModeEnabled,
|
||||||
|
onCheckedChange = {
|
||||||
|
darkModeEnabled = it
|
||||||
|
AppState.darkMode = it
|
||||||
|
AppState.appTheme = if (it) {
|
||||||
|
com.aiosman.ravenow.DarkThemeColors()
|
||||||
|
} else {
|
||||||
|
com.aiosman.ravenow.LightThemeColors()
|
||||||
|
}
|
||||||
|
AppStore.saveDarkMode(it)
|
||||||
|
},
|
||||||
|
colors = SwitchDefaults.colors(
|
||||||
|
checkedThumbColor = Color.White,
|
||||||
|
checkedTrackColor = switchActiveColor,
|
||||||
|
uncheckedThumbColor = Color.White,
|
||||||
|
uncheckedTrackColor = switchActiveColor.copy(alpha = 0.5f),
|
||||||
|
uncheckedBorderColor = Color.Transparent
|
||||||
|
),
|
||||||
|
modifier = Modifier.size(width = 64.dp, height = 28.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
MenuItem(
|
||||||
|
icon = R.mipmap.icons_bell,
|
||||||
|
label = stringResource(R.string.message_notification),
|
||||||
|
rightContent = {
|
||||||
|
Switch(
|
||||||
|
checked = messageNotificationEnabled,
|
||||||
|
onCheckedChange = { messageNotificationEnabled = it },
|
||||||
|
colors = SwitchDefaults.colors(
|
||||||
|
checkedThumbColor = Color.White,
|
||||||
|
checkedTrackColor = switchActiveColor,
|
||||||
|
uncheckedThumbColor = Color.White,
|
||||||
|
uncheckedTrackColor = switchActiveColor.copy(alpha = 0.5f),
|
||||||
|
uncheckedBorderColor = Color.Transparent
|
||||||
|
),
|
||||||
|
modifier = Modifier.size(width = 64.dp, height = 28.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 第三组卡片:关于派派、反馈、退出登录
|
||||||
|
MenuCard(
|
||||||
|
backgroundColor = cardBackgroundColor,
|
||||||
|
width = 270.dp,
|
||||||
|
height = 164.dp,
|
||||||
|
items = listOf(
|
||||||
|
MenuItem(
|
||||||
|
icon = R.mipmap.icons_about,
|
||||||
|
label = stringResource(R.string.about_paipai),
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
onClose()
|
||||||
|
navController.navigate(NavigationRoute.AboutScreen.route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
MenuItem(
|
||||||
|
icon = R.mipmap.feedback_icon,
|
||||||
|
label = stringResource(R.string.feedback),
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
onClose()
|
||||||
|
navController.navigate(NavigationRoute.AboutScreen.route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
MenuItem(
|
||||||
|
icon = R.mipmap.log_out_icon,
|
||||||
|
label = stringResource(R.string.logout_confirm),
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
onClose()
|
||||||
|
// 只有非游客用户才需要取消注册推送设备
|
||||||
|
if (!AppStore.isGuest) {
|
||||||
|
Messaging.unregisterDevice(context)
|
||||||
|
}
|
||||||
|
AppStore.apply {
|
||||||
|
token = null
|
||||||
|
rememberMe = false
|
||||||
|
isGuest = false
|
||||||
|
saveData()
|
||||||
|
}
|
||||||
|
navController.navigate(NavigationRoute.Login.route) {
|
||||||
|
popUpTo(NavigationRoute.Login.route) {
|
||||||
|
inclusive = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AppState.ReloadAppState(context)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showRightArrow = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MenuItem(
|
||||||
|
val icon: Int,
|
||||||
|
val label: String,
|
||||||
|
val onClick: (() -> Unit)? = null,
|
||||||
|
val rightContent: @Composable (() -> Unit)? = null,
|
||||||
|
val showRightArrow: Boolean = true
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MenuCard(
|
||||||
|
backgroundColor: Color,
|
||||||
|
items: List<MenuItem>,
|
||||||
|
width: androidx.compose.ui.unit.Dp? = null,
|
||||||
|
height: androidx.compose.ui.unit.Dp? = null
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.then(if (width != null) Modifier.requiredWidth(width) else Modifier.fillMaxWidth())
|
||||||
|
.then(if (height != null) Modifier.requiredHeight(height) else Modifier)
|
||||||
|
.background(backgroundColor, RoundedCornerShape(16.dp))
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
verticalArrangement = if (height != null) Arrangement.SpaceEvenly else Arrangement.spacedBy(8.dp) // 固定高度时均匀分布
|
||||||
|
) {
|
||||||
|
items.forEachIndexed { index, item ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.then(if (height != null) Modifier.weight(1f) else Modifier),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
MenuItemRow(item = item, compact = height != null) // 传递compact参数
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MenuItemRow(item: MenuItem, compact: Boolean = false) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.then(
|
||||||
|
if (item.onClick != null) {
|
||||||
|
Modifier.noRippleClickable { item.onClick?.invoke() }
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.padding(vertical = if (compact) 4.dp else 8.dp), // 紧凑模式下减少垂直padding
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = item.icon),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
colorFilter = ColorFilter.tint(Color.Black)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = item.label,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = Color.Black
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.rightContent != null) {
|
||||||
|
item.rightContent?.invoke()
|
||||||
|
} else if (item.showRightArrow) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.rave_now_nav_right),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
colorFilter = ColorFilter.tint(Color(0xFF111213))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
app/src/main/res/mipmap-hdpi/bi.png
Normal file
|
After Width: | Height: | Size: 331 B |
BIN
app/src/main/res/mipmap-hdpi/collect.png
Normal file
|
After Width: | Height: | Size: 438 B |
BIN
app/src/main/res/mipmap-hdpi/feedback_icon.png
Normal file
|
After Width: | Height: | Size: 434 B |
BIN
app/src/main/res/mipmap-hdpi/fengm.png
Normal file
|
After Width: | Height: | Size: 331 B |
BIN
app/src/main/res/mipmap-hdpi/icons_about.png
Normal file
|
After Width: | Height: | Size: 465 B |
BIN
app/src/main/res/mipmap-hdpi/icons_account_and_security.png
Normal file
|
After Width: | Height: | Size: 390 B |
BIN
app/src/main/res/mipmap-hdpi/icons_bell.png
Normal file
|
After Width: | Height: | Size: 425 B |
BIN
app/src/main/res/mipmap-hdpi/icons_dark_mode.png
Normal file
|
After Width: | Height: | Size: 381 B |
BIN
app/src/main/res/mipmap-hdpi/icons_edited_data.png
Normal file
|
After Width: | Height: | Size: 428 B |
BIN
app/src/main/res/mipmap-hdpi/log_out_icon.png
Normal file
|
After Width: | Height: | Size: 402 B |
BIN
app/src/main/res/mipmap-hdpi/menu_ico.png
Normal file
|
After Width: | Height: | Size: 156 B |
BIN
app/src/main/res/mipmap-hdpi/menu_icon.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
app/src/main/res/mipmap-hdpi/naoz.png
Normal file
|
After Width: | Height: | Size: 551 B |
BIN
app/src/main/res/mipmap-hdpi/paip_coin_img.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-hdpi/qr_code_icon.png
Normal file
|
After Width: | Height: | Size: 490 B |
BIN
app/src/main/res/mipmap-hdpi/sao.png
Normal file
|
After Width: | Height: | Size: 367 B |
BIN
app/src/main/res/mipmap-hdpi/xingzuo.png
Normal file
|
After Width: | Height: | Size: 593 B |
BIN
app/src/main/res/mipmap-mdpi/bi.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
app/src/main/res/mipmap-mdpi/collect.png
Normal file
|
After Width: | Height: | Size: 348 B |
BIN
app/src/main/res/mipmap-mdpi/feedback_icon.png
Normal file
|
After Width: | Height: | Size: 326 B |
BIN
app/src/main/res/mipmap-mdpi/fengm.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
app/src/main/res/mipmap-mdpi/icons_about.png
Normal file
|
After Width: | Height: | Size: 347 B |
BIN
app/src/main/res/mipmap-mdpi/icons_account_and_security.png
Normal file
|
After Width: | Height: | Size: 325 B |
BIN
app/src/main/res/mipmap-mdpi/icons_bell.png
Normal file
|
After Width: | Height: | Size: 328 B |
BIN
app/src/main/res/mipmap-mdpi/icons_dark_mode.png
Normal file
|
After Width: | Height: | Size: 329 B |
BIN
app/src/main/res/mipmap-mdpi/icons_edited_data.png
Normal file
|
After Width: | Height: | Size: 361 B |
BIN
app/src/main/res/mipmap-mdpi/log_out_icon.png
Normal file
|
After Width: | Height: | Size: 301 B |
BIN
app/src/main/res/mipmap-mdpi/menu_ico.png
Normal file
|
After Width: | Height: | Size: 143 B |
BIN
app/src/main/res/mipmap-mdpi/menu_icon.png
Normal file
|
After Width: | Height: | Size: 229 B |
BIN
app/src/main/res/mipmap-mdpi/naoz.png
Normal file
|
After Width: | Height: | Size: 419 B |
BIN
app/src/main/res/mipmap-mdpi/paip_coin_img.png
Normal file
|
After Width: | Height: | Size: 873 B |
BIN
app/src/main/res/mipmap-mdpi/qr_code_icon.png
Normal file
|
After Width: | Height: | Size: 390 B |
BIN
app/src/main/res/mipmap-mdpi/sao.png
Normal file
|
After Width: | Height: | Size: 290 B |
BIN
app/src/main/res/mipmap-mdpi/xingzuo.png
Normal file
|
After Width: | Height: | Size: 473 B |
BIN
app/src/main/res/mipmap-xhdpi/bi.png
Normal file
|
After Width: | Height: | Size: 415 B |
BIN
app/src/main/res/mipmap-xhdpi/collect.png
Normal file
|
After Width: | Height: | Size: 548 B |
BIN
app/src/main/res/mipmap-xhdpi/feedback_icon.png
Normal file
|
After Width: | Height: | Size: 516 B |
BIN
app/src/main/res/mipmap-xhdpi/fengm.png
Normal file
|
After Width: | Height: | Size: 415 B |
BIN
app/src/main/res/mipmap-xhdpi/icons_about.png
Normal file
|
After Width: | Height: | Size: 552 B |
BIN
app/src/main/res/mipmap-xhdpi/icons_account_and_security.png
Normal file
|
After Width: | Height: | Size: 479 B |
BIN
app/src/main/res/mipmap-xhdpi/icons_bell.png
Normal file
|
After Width: | Height: | Size: 523 B |
BIN
app/src/main/res/mipmap-xhdpi/icons_dark_mode.png
Normal file
|
After Width: | Height: | Size: 455 B |
BIN
app/src/main/res/mipmap-xhdpi/icons_edited_data.png
Normal file
|
After Width: | Height: | Size: 544 B |
BIN
app/src/main/res/mipmap-xhdpi/log_out_icon.png
Normal file
|
After Width: | Height: | Size: 497 B |
BIN
app/src/main/res/mipmap-xhdpi/menu_ico.png
Normal file
|
After Width: | Height: | Size: 167 B |
BIN
app/src/main/res/mipmap-xhdpi/menu_icon.png
Normal file
|
After Width: | Height: | Size: 328 B |
BIN
app/src/main/res/mipmap-xhdpi/naoz.png
Normal file
|
After Width: | Height: | Size: 718 B |
BIN
app/src/main/res/mipmap-xhdpi/paip_coin_img.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/qr_code_icon.png
Normal file
|
After Width: | Height: | Size: 595 B |
BIN
app/src/main/res/mipmap-xhdpi/sao.png
Normal file
|
After Width: | Height: | Size: 421 B |
BIN
app/src/main/res/mipmap-xhdpi/xingzuo.png
Normal file
|
After Width: | Height: | Size: 705 B |
BIN
app/src/main/res/mipmap-xxhdpi/bi.png
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
app/src/main/res/mipmap-xxhdpi/collect.png
Normal file
|
After Width: | Height: | Size: 779 B |
BIN
app/src/main/res/mipmap-xxhdpi/feedback_icon.png
Normal file
|
After Width: | Height: | Size: 685 B |
BIN
app/src/main/res/mipmap-xxhdpi/fengm.png
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
app/src/main/res/mipmap-xxhdpi/icons_about.png
Normal file
|
After Width: | Height: | Size: 787 B |
BIN
app/src/main/res/mipmap-xxhdpi/icons_account_and_security.png
Normal file
|
After Width: | Height: | Size: 656 B |
BIN
app/src/main/res/mipmap-xxhdpi/icons_bell.png
Normal file
|
After Width: | Height: | Size: 687 B |
BIN
app/src/main/res/mipmap-xxhdpi/icons_dark_mode.png
Normal file
|
After Width: | Height: | Size: 613 B |
BIN
app/src/main/res/mipmap-xxhdpi/icons_edited_data.png
Normal file
|
After Width: | Height: | Size: 746 B |
BIN
app/src/main/res/mipmap-xxhdpi/log_out_icon.png
Normal file
|
After Width: | Height: | Size: 652 B |
BIN
app/src/main/res/mipmap-xxhdpi/menu_ico.png
Normal file
|
After Width: | Height: | Size: 171 B |
BIN
app/src/main/res/mipmap-xxhdpi/menu_icon.png
Normal file
|
After Width: | Height: | Size: 418 B |
BIN
app/src/main/res/mipmap-xxhdpi/naoz.png
Normal file
|
After Width: | Height: | Size: 980 B |
BIN
app/src/main/res/mipmap-xxhdpi/paip_coin_img.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/qr_code_icon.png
Normal file
|
After Width: | Height: | Size: 786 B |
BIN
app/src/main/res/mipmap-xxhdpi/sao.png
Normal file
|
After Width: | Height: | Size: 597 B |
BIN
app/src/main/res/mipmap-xxhdpi/xingzuo.png
Normal file
|
After Width: | Height: | Size: 992 B |
BIN
app/src/main/res/mipmap-xxxhdpi/bi.png
Normal file
|
After Width: | Height: | Size: 688 B |
BIN
app/src/main/res/mipmap-xxxhdpi/collect.png
Normal file
|
After Width: | Height: | Size: 952 B |
BIN
app/src/main/res/mipmap-xxxhdpi/feedback_icon.png
Normal file
|
After Width: | Height: | Size: 828 B |
BIN
app/src/main/res/mipmap-xxxhdpi/fengm.png
Normal file
|
After Width: | Height: | Size: 688 B |
BIN
app/src/main/res/mipmap-xxxhdpi/icons_about.png
Normal file
|
After Width: | Height: | Size: 1009 B |
BIN
app/src/main/res/mipmap-xxxhdpi/icons_account_and_security.png
Normal file
|
After Width: | Height: | Size: 766 B |
BIN
app/src/main/res/mipmap-xxxhdpi/icons_bell.png
Normal file
|
After Width: | Height: | Size: 877 B |
BIN
app/src/main/res/mipmap-xxxhdpi/icons_dark_mode.png
Normal file
|
After Width: | Height: | Size: 794 B |
BIN
app/src/main/res/mipmap-xxxhdpi/icons_edited_data.png
Normal file
|
After Width: | Height: | Size: 923 B |
BIN
app/src/main/res/mipmap-xxxhdpi/log_out_icon.png
Normal file
|
After Width: | Height: | Size: 812 B |
BIN
app/src/main/res/mipmap-xxxhdpi/menu_ico.png
Normal file
|
After Width: | Height: | Size: 216 B |
BIN
app/src/main/res/mipmap-xxxhdpi/menu_icon.png
Normal file
|
After Width: | Height: | Size: 482 B |
BIN
app/src/main/res/mipmap-xxxhdpi/naoz.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/paip_coin_img.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/qr_code_icon.png
Normal file
|
After Width: | Height: | Size: 1014 B |
BIN
app/src/main/res/mipmap-xxxhdpi/sao.png
Normal file
|
After Width: | Height: | Size: 725 B |
BIN
app/src/main/res/mipmap-xxxhdpi/xingzuo.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
@@ -248,5 +248,19 @@
|
|||||||
<string name="select_apply_to_use_theme">「適用」を選択してこのテーマを使用</string>
|
<string name="select_apply_to_use_theme">「適用」を選択してこのテーマを使用</string>
|
||||||
<string name="tap_cancel_to_preview_other_themes">「キャンセル」をタップして他のテーマをプレビュー</string>
|
<string name="tap_cancel_to_preview_other_themes">「キャンセル」をタップして他のテーマをプレビュー</string>
|
||||||
|
|
||||||
|
<!-- Edit Profile Extras -->
|
||||||
|
<string name="mbti_type">MBTIタイプ</string>
|
||||||
|
<string name="zodiac">星座</string>
|
||||||
|
<string name="save">保存</string>
|
||||||
|
<string name="choose_mbti">MBTIを選択</string>
|
||||||
|
<string name="choose_zodiac">星座を選択</string>
|
||||||
|
|
||||||
|
<!-- Side Menu -->
|
||||||
|
<string name="scan_qr">さっと動かす</string>
|
||||||
|
<string name="edit_profile_info">データの編集</string>
|
||||||
|
<string name="about_paipai">パイパイについて</string>
|
||||||
|
<string name="follow_system">フォローアップシステム</string>
|
||||||
|
<string name="message_notification">メッセージ通知</string>
|
||||||
|
<string name="logout_confirm">ログアウト</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
<string name="download">下载</string>
|
<string name="download">下载</string>
|
||||||
<string name="original">原始图片</string>
|
<string name="original">原始图片</string>
|
||||||
<string name="favourites">收藏</string>
|
<string name="favourites">收藏</string>
|
||||||
<string name="dark_mode">暗黑模式</string>
|
<string name="dark_mode">暗色模式</string>
|
||||||
<string name="light_mode">明亮模式</string>
|
<string name="light_mode">明亮模式</string>
|
||||||
<string name="update_find_new_version">发现新版本</string>
|
<string name="update_find_new_version">发现新版本</string>
|
||||||
<string name="update_update_now">立即更新</string>
|
<string name="update_update_now">立即更新</string>
|
||||||
@@ -257,4 +257,12 @@
|
|||||||
<string name="save">保存</string>
|
<string name="save">保存</string>
|
||||||
<string name="choose_mbti">选择 MBTI</string>
|
<string name="choose_mbti">选择 MBTI</string>
|
||||||
<string name="choose_zodiac">选择星座</string>
|
<string name="choose_zodiac">选择星座</string>
|
||||||
|
|
||||||
|
<!-- Side Menu -->
|
||||||
|
<string name="scan_qr">扫一扫</string>
|
||||||
|
<string name="edit_profile_info">编辑资料</string>
|
||||||
|
<string name="about_paipai">关于派派</string>
|
||||||
|
<string name="follow_system">跟随系统</string>
|
||||||
|
<string name="message_notification">消息通知</string>
|
||||||
|
<string name="logout_confirm">退出登录</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -254,4 +254,12 @@
|
|||||||
<string name="choose_mbti">Choose MBTI</string>
|
<string name="choose_mbti">Choose MBTI</string>
|
||||||
<string name="choose_zodiac">Choose Zodiac</string>
|
<string name="choose_zodiac">Choose Zodiac</string>
|
||||||
|
|
||||||
|
<!-- Side Menu -->
|
||||||
|
<string name="scan_qr">Scan QR</string>
|
||||||
|
<string name="edit_profile_info">Edit Profile</string>
|
||||||
|
<string name="about_paipai">About Paipai</string>
|
||||||
|
<string name="follow_system">Follow System</string>
|
||||||
|
<string name="message_notification">Message Notification</string>
|
||||||
|
<string name="logout_confirm">Logout</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||