mirror of
http://180.163.74.83:13000/zhangzhenghao/MPVN_Android.git
synced 2025-12-12 15:24:30 +00:00
优化
This commit is contained in:
parent
238958f3d2
commit
fb20e2e64b
@ -74,6 +74,7 @@ dependencies {
|
|||||||
|
|
||||||
// ZXing 二维码生成
|
// ZXing 二维码生成
|
||||||
implementation("com.google.zxing:core:3.5.2")
|
implementation("com.google.zxing:core:3.5.2")
|
||||||
|
|
||||||
|
|
||||||
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.12")
|
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.12")
|
||||||
|
|
||||||
|
|||||||
@ -134,7 +134,7 @@ fun MainContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var selectedRoom by remember { mutableStateOf(0) }
|
var selectedRoom by remember { mutableStateOf(0) }
|
||||||
var selectedNavItem by remember { mutableStateOf(0) } // 0=控制台, 5=设置
|
var selectedNavItem by remember { mutableStateOf(0) }
|
||||||
var rooms by remember { mutableStateOf(savedRooms) }
|
var rooms by remember { mutableStateOf(savedRooms) }
|
||||||
|
|
||||||
// 保存房间列表到SharedPreferences
|
// 保存房间列表到SharedPreferences
|
||||||
@ -170,26 +170,29 @@ fun MainContent() {
|
|||||||
.background(Color(overlayAlpha shl 24 or 0x121212))
|
.background(Color(overlayAlpha shl 24 or 0x121212))
|
||||||
)
|
)
|
||||||
|
|
||||||
// 主内容 - 添加系统栏内边距
|
// 主内容 - 全屏显示
|
||||||
Box(modifier = Modifier.fillMaxSize().systemBarsPadding()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
MainScaffold(
|
MainScaffold(
|
||||||
selectedRoom = selectedRoom,
|
selectedRoom = selectedRoom,
|
||||||
onRoomSelect = { selectedRoom = it },
|
onRoomSelect = { selectedRoom = it },
|
||||||
selectedNavItem = selectedNavItem,
|
selectedNavItem = selectedNavItem,
|
||||||
onNavItemSelect = { selectedNavItem = it },
|
onNavItemSelect = { selectedNavItem = it },
|
||||||
rooms = rooms,
|
rooms = rooms,
|
||||||
onAddRoom = { newRoomName ->
|
onAddRoom = { newRoomName ->
|
||||||
saveRooms(rooms + newRoomName)
|
saveRooms(rooms + newRoomName)
|
||||||
},
|
},
|
||||||
onDeleteRoom = { index ->
|
onDeleteRoom = { index ->
|
||||||
if (rooms.size > 1) { // 至少保留一个房间
|
if (rooms.size > 1) { // 至少保留一个房间
|
||||||
saveRooms(rooms.filterIndexed { i, _ -> i != index })
|
saveRooms(rooms.filterIndexed { i, _ -> i != index })
|
||||||
if (selectedRoom >= rooms.size - 1) {
|
if (selectedRoom >= rooms.size - 1) {
|
||||||
selectedRoom = (rooms.size - 2).coerceAtLeast(0)
|
selectedRoom = (rooms.size - 2).coerceAtLeast(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onRenameRoom = { index, newName ->
|
||||||
|
saveRooms(rooms.mapIndexed { i, name -> if (i == index) newName else name })
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import com.example.smarthome.data.LanguageManager
|
|||||||
import com.example.smarthome.data.tr
|
import com.example.smarthome.data.tr
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import android.view.SoundEffectConstants
|
import android.view.SoundEffectConstants
|
||||||
@ -47,6 +48,7 @@ import androidx.compose.foundation.gestures.detectHorizontalDragGestures
|
|||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.foundation.layout.offset
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainScaffold(
|
fun MainScaffold(
|
||||||
@ -56,27 +58,34 @@ fun MainScaffold(
|
|||||||
onNavItemSelect: (Int) -> Unit = {},
|
onNavItemSelect: (Int) -> Unit = {},
|
||||||
rooms: List<String> = listOf("总览", "客厅", "厨房", "卧室", "影音室", "游戏房"),
|
rooms: List<String> = listOf("总览", "客厅", "厨房", "卧室", "影音室", "游戏房"),
|
||||||
onAddRoom: (String) -> Unit = {},
|
onAddRoom: (String) -> Unit = {},
|
||||||
onDeleteRoom: (Int) -> Unit = {}
|
onDeleteRoom: (Int) -> Unit = {},
|
||||||
|
onRenameRoom: (Int, String) -> Unit = { _, _ -> }
|
||||||
) {
|
) {
|
||||||
Row(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
SideNavRail(
|
// 内容区域 - 全屏显示
|
||||||
selectedNavItem = selectedNavItem,
|
Box(
|
||||||
onNavItemSelect = onNavItemSelect
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
) {
|
||||||
|
|
||||||
// 内容区域 - 减少左侧间距
|
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
|
||||||
// 根据选中的导航项显示不同的内容
|
// 根据选中的导航项显示不同的内容
|
||||||
|
// 底部导航: 0-Dashboard, 1-Scene, 2-Automation, 3-Security, 4-Settings
|
||||||
when (selectedNavItem) {
|
when (selectedNavItem) {
|
||||||
0 -> DashboardContent(selectedRoom, onRoomSelect, rooms, onAddRoom, onDeleteRoom)
|
0 -> DashboardContent(selectedRoom, onRoomSelect, rooms, onAddRoom, onDeleteRoom, onRenameRoom)
|
||||||
1 -> SceneScreen()
|
1 -> SceneScreen()
|
||||||
2 -> AutomationScreen()
|
2 -> AutomationScreen()
|
||||||
3 -> StatisticsScreen()
|
3 -> SecurityScreen()
|
||||||
4 -> SecurityScreen()
|
4 -> SettingsContent()
|
||||||
5 -> SettingsContent()
|
else -> DashboardContent(selectedRoom, onRoomSelect, rooms, onAddRoom, onDeleteRoom, onRenameRoom)
|
||||||
else -> DashboardContent(selectedRoom, onRoomSelect, rooms, onAddRoom, onDeleteRoom)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 底部悬浮导航栏 - 置于内容之上
|
||||||
|
FloatingBottomNav(
|
||||||
|
selectedNavItem = selectedNavItem,
|
||||||
|
onNavItemSelect = onNavItemSelect,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomCenter)
|
||||||
|
.padding(bottom = 24.dp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,23 +95,33 @@ fun DashboardContent(
|
|||||||
onRoomSelect: (Int) -> Unit,
|
onRoomSelect: (Int) -> Unit,
|
||||||
rooms: List<String> = listOf("总览", "客厅", "厨房", "卧室", "影音室", "游戏房"),
|
rooms: List<String> = listOf("总览", "客厅", "厨房", "卧室", "影音室", "游戏房"),
|
||||||
onAddRoom: (String) -> Unit = {},
|
onAddRoom: (String) -> Unit = {},
|
||||||
onDeleteRoom: (Int) -> Unit = {}
|
onDeleteRoom: (Int) -> Unit = {},
|
||||||
|
onRenameRoom: (Int, String) -> Unit = { _, _ -> }
|
||||||
) {
|
) {
|
||||||
var showAddRoomDialog by remember { mutableStateOf(false) }
|
var showAddRoomDialog by remember { mutableStateOf(false) }
|
||||||
var editMode by remember { mutableStateOf(false) }
|
|
||||||
|
// 总览和客厅使用默认壁纸
|
||||||
|
val roomName = rooms.getOrNull(selectedRoom) ?: "总览"
|
||||||
|
val hasWallpaper = selectedRoom == 0 || roomName == "客厅"
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.pointerInput(editMode) {
|
|
||||||
if (editMode) {
|
|
||||||
detectTapGestures(
|
|
||||||
onTap = { editMode = false }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.fillMaxSize().padding(start = 0.dp, end = 16.dp, top = 16.dp, bottom = 16.dp)) {
|
// 房间壁纸背景(总览和客厅)- 放在最底层
|
||||||
|
if (hasWallpaper) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.room_wallpaper_default),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.clip(RoundedCornerShape(24.dp)),
|
||||||
|
contentScale = ContentScale.Crop,
|
||||||
|
alpha = 0.25f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 16.dp, vertical = 16.dp)) {
|
||||||
TopBar()
|
TopBar()
|
||||||
RoomTabs(
|
RoomTabs(
|
||||||
selectedRoom = selectedRoom,
|
selectedRoom = selectedRoom,
|
||||||
@ -110,11 +129,10 @@ fun DashboardContent(
|
|||||||
rooms = rooms,
|
rooms = rooms,
|
||||||
onAddRoomClick = { showAddRoomDialog = true },
|
onAddRoomClick = { showAddRoomDialog = true },
|
||||||
onDeleteRoom = onDeleteRoom,
|
onDeleteRoom = onDeleteRoom,
|
||||||
editMode = editMode,
|
onRenameRoom = onRenameRoom
|
||||||
onEditModeChange = { editMode = it }
|
|
||||||
)
|
)
|
||||||
// 根据选中的房间显示不同的内容
|
// 根据选中的房间显示不同的内容
|
||||||
RoomContent(selectedRoom = selectedRoom, roomName = rooms.getOrNull(selectedRoom) ?: "总览")
|
RoomContent(selectedRoom = selectedRoom, roomName = roomName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showAddRoomDialog) {
|
if (showAddRoomDialog) {
|
||||||
@ -288,9 +306,11 @@ fun RoomTabs(
|
|||||||
rooms: List<String> = listOf("总览", "客厅", "厨房", "卧室", "影音室", "游戏房"),
|
rooms: List<String> = listOf("总览", "客厅", "厨房", "卧室", "影音室", "游戏房"),
|
||||||
onAddRoomClick: () -> Unit = {},
|
onAddRoomClick: () -> Unit = {},
|
||||||
onDeleteRoom: (Int) -> Unit = {},
|
onDeleteRoom: (Int) -> Unit = {},
|
||||||
editMode: Boolean = false,
|
onRenameRoom: (Int, String) -> Unit = { _, _ -> }
|
||||||
onEditModeChange: (Boolean) -> Unit = {}
|
|
||||||
) {
|
) {
|
||||||
|
// 编辑房间对话框状态
|
||||||
|
var showEditRoomsDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -308,24 +328,40 @@ fun RoomTabs(
|
|||||||
RoomTab(
|
RoomTab(
|
||||||
name = name,
|
name = name,
|
||||||
selected = index == selectedRoom,
|
selected = index == selectedRoom,
|
||||||
editMode = editMode,
|
onClick = { onRoomSelect(index) }
|
||||||
canDelete = rooms.size > 1,
|
|
||||||
onClick = {
|
|
||||||
if (!editMode) {
|
|
||||||
onRoomSelect(index)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onLongClick = { onEditModeChange(true) },
|
|
||||||
onDelete = {
|
|
||||||
onDeleteRoom(index)
|
|
||||||
onEditModeChange(false)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 固定的添加按钮
|
// 编辑按钮
|
||||||
GradientButton("+ 添加房间", onClick = onAddRoomClick)
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(44.dp)
|
||||||
|
.clip(RoundedCornerShape(12.dp))
|
||||||
|
.background(Color(0xFF2A2A3E))
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = Color(0xFF3A3A4E),
|
||||||
|
shape = RoundedCornerShape(12.dp)
|
||||||
|
)
|
||||||
|
.clickable { showEditRoomsDialog = true },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "✏️", fontSize = 18.sp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加按钮
|
||||||
|
GradientButton("+ 添加", onClick = onAddRoomClick)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑房间对话框
|
||||||
|
if (showEditRoomsDialog) {
|
||||||
|
EditRoomsDialog(
|
||||||
|
rooms = rooms,
|
||||||
|
onDismiss = { showEditRoomsDialog = false },
|
||||||
|
onRenameRoom = onRenameRoom,
|
||||||
|
onDeleteRoom = onDeleteRoom
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,98 +369,25 @@ fun RoomTabs(
|
|||||||
fun RoomTab(
|
fun RoomTab(
|
||||||
name: String,
|
name: String,
|
||||||
selected: Boolean,
|
selected: Boolean,
|
||||||
editMode: Boolean,
|
onClick: () -> Unit
|
||||||
canDelete: Boolean,
|
|
||||||
onClick: () -> Unit,
|
|
||||||
onLongClick: () -> Unit,
|
|
||||||
onDelete: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val base = Modifier.clip(RoundedCornerShape(20.dp))
|
||||||
|
val mod = if (selected) {
|
||||||
// 改进的晃动动画 - 使用无限循环的旋转动画
|
base.background(brush = Brush.linearGradient(listOf(Color(0xFFA9F0FF), Color(0xFFB89CFF))))
|
||||||
val infiniteTransition = rememberInfiniteTransition(label = "shake")
|
} else {
|
||||||
val rotation by infiniteTransition.animateFloat(
|
base.background(color = Color(0x50121212))
|
||||||
initialValue = -3f,
|
}
|
||||||
targetValue = 3f,
|
|
||||||
animationSpec = infiniteRepeatable(
|
|
||||||
animation = tween(150, easing = LinearEasing),
|
|
||||||
repeatMode = RepeatMode.Reverse
|
|
||||||
),
|
|
||||||
label = "rotation"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 缩放动画
|
|
||||||
val scale by androidx.compose.animation.core.animateFloatAsState(
|
|
||||||
targetValue = if (editMode && canDelete) 0.95f else 1f,
|
|
||||||
animationSpec = androidx.compose.animation.core.spring(
|
|
||||||
dampingRatio = androidx.compose.animation.core.Spring.DampingRatioMediumBouncy,
|
|
||||||
stiffness = androidx.compose.animation.core.Spring.StiffnessLow
|
|
||||||
),
|
|
||||||
label = "scale"
|
|
||||||
)
|
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = mod
|
||||||
.scale(scale)
|
.clickable { onClick() }
|
||||||
.then(
|
.padding(horizontal = 14.dp, vertical = 10.dp)
|
||||||
if (editMode && canDelete) {
|
|
||||||
Modifier.rotate(rotation)
|
|
||||||
} else {
|
|
||||||
Modifier
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.pointerInput(Unit) {
|
|
||||||
detectTapGestures(
|
|
||||||
onTap = { onClick() },
|
|
||||||
onLongPress = {
|
|
||||||
if (canDelete) {
|
|
||||||
onLongClick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
val base = Modifier.clip(RoundedCornerShape(20.dp))
|
Text(
|
||||||
val mod = if (selected) {
|
text = name,
|
||||||
base.background(brush = Brush.linearGradient(listOf(Color(0xFFA9F0FF), Color(0xFFB89CFF))))
|
color = if (selected) Color.Black else Color(0xFFB0B0B0),
|
||||||
} else {
|
maxLines = 1
|
||||||
base.background(color = Color(0x50121212))
|
)
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = mod.padding(horizontal = 14.dp, vertical = 10.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = name,
|
|
||||||
color = if (selected) Color.Black else Color(0xFFB0B0B0),
|
|
||||||
maxLines = 1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除按钮
|
|
||||||
if (editMode && canDelete) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.size(22.dp)
|
|
||||||
.offset(x = (-4).dp, y = (-4).dp)
|
|
||||||
.align(Alignment.TopEnd)
|
|
||||||
.shadow(4.dp, RoundedCornerShape(11.dp))
|
|
||||||
.clip(RoundedCornerShape(11.dp))
|
|
||||||
.background(Color(0xFFFF5252))
|
|
||||||
.clickable(
|
|
||||||
indication = null,
|
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
|
||||||
) { onDelete() },
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "×",
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = 18.sp,
|
|
||||||
fontWeight = FontWeight.Bold
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,6 +536,177 @@ fun NavItem(title: String, selected: Boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 底部悬浮导航栏 - 带液态玻璃滑动效果
|
||||||
|
@Composable
|
||||||
|
fun FloatingBottomNav(
|
||||||
|
selectedNavItem: Int = 0,
|
||||||
|
onNavItemSelect: (Int) -> Unit = {},
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
// 监听语言变化以触发重组
|
||||||
|
val currentLang by LanguageManager.currentLanguage.collectAsState()
|
||||||
|
|
||||||
|
val navItems = listOf(
|
||||||
|
R.drawable.ic_dashboard,
|
||||||
|
R.drawable.ic_scene,
|
||||||
|
R.drawable.ic_automation,
|
||||||
|
R.drawable.ic_security,
|
||||||
|
R.drawable.ic_settings
|
||||||
|
)
|
||||||
|
|
||||||
|
val itemWidth = 52.dp
|
||||||
|
val itemSpacing = 4.dp
|
||||||
|
val totalItemWidth = itemWidth + itemSpacing
|
||||||
|
|
||||||
|
// 是否正在拖动
|
||||||
|
var isDragging by remember { mutableStateOf(false) }
|
||||||
|
// 拖动时的临时选中项
|
||||||
|
var dragIndex by remember { mutableStateOf(selectedNavItem) }
|
||||||
|
|
||||||
|
// 当外部 selectedNavItem 变化时,同步更新 dragIndex
|
||||||
|
LaunchedEffect(selectedNavItem) {
|
||||||
|
if (!isDragging) {
|
||||||
|
dragIndex = selectedNavItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中框的动画偏移量 - 跟随 dragIndex(拖动时)或 selectedNavItem(点击时)
|
||||||
|
val currentIndex = if (isDragging) dragIndex else selectedNavItem
|
||||||
|
val animatedOffset by animateFloatAsState(
|
||||||
|
targetValue = currentIndex * (itemWidth.value + itemSpacing.value),
|
||||||
|
animationSpec = spring(
|
||||||
|
dampingRatio = Spring.DampingRatioMediumBouncy,
|
||||||
|
stiffness = Spring.StiffnessHigh
|
||||||
|
),
|
||||||
|
label = "liquid_glass_offset"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
val density = LocalDensity.current
|
||||||
|
|
||||||
|
// 菜单栏高度(胶囊形)
|
||||||
|
val navBarHeight = 68.dp
|
||||||
|
val navBarPadding = 10.dp
|
||||||
|
val innerHeight = navBarHeight - navBarPadding * 2 // 48dp
|
||||||
|
|
||||||
|
// 选中指示器尺寸 - 按住时放大到贴合菜单栏边缘
|
||||||
|
val indicatorSize by animateFloatAsState(
|
||||||
|
targetValue = if (isDragging) (navBarHeight.value - 4f) else innerHeight.value,
|
||||||
|
animationSpec = spring(
|
||||||
|
dampingRatio = Spring.DampingRatioMediumBouncy,
|
||||||
|
stiffness = Spring.StiffnessMedium
|
||||||
|
),
|
||||||
|
label = "indicator_size"
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = modifier
|
||||||
|
.height(navBarHeight)
|
||||||
|
.shadow(24.dp, RoundedCornerShape(50))
|
||||||
|
.clip(RoundedCornerShape(50))
|
||||||
|
.background(
|
||||||
|
Brush.linearGradient(
|
||||||
|
colors = listOf(
|
||||||
|
Color(0xFF1A1A2E).copy(alpha = 0.95f),
|
||||||
|
Color(0xFF16213E).copy(alpha = 0.95f)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
brush = Brush.linearGradient(
|
||||||
|
colors = listOf(
|
||||||
|
Color.White.copy(alpha = 0.1f),
|
||||||
|
Color.White.copy(alpha = 0.05f)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(50)
|
||||||
|
)
|
||||||
|
.padding(horizontal = 10.dp, vertical = 10.dp)
|
||||||
|
.pointerInput(Unit) {
|
||||||
|
detectHorizontalDragGestures(
|
||||||
|
onDragStart = { offset ->
|
||||||
|
isDragging = true
|
||||||
|
val index = (offset.x / (itemWidth.toPx() + itemSpacing.toPx())).toInt()
|
||||||
|
.coerceIn(0, navItems.size - 1)
|
||||||
|
dragIndex = index
|
||||||
|
},
|
||||||
|
onDragEnd = {
|
||||||
|
isDragging = false
|
||||||
|
onNavItemSelect(dragIndex)
|
||||||
|
},
|
||||||
|
onDragCancel = {
|
||||||
|
isDragging = false
|
||||||
|
dragIndex = selectedNavItem
|
||||||
|
},
|
||||||
|
onHorizontalDrag = { change, _ ->
|
||||||
|
change.consume()
|
||||||
|
val index = (change.position.x / (itemWidth.toPx() + itemSpacing.toPx())).toInt()
|
||||||
|
.coerceIn(0, navItems.size - 1)
|
||||||
|
if (index != dragIndex) {
|
||||||
|
dragIndex = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.CenterStart
|
||||||
|
) {
|
||||||
|
// 选中指示器 - 按住时放大贴合菜单栏边缘
|
||||||
|
val horizontalOffset = (itemWidth.value - indicatorSize) / 2f
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterStart)
|
||||||
|
.offset(x = animatedOffset.dp + horizontalOffset.dp)
|
||||||
|
.size(indicatorSize.dp)
|
||||||
|
.clip(RoundedCornerShape(50))
|
||||||
|
.background(Color.White.copy(alpha = if (isDragging) 0.2f else 0.12f))
|
||||||
|
.border(
|
||||||
|
width = if (isDragging) 2.dp else 1.5.dp,
|
||||||
|
color = Color.White.copy(alpha = if (isDragging) 0.6f else 0.25f),
|
||||||
|
shape = RoundedCornerShape(50)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 图标层
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(itemSpacing),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
navItems.forEachIndexed { index, iconRes ->
|
||||||
|
val isCurrentSelected = if (isDragging) index == dragIndex else index == selectedNavItem
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(itemWidth)
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.clickable(
|
||||||
|
indication = null,
|
||||||
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
) {
|
||||||
|
if (!isDragging) {
|
||||||
|
onNavItemSelect(index)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = iconRes),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(
|
||||||
|
if (isCurrentSelected) Color.White else Color(0xFFB0B0B0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SideNavRail(selectedNavItem: Int = 0, onNavItemSelect: (Int) -> Unit = {}) {
|
fun SideNavRail(selectedNavItem: Int = 0, onNavItemSelect: (Int) -> Unit = {}) {
|
||||||
val context = androidx.compose.ui.platform.LocalContext.current
|
val context = androidx.compose.ui.platform.LocalContext.current
|
||||||
@ -2501,3 +2635,432 @@ fun AddRoomDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RenameRoomDialog(
|
||||||
|
currentName: String,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onConfirm: (String) -> Unit
|
||||||
|
) {
|
||||||
|
var roomName by remember { mutableStateOf(currentName) }
|
||||||
|
|
||||||
|
// 背景遮罩(点击关闭)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.clickable(
|
||||||
|
indication = null,
|
||||||
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
) { onDismiss() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
// 对话框主体
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(380.dp)
|
||||||
|
.clip(RoundedCornerShape(28.dp))
|
||||||
|
.background(
|
||||||
|
Brush.verticalGradient(
|
||||||
|
listOf(
|
||||||
|
Color(0xFF2A2A3E),
|
||||||
|
Color(0xFF1A1A2E)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
brush = Brush.linearGradient(
|
||||||
|
listOf(Color(0xFF00D1FF).copy(alpha = 0.3f), Color(0xFFB89CFF).copy(alpha = 0.3f))
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(28.dp)
|
||||||
|
)
|
||||||
|
.clickable(
|
||||||
|
indication = null,
|
||||||
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
) { /* 阻止点击穿透 */ }
|
||||||
|
.padding(28.dp)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||||
|
) {
|
||||||
|
// 标题区域
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(44.dp)
|
||||||
|
.clip(RoundedCornerShape(12.dp))
|
||||||
|
.background(
|
||||||
|
Brush.linearGradient(
|
||||||
|
listOf(Color(0xFF00D1FF).copy(alpha = 0.3f), Color(0xFFB89CFF).copy(alpha = 0.3f))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "✏️", fontSize = 22.sp)
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = "重命名房间",
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "修改房间名称",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color(0xFF9AA0A6)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(32.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(Color(0x33FFFFFF))
|
||||||
|
.clickable { onDismiss() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "✕", color = Color(0xFF9AA0A6), fontSize = 14.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 房间名称输入
|
||||||
|
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
|
Text(
|
||||||
|
text = "房间名称",
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = Color(0xFFB0B0B0)
|
||||||
|
)
|
||||||
|
TextField(
|
||||||
|
value = roomName,
|
||||||
|
onValueChange = { roomName = it },
|
||||||
|
placeholder = { Text("输入新名称...", color = Color(0xFF6A6A7A)) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(56.dp),
|
||||||
|
colors = TextFieldDefaults.colors(
|
||||||
|
focusedContainerColor = Color(0xFF1A1A2E),
|
||||||
|
unfocusedContainerColor = Color(0xFF1A1A2E),
|
||||||
|
focusedTextColor = Color.White,
|
||||||
|
unfocusedTextColor = Color.White,
|
||||||
|
cursorColor = Color(0xFF00D1FF),
|
||||||
|
focusedIndicatorColor = Color.Transparent,
|
||||||
|
unfocusedIndicatorColor = Color.Transparent
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(14.dp),
|
||||||
|
singleLine = true,
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(fontSize = 16.sp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按钮区域
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(52.dp)
|
||||||
|
.clip(RoundedCornerShape(14.dp))
|
||||||
|
.background(Color(0xFF1A1A2E))
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = Color(0xFF3A3A4E),
|
||||||
|
shape = RoundedCornerShape(14.dp)
|
||||||
|
)
|
||||||
|
.clickable { onDismiss() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "取消",
|
||||||
|
color = Color(0xFFB0B0B0),
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 15.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val canConfirm = roomName.isNotBlank() && roomName.trim() != currentName
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(52.dp)
|
||||||
|
.clip(RoundedCornerShape(14.dp))
|
||||||
|
.background(
|
||||||
|
if (canConfirm)
|
||||||
|
Brush.linearGradient(listOf(Color(0xFF00D1FF), Color(0xFFB89CFF)))
|
||||||
|
else
|
||||||
|
Brush.linearGradient(listOf(Color(0xFF3A3A4E), Color(0xFF3A3A4E)))
|
||||||
|
)
|
||||||
|
.clickable(enabled = canConfirm) {
|
||||||
|
onConfirm(roomName.trim())
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "✓",
|
||||||
|
color = if (canConfirm) Color.White else Color(0xFF6A6A7A),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "确认修改",
|
||||||
|
color = if (canConfirm) Color.White else Color(0xFF6A6A7A),
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 15.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun EditRoomsDialog(
|
||||||
|
rooms: List<String>,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onRenameRoom: (Int, String) -> Unit,
|
||||||
|
onDeleteRoom: (Int) -> Unit
|
||||||
|
) {
|
||||||
|
// 当前编辑的房间索引
|
||||||
|
var editingIndex by remember { mutableStateOf(-1) }
|
||||||
|
var editingName by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
// 背景遮罩
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.clickable(
|
||||||
|
indication = null,
|
||||||
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
) { onDismiss() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
// 对话框主体
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(420.dp)
|
||||||
|
.clip(RoundedCornerShape(28.dp))
|
||||||
|
.background(
|
||||||
|
Brush.verticalGradient(
|
||||||
|
listOf(
|
||||||
|
Color(0xFF2A2A3E),
|
||||||
|
Color(0xFF1A1A2E)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
brush = Brush.linearGradient(
|
||||||
|
listOf(Color(0xFF00D1FF).copy(alpha = 0.3f), Color(0xFFB89CFF).copy(alpha = 0.3f))
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(28.dp)
|
||||||
|
)
|
||||||
|
.clickable(
|
||||||
|
indication = null,
|
||||||
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
) { /* 阻止点击穿透 */ }
|
||||||
|
.padding(28.dp)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(20.dp)
|
||||||
|
) {
|
||||||
|
// 标题区域
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(44.dp)
|
||||||
|
.clip(RoundedCornerShape(12.dp))
|
||||||
|
.background(
|
||||||
|
Brush.linearGradient(
|
||||||
|
listOf(Color(0xFF00D1FF).copy(alpha = 0.3f), Color(0xFFB89CFF).copy(alpha = 0.3f))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "🏠", fontSize = 22.sp)
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = "编辑房间",
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "管理你的房间列表",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color(0xFF9AA0A6)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(32.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(Color(0x33FFFFFF))
|
||||||
|
.clickable { onDismiss() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "✕", color = Color(0xFF9AA0A6), fontSize = 14.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 房间列表
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
modifier = Modifier.heightIn(max = 300.dp).verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
rooms.forEachIndexed { index, name ->
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(14.dp))
|
||||||
|
.background(Color(0xFF1A1A2E))
|
||||||
|
.padding(12.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
if (editingIndex == index) {
|
||||||
|
// 编辑模式
|
||||||
|
TextField(
|
||||||
|
value = editingName,
|
||||||
|
onValueChange = { editingName = it },
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(48.dp),
|
||||||
|
colors = TextFieldDefaults.colors(
|
||||||
|
focusedContainerColor = Color(0xFF2A2A3E),
|
||||||
|
unfocusedContainerColor = Color(0xFF2A2A3E),
|
||||||
|
focusedTextColor = Color.White,
|
||||||
|
unfocusedTextColor = Color.White,
|
||||||
|
cursorColor = Color(0xFF00D1FF),
|
||||||
|
focusedIndicatorColor = Color.Transparent,
|
||||||
|
unfocusedIndicatorColor = Color.Transparent
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(10.dp),
|
||||||
|
singleLine = true,
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(fontSize = 15.sp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
|
// 确认按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(36.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(Color(0xFF4CAF50))
|
||||||
|
.clickable {
|
||||||
|
if (editingName.isNotBlank() && editingName != name) {
|
||||||
|
onRenameRoom(index, editingName.trim())
|
||||||
|
}
|
||||||
|
editingIndex = -1
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "✓", color = Color.White, fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
// 取消按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(36.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(Color(0xFF3A3A4E))
|
||||||
|
.clickable { editingIndex = -1 },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "✕", color = Color(0xFFB0B0B0), fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 显示模式
|
||||||
|
Text(
|
||||||
|
text = name,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
|
// 编辑按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(36.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(Color(0xFF3A3A4E))
|
||||||
|
.clickable {
|
||||||
|
editingIndex = index
|
||||||
|
editingName = name
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "✏️", fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
// 删除按钮
|
||||||
|
if (rooms.size > 1) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(36.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(Color(0xFFFF5252).copy(alpha = 0.2f))
|
||||||
|
.clickable { onDeleteRoom(index) },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "🗑️", fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 完成按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(52.dp)
|
||||||
|
.clip(RoundedCornerShape(14.dp))
|
||||||
|
.background(
|
||||||
|
Brush.linearGradient(listOf(Color(0xFF00D1FF), Color(0xFFB89CFF)))
|
||||||
|
)
|
||||||
|
.clickable { onDismiss() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "完成",
|
||||||
|
color = Color.White,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 15.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
BIN
app/src/main/res/drawable/room_wallpaper_default.png
Normal file
BIN
app/src/main/res/drawable/room_wallpaper_default.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
BIN
zenhome-wallpaper-1764392320729.png
Normal file
BIN
zenhome-wallpaper-1764392320729.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
Loading…
Reference in New Issue
Block a user