我的(侧边栏)ui调整

This commit is contained in:
2025-11-06 21:23:51 +08:00
parent f90bfbfa0f
commit 703beb8d43
89 changed files with 398 additions and 146 deletions

View File

@@ -1,6 +1,12 @@
package com.aiosman.ravenow.ui.index
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.foundation.ExperimentalFoundationApi
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.Spacer
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
@@ -42,8 +54,10 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
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.GuestLoginCheckOut
import com.aiosman.ravenow.GuestLoginCheckOutScene
@@ -123,151 +141,16 @@ fun IndexScreen() {
gesturesEnabled = drawerState.isOpen,
drawerContent = {
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
Column(
modifier = Modifier
.requiredWidth(250.dp)
.fillMaxHeight()
.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)
}
SideMenuContent(
onClose = {
coroutineScope.launch {
drawerState.close()
}
)
Spacer(modifier = Modifier.height(16.dp))
NavItem(
iconRes = R.drawable.rider_pro_favourited,
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)
}
}
)
}
},
navController = navController,
context = context,
isDrawerOpen = drawerState.isOpen
)
}
}
) {
@@ -447,7 +330,6 @@ fun IndexScreen() {
)
}
}
}
@Composable
@@ -623,4 +505,344 @@ 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))
)
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -248,5 +248,19 @@
<string name="select_apply_to_use_theme">「適用」を選択してこのテーマを使用</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>

View File

@@ -75,7 +75,7 @@
<string name="download">下载</string>
<string name="original">原始图片</string>
<string name="favourites">收藏</string>
<string name="dark_mode">模式</string>
<string name="dark_mode">模式</string>
<string name="light_mode">明亮模式</string>
<string name="update_find_new_version">发现新版本</string>
<string name="update_update_now">立即更新</string>
@@ -257,4 +257,12 @@
<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>

View File

@@ -254,4 +254,12 @@
<string name="choose_mbti">Choose MBTI</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>