聊天自定义背景实现

This commit is contained in:
2025-10-31 16:41:39 +08:00
parent d7f87c7c55
commit 4a684886fa
7 changed files with 92 additions and 26 deletions

View File

@@ -46,6 +46,7 @@ object AppState {
var enableGoogleLogin: Boolean = false
var enableChat = false
var agentCreatedSuccess by mutableStateOf(false)
var chatBackgroundUrl by mutableStateOf<String?>(null)
suspend fun initWithAccount(scope: CoroutineScope, context: Context) {
// 如果是游客模式,使用简化的初始化流程
if (AppStore.isGuest) {

View File

@@ -30,6 +30,12 @@ object AppStore {
AppState.appTheme = DarkThemeColors()
}
// load chat background
val savedBgUrl = sharedPreferences.getString("chatBackgroundUrl", null)
if (savedBgUrl != null) {
AppState.chatBackgroundUrl = savedBgUrl
}
}
suspend fun saveData() {
@@ -54,5 +60,15 @@ object AppStore {
}.apply()
}
fun saveChatBackgroundUrl(url: String?) {
sharedPreferences.edit().apply {
if (url != null) {
putString("chatBackgroundUrl", url)
} else {
remove("chatBackgroundUrl")
}
}.apply()
AppState.chatBackgroundUrl = url
}
}

View File

@@ -83,6 +83,8 @@ import com.aiosman.ravenow.ui.composables.StatusBarSpacer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.aiosman.ravenow.utils.NetworkUtils
import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.AppState
import androidx.compose.ui.layout.ContentScale
import io.openim.android.sdk.enums.MessageType
import kotlinx.coroutines.launch
import java.util.UUID
@@ -93,6 +95,7 @@ fun ChatAiScreen(userId: String) {
val navController = LocalNavController.current
val context = LocalNavController.current.context
val AppColors = LocalAppTheme.current
val chatBackgroundUrl = AppState.chatBackgroundUrl
var goToNewCount by remember { mutableStateOf(0) }
val viewModel = viewModel<ChatAiViewModel>(
key = "ChatAiViewModel_$userId",
@@ -156,14 +159,25 @@ fun ChatAiScreen(userId: String) {
}
Box(modifier = Modifier.fillMaxSize()) {
if (chatBackgroundUrl != null && chatBackgroundUrl.isNotEmpty()) {
CustomAsyncImage(
imageUrl = chatBackgroundUrl,
modifier = Modifier.fillMaxSize(),
contentDescription = "chat_background",
contentScale = ContentScale.Crop
)
}
Scaffold(
modifier = Modifier
.fillMaxSize(),
backgroundColor = Color.Transparent,
topBar = {
Column(
modifier = Modifier
.fillMaxWidth()
.background(AppColors.background)
.background(Color.Transparent)
) {
StatusBarSpacer()
Row(
@@ -222,11 +236,13 @@ fun ChatAiScreen(userId: String) {
}
},
bottomBar = {
val hasChatBackground = AppState.chatBackgroundUrl != null && AppState.chatBackgroundUrl!!.isNotEmpty()
Column(
modifier = Modifier
.fillMaxWidth()
.imePadding()
) {
if (!hasChatBackground) {
Box(
modifier = Modifier
.fillMaxWidth()
@@ -234,6 +250,7 @@ fun ChatAiScreen(userId: String) {
.background(
AppColors.decentBackground)
)
}
Spacer(modifier = Modifier.height(8.dp))
ChatAiInput(
onSendImage = {
@@ -254,7 +271,7 @@ fun ChatAiScreen(userId: String) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.background(Color.Transparent)
.padding(paddingValues)
) {
LazyColumn(
@@ -317,8 +334,7 @@ fun ChatAiScreen(userId: String) {
}
}
}
}
}
}
@@ -542,7 +558,8 @@ fun ChatAiInput(
}
Box( modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp),){
.background(Color.Transparent)
.padding(start = 16.dp, end = 16.dp, bottom = 45.dp),){
Row(
modifier = Modifier

View File

@@ -64,6 +64,7 @@ import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.SoftwareKeyboardController
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextAlign
@@ -74,6 +75,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R
import com.aiosman.ravenow.entity.ChatItem
@@ -158,14 +160,37 @@ fun ChatScreen(userId: String) {
}
Box(
modifier = Modifier
.fillMaxSize()
) {
// 背景图层
val bgUrl = AppState.chatBackgroundUrl
if (bgUrl != null) {
CustomAsyncImage(
imageUrl = bgUrl,
modifier = Modifier.fillMaxSize(),
contentDescription = "chat_background",
contentScale = ContentScale.Crop
)
} else {
// 无背景时使用主题背景色
Box(
modifier = Modifier
.fillMaxSize()
.background(AppColors.background)
)
}
Scaffold(
modifier = Modifier
.fillMaxSize(),
backgroundColor = Color.Transparent,
topBar = {
Column(
modifier = Modifier
.fillMaxWidth()
.background(AppColors.background)
.background(Color.Transparent)
) {
StatusBarSpacer()
Row(
@@ -256,7 +281,7 @@ fun ChatScreen(userId: String) {
Box(
modifier = Modifier
.fillMaxSize()
.background(AppColors.background)
.background(Color.Transparent)
.padding(paddingValues)
) {
LazyColumn(
@@ -322,6 +347,7 @@ fun ChatScreen(userId: String) {
}
}
}
@Composable
fun ChatSelfItem(item: ChatItem) {
@@ -545,7 +571,7 @@ fun ChatInput(
}
Box( modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp),){
.padding(start = 16.dp, end = 16.dp, bottom = 45.dp),){
Row(
modifier = Modifier

View File

@@ -147,7 +147,7 @@ private fun ThemePickerSheet(onClose: () -> Unit) {
color = appColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600,
modifier = Modifier.weight(1f).padding(start = 100.dp),
modifier = Modifier.weight(1f).padding(start = 90.dp),
)
IconButton(onClick = onClose) {
Icon(
@@ -338,7 +338,13 @@ private fun ThemePickerSheet(onClose: () -> Unit) {
)
)
)
.clickable { }
.clickable {
previewUrl?.let { url ->
com.aiosman.ravenow.AppStore.saveChatBackgroundUrl(url)
previewUrl = null
onClose()
}
}
.padding(vertical = 12.dp),
contentAlignment = Alignment.Center
) {

View File

@@ -276,7 +276,7 @@ fun IndexScreen() {
bottomBar = {
NavigationBar(
modifier = Modifier.height(58.dp + navigationBarHeight),
containerColor = AppColors.secondaryBackground
containerColor = AppColors.tabUnselectedBackground
) {
item.forEachIndexed { idx, it ->
val isSelected = model.tabIndex == idx

View File

@@ -891,7 +891,7 @@ fun ChatRoomCard(
Box(
modifier = modifier
.size(cardSize)
.background(AppColors.secondaryBackground, RoundedCornerShape(12.dp))
.background(AppColors.tabUnselectedBackground, RoundedCornerShape(12.dp))
.clickable(enabled = !viewModel.isJoiningRoom) {
if (!viewModel.isJoiningRoom && DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
// 加入群聊房间