Merge pull request #87 from Kevinlinpr/nagisa

修复bug、暗色模式适配
This commit is contained in:
2025-11-20 23:06:53 +08:00
committed by GitHub
7 changed files with 315 additions and 253 deletions

View File

@@ -16,9 +16,11 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue 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.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.LocalAppTheme import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R import com.aiosman.ravenow.R
@@ -68,6 +70,19 @@ fun ChangePasswordScreen() {
var confirmPasswordError by remember { mutableStateOf<String?>(null) } var confirmPasswordError by remember { mutableStateOf<String?>(null) }
var passwordError by remember { mutableStateOf<String?>(null) } var passwordError by remember { mutableStateOf<String?>(null) }
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
// 暗色模式下的 hint 文本颜色
val isDarkMode = AppState.darkMode
val hintColor = if (isDarkMode) {
Color(0xFFFFFFFF).copy(alpha = 0.7f)
} else {
null // 使用默认颜色
}
val labelColor = if (isDarkMode) {
Color(0xFFFFFFFF).copy(alpha = 0.7f)
} else {
null // 使用默认颜色
}
fun validate(): Boolean { fun validate(): Boolean {
// 使用通用密码校验器校验当前密码 // 使用通用密码校验器校验当前密码
val currentPasswordValidation = PasswordValidator.validateCurrentPassword(currentPassword, context) val currentPasswordValidation = PasswordValidator.validateCurrentPassword(currentPassword, context)
@@ -112,7 +127,9 @@ fun ChangePasswordScreen() {
password = true, password = true,
label = stringResource(R.string.current_password), label = stringResource(R.string.current_password),
hint = stringResource(R.string.current_password_tip5), hint = stringResource(R.string.current_password_tip5),
error = oldPasswordError error = oldPasswordError,
customHintColor = hintColor,
customLabelColor = labelColor
) )
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
TextInputField( TextInputField(
@@ -121,7 +138,9 @@ fun ChangePasswordScreen() {
password = true, password = true,
label = stringResource(R.string.new_password), label = stringResource(R.string.new_password),
hint = stringResource(R.string.new_password), hint = stringResource(R.string.new_password),
error = passwordError error = passwordError,
customHintColor = hintColor,
customLabelColor = labelColor
) )
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
TextInputField( TextInputField(
@@ -130,7 +149,9 @@ fun ChangePasswordScreen() {
password = true, password = true,
label = stringResource(R.string.confirm_new_password_tip1), label = stringResource(R.string.confirm_new_password_tip1),
hint = stringResource(R.string.new_password_tip1), hint = stringResource(R.string.new_password_tip1),
error = confirmPasswordError error = confirmPasswordError,
customHintColor = hintColor,
customLabelColor = labelColor
) )
Spacer(modifier = Modifier.height(50.dp)) Spacer(modifier = Modifier.height(50.dp))
ActionButton( ActionButton(

View File

@@ -17,6 +17,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue 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.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@@ -50,6 +51,14 @@ fun RemoveAccountScreen() {
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val context = LocalContext.current val context = LocalContext.current
// 暗色模式下的 hint 文本颜色
val isDarkMode = AppState.darkMode
val hintColor = if (isDarkMode) {
Color(0xFFFFFFFF).copy(alpha = 0.7f)
} else {
null // 使用默认颜色
}
fun removeAccount(password: String) { fun removeAccount(password: String) {
// 使用通用密码校验器 // 使用通用密码校验器
val passwordValidation = PasswordValidator.validateCurrentPassword(password, context) val passwordValidation = PasswordValidator.validateCurrentPassword(password, context)
@@ -132,7 +141,8 @@ fun RemoveAccountScreen() {
}, },
password = true, password = true,
hint = stringResource(R.string.remove_account_password_hint), hint = stringResource(R.string.remove_account_password_hint),
error = passwordError error = passwordError,
customHintColor = hintColor
) )
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))

View File

@@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Spacer
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.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
@@ -89,26 +90,26 @@ fun AgentChatListScreen() {
.pullRefresh(state) .pullRefresh(state)
) { ) {
if (AgentChatListViewModel.agentChatList.isEmpty() && !AgentChatListViewModel.isLoading) { if (AgentChatListViewModel.agentChatList.isEmpty() && !AgentChatListViewModel.isLoading) {
// 空状态 Box(
Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp), .padding(horizontal = 16.dp),
contentAlignment = Alignment.Center
) {
// 空状态
Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.offset(y = (-40).dp)
) { ) {
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context) val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
if (isNetworkAvailable) { if (isNetworkAvailable) {
Spacer(modifier = Modifier.height(39.dp))
Image( Image(
painter = painterResource(id = R.mipmap.invalid_name_3), painter = painterResource(id = R.mipmap.invalid_name_3),
contentDescription = "null data", contentDescription = "null data",
modifier = Modifier modifier = Modifier.size(120.dp)
.width(181.dp)
.height(153.dp)
) )
Spacer(modifier = Modifier.height(9.dp)) Spacer(modifier = Modifier.height(12.dp))
Text( Text(
text = stringResource(R.string.no_one_knocked_yet), text = stringResource(R.string.no_one_knocked_yet),
color = AppColors.text, color = AppColors.text,
@@ -119,14 +120,11 @@ fun AgentChatListScreen() {
maxLines = 2, maxLines = 2,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
} } else {
else {
Spacer(modifier = Modifier.height(39.dp))
Image( Image(
painter = painterResource(id = R.mipmap.invalid_name_10), painter = painterResource(id = R.mipmap.invalid_name_10),
contentDescription = "network error", contentDescription = "network error",
modifier = Modifier modifier = Modifier.size(120.dp)
.size(181.dp)
) )
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
Text( Text(
@@ -157,6 +155,7 @@ fun AgentChatListScreen() {
) )
} }
} }
}
} else { } else {
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()

View File

@@ -217,24 +217,25 @@ fun AllChatListScreen() {
.pullRefresh(state) .pullRefresh(state)
) { ) {
if (allConversations.isEmpty() && !isLoading) { if (allConversations.isEmpty() && !isLoading) {
Column( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp), .padding(horizontal = 16.dp),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.offset(y = (-40).dp)
) { ) {
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context) val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
if (isNetworkAvailable) { if (isNetworkAvailable) {
Spacer(modifier = Modifier.height(39.dp))
Image( Image(
painter = painterResource(id = R.mipmap.invalid_name_3), painter = painterResource(id = R.mipmap.invalid_name_3),
contentDescription = "null data", contentDescription = "null data",
modifier = Modifier modifier = Modifier.size(120.dp)
.width(181.dp)
.height(153.dp)
) )
Spacer(modifier = Modifier.height(9.dp)) Spacer(modifier = Modifier.height(12.dp))
Text( Text(
text = stringResource(R.string.no_one_knocked_yet), text = stringResource(R.string.no_one_knocked_yet),
color = AppColors.text, color = AppColors.text,
@@ -246,12 +247,10 @@ fun AllChatListScreen() {
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
} else { } else {
Spacer(modifier = Modifier.height(39.dp))
Image( Image(
painter = painterResource(id = R.mipmap.invalid_name_10), painter = painterResource(id = R.mipmap.invalid_name_10),
contentDescription = "network error", contentDescription = "network error",
modifier = Modifier modifier = Modifier.size(120.dp)
.size(181.dp)
) )
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
Text( Text(
@@ -286,6 +285,7 @@ fun AllChatListScreen() {
) )
} }
} }
}
} else { } else {
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()

View File

@@ -72,25 +72,25 @@ fun FriendChatListScreen() {
.pullRefresh(state) .pullRefresh(state)
) { ) {
if (FriendChatListViewModel.friendChatList.isEmpty() && !FriendChatListViewModel.isLoading) { if (FriendChatListViewModel.friendChatList.isEmpty() && !FriendChatListViewModel.isLoading) {
Column( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp), .padding(horizontal = 16.dp),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
//verticalArrangement = Arrangement.Center modifier = Modifier.offset(y = (-40).dp)
) { ) {
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context) val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
if (isNetworkAvailable) { if (isNetworkAvailable) {
Spacer(modifier = Modifier.height(39.dp))
Image( Image(
painter = painterResource(id = R.mipmap.invalid_name_3), painter = painterResource(id = R.mipmap.invalid_name_3),
contentDescription = "null data", contentDescription = "null data",
modifier = Modifier modifier = Modifier.size(120.dp)
.width(181.dp)
.height(153.dp)
) )
Spacer(modifier = Modifier.height(9.dp)) Spacer(modifier = Modifier.height(12.dp))
Text( Text(
text = stringResource(R.string.no_one_knocked_yet), text = stringResource(R.string.no_one_knocked_yet),
color = AppColors.text, color = AppColors.text,
@@ -101,13 +101,11 @@ fun FriendChatListScreen() {
maxLines = 2, maxLines = 2,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
}else { } else {
Spacer(modifier = Modifier.height(39.dp))
Image( Image(
painter = painterResource(id = R.mipmap.invalid_name_10), painter = painterResource(id = R.mipmap.invalid_name_10),
contentDescription = "network error", contentDescription = "network error",
modifier = Modifier modifier = Modifier.size(120.dp)
.size(181.dp)
) )
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
Text( Text(
@@ -138,6 +136,7 @@ fun FriendChatListScreen() {
) )
} }
} }
}
} else { } else {
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()

View File

@@ -67,24 +67,25 @@ fun GroupChatListScreen() {
.pullRefresh(state) .pullRefresh(state)
) { ) {
if (GroupChatListViewModel.groupChatList.isEmpty() && !GroupChatListViewModel.isLoading) { if (GroupChatListViewModel.groupChatList.isEmpty() && !GroupChatListViewModel.isLoading) {
Column( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp), .padding(horizontal = 16.dp),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.offset(y = (-40).dp)
) { ) {
val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context) val isNetworkAvailable = NetworkUtils.isNetworkAvailable(context)
if (isNetworkAvailable) { if (isNetworkAvailable) {
Spacer(modifier = Modifier.height(39.dp))
Image( Image(
painter = painterResource(id = R.mipmap.invalid_name_3), painter = painterResource(id = R.mipmap.invalid_name_3),
contentDescription = "null data", contentDescription = "null data",
modifier = Modifier modifier = Modifier.size(120.dp)
.width(181.dp)
.height(153.dp)
) )
Spacer(modifier = Modifier.height(9.dp)) Spacer(modifier = Modifier.height(12.dp))
Text( Text(
text = stringResource(R.string.no_one_knocked_yet), text = stringResource(R.string.no_one_knocked_yet),
color = AppColors.text, color = AppColors.text,
@@ -95,13 +96,11 @@ fun GroupChatListScreen() {
maxLines = 2, maxLines = 2,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
}else { } else {
Spacer(modifier = Modifier.height(39.dp))
Image( Image(
painter = painterResource(id = R.mipmap.invalid_name_10), painter = painterResource(id = R.mipmap.invalid_name_10),
contentDescription = "network error", contentDescription = "network error",
modifier = Modifier modifier = Modifier.size(120.dp)
.size(181.dp)
) )
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
Text( Text(
@@ -132,6 +131,7 @@ fun GroupChatListScreen() {
) )
} }
} }
}
} else { } else {
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()

View File

@@ -19,6 +19,8 @@ import com.aiosman.ravenow.entity.MomentEntity
import com.aiosman.ravenow.entity.MomentPagingSource import com.aiosman.ravenow.entity.MomentPagingSource
import com.aiosman.ravenow.entity.MomentRemoteDataSource import com.aiosman.ravenow.entity.MomentRemoteDataSource
import com.aiosman.ravenow.entity.MomentServiceImpl import com.aiosman.ravenow.entity.MomentServiceImpl
import com.aiosman.ravenow.event.MomentFavouriteChangeEvent
import com.aiosman.ravenow.event.MomentLikeChangeEvent
import com.aiosman.ravenow.entity.AgentEntity import com.aiosman.ravenow.entity.AgentEntity
import com.aiosman.ravenow.entity.AgentRemoteDataSource import com.aiosman.ravenow.entity.AgentRemoteDataSource
import com.aiosman.ravenow.entity.AgentSearchPagingSource import com.aiosman.ravenow.entity.AgentSearchPagingSource
@@ -31,6 +33,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
object SearchViewModel : ViewModel() { object SearchViewModel : ViewModel() {
var searchText by mutableStateOf("") var searchText by mutableStateOf("")
@@ -204,7 +207,14 @@ object SearchViewModel : ViewModel() {
suspend fun likeMoment(id: Int) { suspend fun likeMoment(id: Int) {
try { try {
momentService.likeMoment(id) momentService.likeMoment(id)
updateMomentLike(id, true) val likeCount = updateMomentLike(id, true)
EventBus.getDefault().post(
MomentLikeChangeEvent(
postId = id,
likeCount = likeCount,
isLike = true
)
)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
@@ -213,7 +223,14 @@ object SearchViewModel : ViewModel() {
suspend fun dislikeMoment(id: Int) { suspend fun dislikeMoment(id: Int) {
try { try {
momentService.dislikeMoment(id) momentService.dislikeMoment(id)
updateMomentLike(id, false) val likeCount = updateMomentLike(id, false)
EventBus.getDefault().post(
MomentLikeChangeEvent(
postId = id,
likeCount = likeCount,
isLike = false
)
)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
@@ -223,6 +240,12 @@ object SearchViewModel : ViewModel() {
try { try {
momentService.favoriteMoment(id) momentService.favoriteMoment(id)
updateMomentFavorite(id, true) updateMomentFavorite(id, true)
EventBus.getDefault().post(
MomentFavouriteChangeEvent(
postId = id,
isFavourite = true
)
)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
@@ -232,6 +255,12 @@ object SearchViewModel : ViewModel() {
try { try {
momentService.unfavoriteMoment(id) momentService.unfavoriteMoment(id)
updateMomentFavorite(id, false) updateMomentFavorite(id, false)
EventBus.getDefault().post(
MomentFavouriteChangeEvent(
postId = id,
isFavourite = false
)
)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
@@ -241,19 +270,23 @@ object SearchViewModel : ViewModel() {
updateMomentCommentCount(id, 1) updateMomentCommentCount(id, 1)
} }
private fun updateMomentLike(id: Int, isLike: Boolean) { private fun updateMomentLike(id: Int, isLike: Boolean): Int? {
var latestLikeCount: Int? = null
val currentPagingData = _momentsFlow.value val currentPagingData = _momentsFlow.value
val updatedPagingData = currentPagingData.map { momentItem -> val updatedPagingData = currentPagingData.map { momentItem ->
if (momentItem.id == id) { if (momentItem.id == id) {
val nextCount = (momentItem.likeCount + if (isLike) 1 else -1).coerceAtLeast(0)
latestLikeCount = nextCount
momentItem.copy( momentItem.copy(
liked = isLike, liked = isLike,
likeCount = momentItem.likeCount + if (isLike) 1 else -1 likeCount = nextCount
) )
} else { } else {
momentItem momentItem
} }
} }
_momentsFlow.value = updatedPagingData _momentsFlow.value = updatedPagingData
return latestLikeCount
} }
private fun updateMomentFavorite(id: Int, isFavorite: Boolean) { private fun updateMomentFavorite(id: Int, isFavorite: Boolean) {
@@ -262,7 +295,7 @@ object SearchViewModel : ViewModel() {
if (momentItem.id == id) { if (momentItem.id == id) {
momentItem.copy( momentItem.copy(
isFavorite = isFavorite, isFavorite = isFavorite,
favoriteCount = momentItem.favoriteCount + if (isFavorite) 1 else -1 favoriteCount = (momentItem.favoriteCount + if (isFavorite) 1 else -1).coerceAtLeast(0)
) )
} else { } else {
momentItem momentItem