refactor: 主页重构,联机模式/游戏设置改为二级页面,昵称/主题/关于移至设置
This commit is contained in:
parent
093a759ad4
commit
d8191a44b1
@ -198,40 +198,17 @@ fun UnoApp() {
|
|||||||
) {
|
) {
|
||||||
composable(Screen.MainMenu.route) {
|
composable(Screen.MainMenu.route) {
|
||||||
MainMenuScreen(
|
MainMenuScreen(
|
||||||
initialName = savedName,
|
onLocalGame = { navController.navigate(Screen.ModeSelect.route) },
|
||||||
onNameChanged = { name ->
|
onOnlineGame = { navController.navigate(Screen.LobbyMenu.route) },
|
||||||
savedName = name
|
onScoreboard = { navController.navigate(Screen.Scoreboard.route) },
|
||||||
prefs.edit().putString("player_name", name).apply()
|
onRules = { navController.navigate(Screen.Rules.route) },
|
||||||
},
|
onSettings = { navController.navigate(Screen.Settings.route) }
|
||||||
onLocalGame = {
|
)
|
||||||
navController.navigate(Screen.ModeSelect.route)
|
}
|
||||||
},
|
|
||||||
onScoreboard = {
|
composable(Screen.LobbyMenu.route) {
|
||||||
navController.navigate(Screen.Scoreboard.route)
|
LobbyMenuScreen(
|
||||||
},
|
playerName = savedName,
|
||||||
onRules = {
|
|
||||||
navController.navigate(Screen.Rules.route)
|
|
||||||
},
|
|
||||||
currentTheme = cardTheme,
|
|
||||||
currentBg = tableBg,
|
|
||||||
onToggleTheme = {
|
|
||||||
val next = CardTheme.values()[(cardTheme.ordinal + 1) % CardTheme.values().size]
|
|
||||||
cardTheme = next
|
|
||||||
CardTheme.save(context, next)
|
|
||||||
},
|
|
||||||
onToggleBg = {
|
|
||||||
val next = TableBg.values()[(tableBg.ordinal + 1) % TableBg.values().size]
|
|
||||||
tableBg = next
|
|
||||||
TableBg.save(context, next)
|
|
||||||
},
|
|
||||||
onToggleOrientation = {
|
|
||||||
isLandscape = !isLandscape
|
|
||||||
prefs.edit().putBoolean("landscape", isLandscape).apply()
|
|
||||||
(context as? android.app.Activity)?.requestedOrientation =
|
|
||||||
if (isLandscape) ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
|
||||||
else ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
|
||||||
},
|
|
||||||
isLandscape = isLandscape,
|
|
||||||
onHostGame = { name ->
|
onHostGame = { name ->
|
||||||
myName = name
|
myName = name
|
||||||
isHost = true
|
isHost = true
|
||||||
@ -244,7 +221,6 @@ fun UnoApp() {
|
|||||||
discoveryService = discovery
|
discoveryService = discovery
|
||||||
discovery.startAdvertising(name, 1)
|
discovery.startAdvertising(name, 1)
|
||||||
navController.navigate(Screen.Lobby.createRoute(true))
|
navController.navigate(Screen.Lobby.createRoute(true))
|
||||||
// Host connects as a client too (to localhost) - on IO thread
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val client = GameClient()
|
val client = GameClient()
|
||||||
if (client.connect("127.0.0.1", name)) {
|
if (client.connect("127.0.0.1", name)) {
|
||||||
@ -262,7 +238,6 @@ fun UnoApp() {
|
|||||||
discoveryService = discovery
|
discoveryService = discovery
|
||||||
discovery.startDiscovery(name)
|
discovery.startDiscovery(name)
|
||||||
isDiscovering = true
|
isDiscovering = true
|
||||||
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
discovery.hosts.collect { hosts ->
|
discovery.hosts.collect { hosts ->
|
||||||
discoveredHosts = hosts
|
discoveredHosts = hosts
|
||||||
@ -270,7 +245,8 @@ fun UnoApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
navController.navigate(Screen.Lobby.createRoute(false))
|
navController.navigate(Screen.Lobby.createRoute(false))
|
||||||
}
|
},
|
||||||
|
onBack = { navController.popBackStack() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,6 +400,34 @@ fun UnoApp() {
|
|||||||
RulesHelpScreen(onBack = { navController.popBackStack() })
|
RulesHelpScreen(onBack = { navController.popBackStack() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
composable(Screen.Settings.route) {
|
||||||
|
SettingsScreen(
|
||||||
|
initialName = savedName,
|
||||||
|
currentTheme = cardTheme,
|
||||||
|
currentBg = tableBg,
|
||||||
|
isLandscape = isLandscape,
|
||||||
|
onNameChanged = { name ->
|
||||||
|
savedName = name
|
||||||
|
prefs.edit().putString("player_name", name).apply()
|
||||||
|
},
|
||||||
|
onToggleTheme = {
|
||||||
|
val next = CardTheme.values()[(cardTheme.ordinal + 1) % CardTheme.values().size]
|
||||||
|
cardTheme = next
|
||||||
|
CardTheme.save(context, next)
|
||||||
|
},
|
||||||
|
onToggleBg = {
|
||||||
|
val next = TableBg.values()[(tableBg.ordinal + 1) % TableBg.values().size]
|
||||||
|
tableBg = next
|
||||||
|
TableBg.save(context, next)
|
||||||
|
},
|
||||||
|
onToggleOrientation = {
|
||||||
|
isLandscape = !isLandscape
|
||||||
|
prefs.edit().putBoolean("landscape", isLandscape).apply()
|
||||||
|
},
|
||||||
|
onBack = { navController.popBackStack() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
composable(Screen.Game.route) {
|
composable(Screen.Game.route) {
|
||||||
gameState?.let { state ->
|
gameState?.let { state ->
|
||||||
GameScreen(
|
GameScreen(
|
||||||
|
|||||||
@ -6,6 +6,7 @@ sealed class Screen(val route: String) {
|
|||||||
fun createRoute(isHost: Boolean) = "lobby/$isHost"
|
fun createRoute(isHost: Boolean) = "lobby/$isHost"
|
||||||
}
|
}
|
||||||
data object ModeSelect : Screen("mode_select")
|
data object ModeSelect : Screen("mode_select")
|
||||||
|
data object LobbyMenu : Screen("lobby_menu")
|
||||||
data object LocalSetup : Screen("local_setup/{modeName}") {
|
data object LocalSetup : Screen("local_setup/{modeName}") {
|
||||||
fun createRoute(mode: String) = "local_setup/$mode"
|
fun createRoute(mode: String) = "local_setup/$mode"
|
||||||
}
|
}
|
||||||
@ -20,4 +21,5 @@ sealed class Screen(val route: String) {
|
|||||||
fun createRoute(winnerName: String, isYouWinner: Boolean) =
|
fun createRoute(winnerName: String, isYouWinner: Boolean) =
|
||||||
"game_over/$winnerName/$isYouWinner"
|
"game_over/$winnerName/$isYouWinner"
|
||||||
}
|
}
|
||||||
|
data object Settings : Screen("settings")
|
||||||
}
|
}
|
||||||
|
|||||||
101
app/src/main/java/com/unogame/ui/screens/LobbyMenuScreen.kt
Normal file
101
app/src/main/java/com/unogame/ui/screens/LobbyMenuScreen.kt
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package com.unogame.ui.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.*
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.unogame.ui.theme.*
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LobbyMenuScreen(
|
||||||
|
playerName: String,
|
||||||
|
onHostGame: (String) -> Unit,
|
||||||
|
onJoinGame: (String) -> Unit,
|
||||||
|
onBack: () -> Unit
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize().background(LocalTableBg.current.color)) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(24.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
IconButton(onClick = onBack) {
|
||||||
|
Icon(Icons.Default.ArrowBack, "返回", tint = Color.White)
|
||||||
|
}
|
||||||
|
Text("联机模式", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = Color.White)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(40.dp))
|
||||||
|
|
||||||
|
// Create room
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val name = playerName.ifBlank { "玩家" }
|
||||||
|
onHostGame(name)
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth().height(56.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = GoldAccent,
|
||||||
|
contentColor = Color.Black
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Icon(Icons.Default.Home, null)
|
||||||
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
Text("创建房间", fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// Join room
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val name = playerName.ifBlank { "玩家" }
|
||||||
|
onJoinGame(name)
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth().height(56.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = DarkSurface,
|
||||||
|
contentColor = Color.White
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Icon(Icons.Default.Search, null)
|
||||||
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
Text("加入房间", fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
shape = RoundedCornerShape(12.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = DarkSurface.copy(alpha = 0.5f))
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
|
Text("说明", color = GoldAccent, fontWeight = FontWeight.Bold, fontSize = 14.sp)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
"创建房间:作为房主等待其他玩家加入\n加入房间:搜索同一WiFi下的房间",
|
||||||
|
color = Color.White.copy(alpha = 0.6f),
|
||||||
|
fontSize = 13.sp,
|
||||||
|
lineHeight = 20.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package com.unogame.ui.screens
|
package com.unogame.ui.screens
|
||||||
|
|
||||||
import androidx.compose.animation.*
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
@ -12,10 +11,8 @@ import androidx.compose.material3.*
|
|||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
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.Brush
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@ -23,23 +20,12 @@ import com.unogame.ui.theme.*
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainMenuScreen(
|
fun MainMenuScreen(
|
||||||
initialName: String,
|
|
||||||
currentTheme: CardTheme,
|
|
||||||
currentBg: TableBg,
|
|
||||||
onHostGame: (String) -> Unit,
|
|
||||||
onJoinGame: (String) -> Unit,
|
|
||||||
onLocalGame: () -> Unit,
|
onLocalGame: () -> Unit,
|
||||||
|
onOnlineGame: () -> Unit,
|
||||||
onScoreboard: () -> Unit,
|
onScoreboard: () -> Unit,
|
||||||
onRules: () -> Unit,
|
onRules: () -> Unit,
|
||||||
onToggleTheme: () -> Unit,
|
onSettings: () -> Unit
|
||||||
onToggleBg: () -> Unit,
|
|
||||||
onToggleOrientation: () -> Unit,
|
|
||||||
isLandscape: Boolean,
|
|
||||||
onNameChanged: (String) -> Unit
|
|
||||||
) {
|
) {
|
||||||
var playerName by remember { mutableStateOf(initialName) }
|
|
||||||
var showAbout by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@ -54,7 +40,6 @@ fun MainMenuScreen(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
// Title
|
// Title
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
Text(
|
Text(
|
||||||
text = "UNO",
|
text = "UNO",
|
||||||
fontSize = 72.sp,
|
fontSize = 72.sp,
|
||||||
@ -62,7 +47,6 @@ fun MainMenuScreen(
|
|||||||
color = GoldAccent,
|
color = GoldAccent,
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
}
|
|
||||||
Text(
|
Text(
|
||||||
text = "卡牌游戏",
|
text = "卡牌游戏",
|
||||||
fontSize = 18.sp,
|
fontSize = 18.sp,
|
||||||
@ -70,76 +54,9 @@ fun MainMenuScreen(
|
|||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(60.dp))
|
Spacer(modifier = Modifier.height(48.dp))
|
||||||
|
|
||||||
// Name input
|
// 1. 本地模式
|
||||||
OutlinedTextField(
|
|
||||||
value = playerName,
|
|
||||||
onValueChange = {
|
|
||||||
playerName = it.take(10)
|
|
||||||
onNameChanged(playerName.ifBlank { "玩家" })
|
|
||||||
},
|
|
||||||
label = { Text("你的昵称", color = Color.White.copy(alpha = 0.6f)) },
|
|
||||||
singleLine = true,
|
|
||||||
colors = OutlinedTextFieldDefaults.colors(
|
|
||||||
focusedTextColor = Color.White,
|
|
||||||
unfocusedTextColor = Color.White,
|
|
||||||
focusedBorderColor = GoldAccent,
|
|
||||||
unfocusedBorderColor = Color.Gray,
|
|
||||||
cursorColor = GoldAccent
|
|
||||||
),
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(32.dp))
|
|
||||||
|
|
||||||
// Host Game button
|
|
||||||
Button(
|
|
||||||
onClick = {
|
|
||||||
val name = playerName.ifBlank { "玩家" }
|
|
||||||
onNameChanged(name)
|
|
||||||
onHostGame(name)
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(56.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
containerColor = DarkSurface,
|
|
||||||
contentColor = GoldAccent
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.Home, contentDescription = null)
|
|
||||||
Spacer(modifier = Modifier.width(12.dp))
|
|
||||||
Text("创建房间", fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
// Join Game button
|
|
||||||
Button(
|
|
||||||
onClick = {
|
|
||||||
val name = playerName.ifBlank { "玩家" }
|
|
||||||
onNameChanged(name)
|
|
||||||
onJoinGame(name)
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(56.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
containerColor = DarkSurface,
|
|
||||||
contentColor = Color.White
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.Search, contentDescription = null)
|
|
||||||
Spacer(modifier = Modifier.width(12.dp))
|
|
||||||
Text("加入房间", fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
// Local Game button
|
|
||||||
Button(
|
Button(
|
||||||
onClick = onLocalGame,
|
onClick = onLocalGame,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -158,7 +75,26 @@ fun MainMenuScreen(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
// Scoreboard button
|
// 2. 联机模式
|
||||||
|
Button(
|
||||||
|
onClick = onOnlineGame,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(56.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = DarkSurface,
|
||||||
|
contentColor = GoldAccent
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Icon(Icons.Default.Wifi, contentDescription = null)
|
||||||
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
Text("联机模式", fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// 3. 排行榜
|
||||||
Button(
|
Button(
|
||||||
onClick = onScoreboard,
|
onClick = onScoreboard,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -177,7 +113,7 @@ fun MainMenuScreen(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
// Rules button
|
// 4. 规则说明
|
||||||
Button(
|
Button(
|
||||||
onClick = onRules,
|
onClick = onRules,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -196,92 +132,22 @@ fun MainMenuScreen(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
// Theme toggle
|
// 5. 游戏设置
|
||||||
TextButton(onClick = onToggleTheme) {
|
Button(
|
||||||
Icon(Icons.Default.Palette, null, tint = Color.White.copy(alpha = 0.5f))
|
onClick = onSettings,
|
||||||
Spacer(modifier = Modifier.width(6.dp))
|
modifier = Modifier
|
||||||
Text("卡面: ${currentTheme.displayName}", color = Color.White.copy(alpha = 0.5f), fontSize = 14.sp)
|
.fillMaxWidth()
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
.height(56.dp),
|
||||||
Text("→", color = GoldAccent, fontSize = 14.sp)
|
shape = RoundedCornerShape(16.dp),
|
||||||
}
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = DarkSurface,
|
||||||
// Background toggle
|
contentColor = Color.White.copy(alpha = 0.5f)
|
||||||
TextButton(onClick = onToggleBg) {
|
)
|
||||||
Icon(Icons.Default.Wallpaper, null, tint = Color.White.copy(alpha = 0.5f))
|
|
||||||
Spacer(modifier = Modifier.width(6.dp))
|
|
||||||
Text("牌桌: ${currentBg.displayName}", color = Color.White.copy(alpha = 0.5f), fontSize = 14.sp)
|
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Text("→", color = GoldAccent, fontSize = 14.sp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Orientation toggle
|
|
||||||
TextButton(onClick = onToggleOrientation) {
|
|
||||||
Icon(if (isLandscape) Icons.Default.StayCurrentLandscape else Icons.Default.StayCurrentPortrait,
|
|
||||||
null, tint = Color.White.copy(alpha = 0.5f))
|
|
||||||
Spacer(modifier = Modifier.width(6.dp))
|
|
||||||
Text(if (isLandscape) "横屏" else "竖屏", color = Color.White.copy(alpha = 0.5f), fontSize = 14.sp)
|
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Text("→", color = GoldAccent, fontSize = 14.sp)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
// About button
|
|
||||||
TextButton(onClick = { showAbout = true }) {
|
|
||||||
Icon(Icons.Default.Info, null, tint = Color.White.copy(alpha = 0.5f))
|
|
||||||
Spacer(modifier = Modifier.width(6.dp))
|
|
||||||
Text("关于", color = Color.White.copy(alpha = 0.5f), fontSize = 14.sp)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
|
|
||||||
// Instructions
|
|
||||||
Card(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
shape = RoundedCornerShape(12.dp),
|
|
||||||
colors = CardDefaults.cardColors(containerColor = DarkSurface.copy(alpha = 0.5f))
|
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
Icon(Icons.Default.Settings, contentDescription = null)
|
||||||
Text(
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
"游戏说明",
|
Text("游戏设置", fontSize = 18.sp, fontWeight = FontWeight.Bold)
|
||||||
color = GoldAccent,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
fontSize = 14.sp
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
Text(
|
|
||||||
"• 创建房间:作为房主等待其他玩家加入\n• 加入房间:搜索同一WiFi下的房间\n• 与同颜色、同数字/功能的牌匹配",
|
|
||||||
color = Color.White.copy(alpha = 0.7f),
|
|
||||||
fontSize = 12.sp,
|
|
||||||
lineHeight = 18.sp
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// About dialog
|
|
||||||
if (showAbout) {
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = { showAbout = false },
|
|
||||||
title = { Text("关于", color = GoldAccent, fontWeight = FontWeight.Bold) },
|
|
||||||
text = {
|
|
||||||
Column {
|
|
||||||
Text("感谢名单", color = GoldAccent, fontSize = 16.sp, fontWeight = FontWeight.Bold)
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
Text("主创:刘博", color = Color.White, fontSize = 14.sp)
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
Text("最佳苦力:opencode、deepseek v4 pro", color = Color.White, fontSize = 14.sp)
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
Text("金牌测试:张天弈、蔺明智", color = Color.White, fontSize = 14.sp)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
confirmButton = {
|
|
||||||
TextButton(onClick = { showAbout = false }) {
|
|
||||||
Text("关闭", color = GoldAccent)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
containerColor = DarkSurface
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
167
app/src/main/java/com/unogame/ui/screens/SettingsScreen.kt
Normal file
167
app/src/main/java/com/unogame/ui/screens/SettingsScreen.kt
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
package com.unogame.ui.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.*
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.unogame.ui.theme.*
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsScreen(
|
||||||
|
initialName: String,
|
||||||
|
currentTheme: CardTheme,
|
||||||
|
currentBg: TableBg,
|
||||||
|
isLandscape: Boolean,
|
||||||
|
onNameChanged: (String) -> Unit,
|
||||||
|
onToggleTheme: () -> Unit,
|
||||||
|
onToggleBg: () -> Unit,
|
||||||
|
onToggleOrientation: () -> Unit,
|
||||||
|
onBack: () -> Unit
|
||||||
|
) {
|
||||||
|
var playerName by remember { mutableStateOf(initialName) }
|
||||||
|
var showAbout by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxSize().background(LocalTableBg.current.color)) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.padding(24.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
IconButton(onClick = onBack) {
|
||||||
|
Icon(Icons.Default.ArrowBack, "返回", tint = Color.White)
|
||||||
|
}
|
||||||
|
Text("游戏设置", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = Color.White)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
|
|
||||||
|
// Nickname
|
||||||
|
Text("你的昵称", color = Color.White.copy(alpha = 0.6f), fontSize = 14.sp)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
OutlinedTextField(
|
||||||
|
value = playerName,
|
||||||
|
onValueChange = {
|
||||||
|
playerName = it.take(10)
|
||||||
|
onNameChanged(playerName.ifBlank { "玩家" })
|
||||||
|
},
|
||||||
|
singleLine = true,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
colors = OutlinedTextFieldDefaults.colors(
|
||||||
|
focusedTextColor = Color.White,
|
||||||
|
unfocusedTextColor = Color.White,
|
||||||
|
focusedBorderColor = GoldAccent,
|
||||||
|
unfocusedBorderColor = Color.Gray,
|
||||||
|
cursorColor = GoldAccent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(28.dp))
|
||||||
|
|
||||||
|
// Card theme
|
||||||
|
Text("外观设置", color = Color.White.copy(alpha = 0.6f), fontSize = 14.sp)
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
SettingsRow(
|
||||||
|
icon = Icons.Default.Palette,
|
||||||
|
label = "卡面风格",
|
||||||
|
value = currentTheme.displayName,
|
||||||
|
onClick = onToggleTheme
|
||||||
|
)
|
||||||
|
SettingsRow(
|
||||||
|
icon = Icons.Default.Wallpaper,
|
||||||
|
label = "牌桌背景",
|
||||||
|
value = currentBg.displayName,
|
||||||
|
onClick = onToggleBg
|
||||||
|
)
|
||||||
|
SettingsRow(
|
||||||
|
icon = if (isLandscape) Icons.Default.StayCurrentLandscape else Icons.Default.StayCurrentPortrait,
|
||||||
|
label = "屏幕方向",
|
||||||
|
value = if (isLandscape) "横屏" else "竖屏",
|
||||||
|
onClick = onToggleOrientation
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(28.dp))
|
||||||
|
|
||||||
|
// About
|
||||||
|
Text("其他", color = Color.White.copy(alpha = 0.6f), fontSize = 14.sp)
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
SettingsRow(
|
||||||
|
icon = Icons.Default.Info,
|
||||||
|
label = "关于",
|
||||||
|
value = "",
|
||||||
|
onClick = { showAbout = true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showAbout) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { showAbout = false },
|
||||||
|
title = { Text("关于", color = GoldAccent, fontWeight = FontWeight.Bold) },
|
||||||
|
text = {
|
||||||
|
Column {
|
||||||
|
Text("感谢名单", color = GoldAccent, fontSize = 16.sp, fontWeight = FontWeight.Bold)
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
Text("主创:刘博", color = Color.White, fontSize = 14.sp)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text("最佳苦力:opencode、deepseek v4 pro", color = Color.White.copy(alpha = 0.7f), fontSize = 14.sp)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text("金牌测试:张天羿、蔺明智", color = Color.White.copy(alpha = 0.7f), fontSize = 14.sp)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = { showAbout = false }) {
|
||||||
|
Text("关闭", color = GoldAccent)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
containerColor = DarkSurface
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SettingsRow(
|
||||||
|
icon: androidx.compose.ui.graphics.vector.ImageVector,
|
||||||
|
label: String,
|
||||||
|
value: String,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onClick() },
|
||||||
|
shape = RoundedCornerShape(12.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = DarkSurface)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(icon, null, tint = Color.White.copy(alpha = 0.6f), modifier = Modifier.size(20.dp))
|
||||||
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
Text(label, color = Color.White, fontSize = 15.sp, modifier = Modifier.weight(1f))
|
||||||
|
if (value.isNotEmpty()) {
|
||||||
|
Text(value, color = GoldAccent, fontSize = 14.sp)
|
||||||
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
|
Icon(Icons.Default.ChevronRight, null, tint = Color.White.copy(alpha = 0.3f), modifier = Modifier.size(18.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user