From 2f6944abfed5ca409e95f9d90dc516ca5924a12e Mon Sep 17 00:00:00 2001 From: Mohammed-MEZO Date: Wed, 22 Apr 2026 00:26:53 +0200 Subject: [PATCH] Redesign Dead Zon screens with red-glass onboarding pass --- .../java/com/deadzon/app/app/DeadZonApp.kt | 128 ++++++++++++--- .../deadzon/app/core/theme/DeadZonTheme.kt | 27 ++-- .../com/deadzon/app/core/ui/DeadZonGlass.kt | 153 ++++++++++++++++++ .../com/deadzon/app/core/ui/MonetWidgets.kt | 51 +++--- .../app/data/prefs/MonetPreferences.kt | 11 +- .../deadzon/app/domain/monet/MonetModels.kt | 3 +- .../app/feature/dashboard/DashboardScreen.kt | 73 ++++++--- .../deadzon/app/feature/monet/MonetScreen.kt | 116 ++++++++----- .../app/feature/monet/MonetViewModel.kt | 34 +++- .../app/feature/settings/SettingsScreen.kt | 33 +++- 10 files changed, 496 insertions(+), 133 deletions(-) create mode 100644 app/src/main/java/com/deadzon/app/core/ui/DeadZonGlass.kt diff --git a/app/src/main/java/com/deadzon/app/app/DeadZonApp.kt b/app/src/main/java/com/deadzon/app/app/DeadZonApp.kt index 4215fb85..20fae44a 100644 --- a/app/src/main/java/com/deadzon/app/app/DeadZonApp.kt +++ b/app/src/main/java/com/deadzon/app/app/DeadZonApp.kt @@ -1,52 +1,132 @@ package com.deadzon.app.app +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon -import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController +import com.deadzon.app.core.ui.BottomActionBar +import com.deadzon.app.core.ui.DeadZonBackground +import com.deadzon.app.core.ui.DeadZonLogoMark +import com.deadzon.app.core.ui.GlassCard +import com.deadzon.app.core.ui.SectionTitle import com.deadzon.app.feature.dashboard.DashboardScreen import com.deadzon.app.feature.monet.MonetScreen +import com.deadzon.app.feature.monet.MonetViewModel import com.deadzon.app.feature.settings.SettingsScreen @Composable -fun DeadZonApp() { +fun DeadZonApp(vm: MonetViewModel = hiltViewModel()) { + val state by vm.uiState.collectAsState() + + if (!state.rootGateCompleted) { + RootGateScreen( + busy = state.busy, + rootAvailable = state.rootAvailable, + message = state.lastResult, + onRefresh = vm::refreshRootStatus, + onRequest = vm::requestRootFromOnboarding + ) + return + } + val navController = rememberNavController() - val tabs = listOf( - Screen.Dashboard, - Screen.Monet, - Screen.Settings - ) + val tabs = listOf(Screen.Dashboard, Screen.Monet, Screen.Settings) - Scaffold( - bottomBar = { - NavigationBar { - val navBackStackEntry by navController.currentBackStackEntryAsState() - val currentDestination = navBackStackEntry?.destination - tabs.forEach { screen -> - NavigationBarItem( - selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true, - onClick = { navController.navigate(screen.route) }, - icon = { Icon(screen.icon, contentDescription = screen.title) }, - label = { Text(screen.title) } - ) + DeadZonBackground { + Scaffold( + containerColor = Color.Transparent, + bottomBar = { + BottomActionBar { + Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) { + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentDestination = navBackStackEntry?.destination + tabs.forEach { screen -> + NavigationBarItem( + selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true, + onClick = { navController.navigate(screen.route) }, + icon = { Icon(screen.icon, contentDescription = screen.title) }, + label = { Text(screen.title) } + ) + } + } } } + ) { paddingValues -> + NavHost( + navController = navController, + startDestination = Screen.Dashboard.route, + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + ) { + composable(Screen.Dashboard.route) { DashboardScreen(navController) } + composable(Screen.Monet.route) { MonetScreen() } + composable(Screen.Settings.route) { SettingsScreen() } + } } - ) { paddingValues -> - NavHost(navController = navController, startDestination = Screen.Dashboard.route, modifier = Modifier.padding(paddingValues)) { - composable(Screen.Dashboard.route) { DashboardScreen(navController) } - composable(Screen.Monet.route) { MonetScreen() } - composable(Screen.Settings.route) { SettingsScreen() } + } +} + +@Composable +private fun RootGateScreen( + busy: Boolean, + rootAvailable: Boolean, + message: String?, + onRefresh: () -> Unit, + onRequest: () -> Unit +) { + DeadZonBackground { + Column( + modifier = Modifier + .fillMaxSize() + .padding(20.dp), + verticalArrangement = Arrangement.Center + ) { + GlassCard { + DeadZonLogoMark(modifier = Modifier.align(Alignment.CenterHorizontally)) + Spacer(modifier = Modifier.height(8.dp)) + SectionTitle( + title = "Root Access Required", + subtitle = "Dead Zon needs root to control Monet overlays internally" + ) + Text(if (rootAvailable) "Root detected. Continue." else "Tap request to trigger your root manager prompt.") + message?.let { Text(it, color = Color(0xFFFFA0A0)) } + Row(horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.fillMaxWidth()) { + OutlinedButton(onClick = onRefresh, modifier = Modifier.weight(1f)) { Text("Refresh") } + Button( + onClick = onRequest, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFB91010)) + ) { + if (busy) CircularProgressIndicator(strokeWidth = 2.dp, color = Color.White) else Text("Request Root") + } + } + } } } } diff --git a/app/src/main/java/com/deadzon/app/core/theme/DeadZonTheme.kt b/app/src/main/java/com/deadzon/app/core/theme/DeadZonTheme.kt index d9382e53..cac31ede 100644 --- a/app/src/main/java/com/deadzon/app/core/theme/DeadZonTheme.kt +++ b/app/src/main/java/com/deadzon/app/core/theme/DeadZonTheme.kt @@ -1,9 +1,7 @@ package com.deadzon.app.core.theme -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -12,21 +10,22 @@ import androidx.compose.ui.graphics.Color @Composable fun DeadZonTheme(content: @Composable () -> Unit) { val seed by ThemeSync.seed.collectAsState() - val dark = isSystemInDarkTheme() - val colorScheme = if (dark) { - darkColorScheme( - primary = seed, - secondary = seed.copy(alpha = 0.78f), - background = Color.Black, - surface = Color(0xFF080808), - tertiary = Color(0xFFB71C1C) - ) - } else { - lightColorScheme(primary = seed) - } + val colorScheme = darkColorScheme( + primary = seed, + onPrimary = Color.White, + secondary = seed.copy(alpha = 0.82f), + onSecondary = Color.White, + tertiary = Color(0xFFFF4A4A), + background = Color(0xFF020202), + surface = Color(0xFF090909), + surfaceVariant = Color(0xFF171010), + onSurface = Color(0xFFF2F2F2), + onSurfaceVariant = Color(0xFFB4A7A7) + ) MaterialTheme( colorScheme = colorScheme, + typography = MaterialTheme.typography, content = content ) } diff --git a/app/src/main/java/com/deadzon/app/core/ui/DeadZonGlass.kt b/app/src/main/java/com/deadzon/app/core/ui/DeadZonGlass.kt new file mode 100644 index 00000000..7189e56e --- /dev/null +++ b/app/src/main/java/com/deadzon/app/core/ui/DeadZonGlass.kt @@ -0,0 +1,153 @@ +package com.deadzon.app.core.ui + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp + +val AmoledBlack = Color(0xFF040404) +val GlassRed = Color(0x33FF3131) +val GlassStroke = Color(0x66FF6666) + +@Composable +fun DeadZonBackground(modifier: Modifier = Modifier, content: @Composable () -> Unit) { + Box( + modifier = modifier + .fillMaxSize() + .background( + brush = Brush.verticalGradient( + colors = listOf(Color(0xFF030303), Color(0xFF0A0303), Color(0xFF030303)) + ) + ) + ) { + content() + } +} + +@Composable +fun DeadZonLogoMark(modifier: Modifier = Modifier) { + Box( + modifier = modifier + .size(88.dp) + .clip(RoundedCornerShape(24.dp)) + .background( + brush = Brush.radialGradient( + colors = listOf(Color(0x88FF3D3D), Color(0x00FF3D3D)) + ) + ), + contentAlignment = Alignment.Center + ) { + Canvas(modifier = Modifier.size(76.dp)) { + val gradient = Brush.linearGradient(listOf(Color(0xFFFF2E2E), Color(0xFFAA0000))) + drawRoundRect( + brush = gradient, + topLeft = Offset(size.width * 0.15f, size.height * 0.1f), + size = androidx.compose.ui.geometry.Size(size.width * 0.7f, size.height * 0.8f), + cornerRadius = androidx.compose.ui.geometry.CornerRadius(26f, 26f) + ) + drawRoundRect( + color = AmoledBlack, + topLeft = Offset(size.width * 0.32f, size.height * 0.26f), + size = androidx.compose.ui.geometry.Size(size.width * 0.36f, size.height * 0.48f), + cornerRadius = androidx.compose.ui.geometry.CornerRadius(20f, 20f) + ) + drawLine( + color = AmoledBlack, + start = Offset(size.width * 0.1f, size.height * 0.86f), + end = Offset(size.width * 0.9f, size.height * 0.42f), + strokeWidth = 11f, + cap = StrokeCap.Round + ) + } + } +} + +@Composable +fun GlassCard( + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues(16.dp), + content: @Composable () -> Unit +) { + Card( + modifier = modifier + .fillMaxWidth() + .border(1.dp, GlassStroke, RoundedCornerShape(24.dp)), + shape = RoundedCornerShape(24.dp), + colors = CardDefaults.cardColors(containerColor = GlassRed) + ) { + Box( + Modifier.background( + Brush.verticalGradient( + listOf(Color(0x26FFFFFF), Color.Transparent, Color(0x22B00000)) + ) + ) + ) { + Column(modifier = Modifier.padding(contentPadding), verticalArrangement = Arrangement.spacedBy(10.dp)) { + content() + } + } + } +} + +@Composable +fun SectionTitle(title: String, subtitle: String? = null) { + Column(verticalArrangement = Arrangement.spacedBy(3.dp)) { + Text(title, style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.SemiBold) + subtitle?.let { + Text(it, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) + } + } +} + +@Composable +fun MetricChip(icon: ImageVector, title: String, value: String) { + GlassCard(contentPadding = PaddingValues(horizontal = 14.dp, vertical = 10.dp)) { + Row(horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically) { + Icon(icon, contentDescription = null, tint = Color(0xFFFF6B6B), modifier = Modifier.size(18.dp)) + Column { + Text(title, style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurfaceVariant) + Text(value, style = MaterialTheme.typography.titleMedium) + } + } + } +} + +@Composable +fun BottomActionBar(content: @Composable () -> Unit) { + Box( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)) + .background(Color(0xE0100808)) + .border(1.dp, GlassStroke, RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp)) + .padding(16.dp) + ) { + content() + } +} diff --git a/app/src/main/java/com/deadzon/app/core/ui/MonetWidgets.kt b/app/src/main/java/com/deadzon/app/core/ui/MonetWidgets.kt index e10c59cd..84b86a08 100644 --- a/app/src/main/java/com/deadzon/app/core/ui/MonetWidgets.kt +++ b/app/src/main/java/com/deadzon/app/core/ui/MonetWidgets.kt @@ -10,8 +10,9 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.Checkbox import androidx.compose.material3.FilterChip @@ -28,23 +29,24 @@ import com.deadzon.app.domain.monet.MonetTarget @Composable fun RootStatusCard(rootAvailable: Boolean) { - Card(colors = CardDefaults.cardColors(containerColor = Color(0xFF111111))) { + GlassCard { + SectionTitle("Root Access", if (rootAvailable) "Granted" else "Required") Text( - text = if (rootAvailable) "Root status: available" else "Root status: unavailable", - modifier = Modifier.padding(16.dp), - color = if (rootAvailable) Color(0xFF66BB6A) else Color(0xFFEF5350) + text = if (rootAvailable) "Overlay operations are ready." else "Grant root to continue using Dead Zon modules.", + color = if (rootAvailable) Color(0xFF7DFF9A) else Color(0xFFFF8A8A) ) } } @Composable fun PresetChips(presets: List, selectedId: String, onSelect: (String) -> Unit) { - Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) { - presets.forEach { preset -> + LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + items(presets) { preset -> FilterChip( selected = preset.id == selectedId, onClick = { onSelect(preset.id) }, - label = { Text(preset.name) } + label = { Text(preset.name) }, + border = CardDefaults.outlinedCardBorder(), ) } } @@ -52,19 +54,16 @@ fun PresetChips(presets: List, selectedId: String, onSelect: (Strin @Composable fun TargetRow(target: MonetTarget, checked: Boolean, onToggle: () -> Unit) { - Card( + GlassCard( modifier = Modifier .fillMaxWidth() - .clickable(onClick = onToggle), - colors = CardDefaults.cardColors(containerColor = Color(0xFF0F0F0F)), - shape = RoundedCornerShape(14.dp) + .clickable(onClick = onToggle) ) { Row( - modifier = Modifier.padding(14.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { - Column(modifier = Modifier.weight(1f)) { + Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(3.dp)) { Text(target.title, style = MaterialTheme.typography.titleMedium) Text(target.overlayPackage, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) } @@ -75,13 +74,13 @@ fun TargetRow(target: MonetTarget, checked: Boolean, onToggle: () -> Unit) { @Composable fun QuickSwitch(title: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit) { - Card(colors = CardDefaults.cardColors(containerColor = Color(0xFF101010))) { + GlassCard { Row( - modifier = Modifier.fillMaxWidth().padding(16.dp), + modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { - Text(title) + Text(title, style = MaterialTheme.typography.titleMedium) Switch(checked = checked, onCheckedChange = onCheckedChange) } } @@ -89,13 +88,17 @@ fun QuickSwitch(title: String, checked: Boolean, onCheckedChange: (Boolean) -> U @Composable fun ColorPreviewRow(preset: MonetPreset) { - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - preset.preview.forEach { - Box( - modifier = Modifier - .size(24.dp) - .background(it, RoundedCornerShape(50)) - ) + GlassCard { + Text("Palette Preview", style = MaterialTheme.typography.titleMedium) + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + preset.preview.forEach { + Box( + modifier = Modifier + .size(26.dp) + .background(it, RoundedCornerShape(50)) + ) + } } + Box(modifier = Modifier.fillMaxWidth().height(3.dp).background(Color(0x66FFFFFF), RoundedCornerShape(99.dp))) } } diff --git a/app/src/main/java/com/deadzon/app/data/prefs/MonetPreferences.kt b/app/src/main/java/com/deadzon/app/data/prefs/MonetPreferences.kt index 0e645403..bb358799 100644 --- a/app/src/main/java/com/deadzon/app/data/prefs/MonetPreferences.kt +++ b/app/src/main/java/com/deadzon/app/data/prefs/MonetPreferences.kt @@ -23,6 +23,7 @@ class MonetPreferences @Inject constructor( val applyToApp = booleanPreferencesKey("apply_to_app") val preset = stringPreferencesKey("preset") val targets = stringPreferencesKey("targets") + val rootGateCompleted = booleanPreferencesKey("root_gate_completed") } val state: Flow = context.monetDataStore.data.map { prefs -> @@ -31,7 +32,8 @@ class MonetPreferences @Inject constructor( applyToApp = prefs[Keys.applyToApp] ?: true, presetId = prefs[Keys.preset] ?: "stock", selectedTargets = (prefs[Keys.targets]?.split(',')?.filter { it.isNotBlank() } - ?.toSet() ?: MonetOverlayRegistry.targets.map { it.preferenceKey }.toSet()) + ?.toSet() ?: MonetOverlayRegistry.targets.map { it.preferenceKey }.toSet()), + rootGateCompleted = prefs[Keys.rootGateCompleted] ?: false ) } @@ -42,13 +44,15 @@ class MonetPreferences @Inject constructor( applyToApp = prefs[Keys.applyToApp] ?: true, presetId = prefs[Keys.preset] ?: "stock", selectedTargets = (prefs[Keys.targets]?.split(',')?.filter { it.isNotBlank() } - ?.toSet() ?: MonetOverlayRegistry.targets.map { it.preferenceKey }.toSet()) + ?.toSet() ?: MonetOverlayRegistry.targets.map { it.preferenceKey }.toSet()), + rootGateCompleted = prefs[Keys.rootGateCompleted] ?: false ) val next = transform(current) prefs[Keys.monetEnabled] = next.monetEnabled prefs[Keys.applyToApp] = next.applyToApp prefs[Keys.preset] = next.presetId prefs[Keys.targets] = next.selectedTargets.joinToString(",") + prefs[Keys.rootGateCompleted] = next.rootGateCompleted } } } @@ -57,7 +61,8 @@ data class StoredMonetState( val monetEnabled: Boolean, val applyToApp: Boolean, val presetId: String, - val selectedTargets: Set + val selectedTargets: Set, + val rootGateCompleted: Boolean ) typealias MutablePreferences = androidx.datastore.preferences.core.MutablePreferences diff --git a/app/src/main/java/com/deadzon/app/domain/monet/MonetModels.kt b/app/src/main/java/com/deadzon/app/domain/monet/MonetModels.kt index ed4c714d..39cbbbc4 100644 --- a/app/src/main/java/com/deadzon/app/domain/monet/MonetModels.kt +++ b/app/src/main/java/com/deadzon/app/domain/monet/MonetModels.kt @@ -43,5 +43,6 @@ data class MonetUiState( val rootAvailable: Boolean = false, val busy: Boolean = false, val logs: List = emptyList(), - val lastResult: String? = null + val lastResult: String? = null, + val rootGateCompleted: Boolean = false ) diff --git a/app/src/main/java/com/deadzon/app/feature/dashboard/DashboardScreen.kt b/app/src/main/java/com/deadzon/app/feature/dashboard/DashboardScreen.kt index 1eb9159b..103c25c0 100644 --- a/app/src/main/java/com/deadzon/app/feature/dashboard/DashboardScreen.kt +++ b/app/src/main/java/com/deadzon/app/feature/dashboard/DashboardScreen.kt @@ -2,42 +2,79 @@ package com.deadzon.app.feature.dashboard import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AutoFixHigh +import androidx.compose.material.icons.filled.Palette +import androidx.compose.material.icons.filled.Verified import androidx.compose.material3.Button -import androidx.compose.material3.Card -import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.deadzon.app.app.Screen +import com.deadzon.app.core.ui.DeadZonBackground +import com.deadzon.app.core.ui.DeadZonLogoMark +import com.deadzon.app.core.ui.GlassCard +import com.deadzon.app.core.ui.MetricChip +import com.deadzon.app.core.ui.SectionTitle import com.deadzon.app.feature.monet.MonetViewModel @Composable fun DashboardScreen(navController: NavController, vm: MonetViewModel = hiltViewModel()) { val state by vm.uiState.collectAsState() - Column(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) { - Text("Dead Zon", style = MaterialTheme.typography.headlineLarge) - Card(modifier = Modifier.padding(top = 8.dp)) { - Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { - Text("Monet status: ${if (state.monetEnabled) "Enabled" else "Disabled"}") - Text("Selected targets: ${state.selectedTargets.size}") - Text("Active preset: ${state.selectedPresetId}") + + DeadZonBackground { + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + GlassCard { + Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { + DeadZonLogoMark() + Column(verticalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.padding(top = 8.dp)) { + Text("DEAD ZON") + Text("Premium Overlay Control", color = Color(0xFFB9A6A6)) + } + } } - } - Button(onClick = { vm.apply(false) }) { Text("Quick Apply") } - Button(onClick = { navController.navigate(Screen.Monet.route) }) { Text("Open Monet Screen") } - Card { - Column(modifier = Modifier.padding(16.dp)) { - Text("Future modules", style = MaterialTheme.typography.titleMedium) - Text("• Performance (coming soon)") - Text("• Thermal profiles (coming soon)") - Text("• Network tuning (coming soon)") + + Row(horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.fillMaxWidth()) { + Column(Modifier.weight(1f)) { + MetricChip(Icons.Default.Verified, "Monet", if (state.monetEnabled) "Enabled" else "Disabled") + } + Column(Modifier.weight(1f)) { + MetricChip(Icons.Default.Palette, "Preset", state.selectedPresetId.uppercase()) + } + } + + MetricChip(Icons.Default.AutoFixHigh, "Selected Targets", state.selectedTargets.size.toString()) + + Row(horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.fillMaxWidth()) { + Button( + onClick = { vm.apply(false) }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFB91010)) + ) { Text("Quick Apply") } + Button(onClick = { navController.navigate(Screen.Monet.route) }, modifier = Modifier.weight(1f)) { Text("Open Monet") } + } + + GlassCard { + SectionTitle("Future Modules", "Temporary placeholders for this visual pass") + Text("• Performance profiles") + Text("• Thermal manager") + Text("• Network tuning") } } } diff --git a/app/src/main/java/com/deadzon/app/feature/monet/MonetScreen.kt b/app/src/main/java/com/deadzon/app/feature/monet/MonetScreen.kt index 55c079e0..9c6e35a2 100644 --- a/app/src/main/java/com/deadzon/app/feature/monet/MonetScreen.kt +++ b/app/src/main/java/com/deadzon/app/feature/monet/MonetScreen.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField @@ -17,58 +18,95 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import com.deadzon.app.core.ui.BottomActionBar import com.deadzon.app.core.ui.ColorPreviewRow +import com.deadzon.app.core.ui.DeadZonBackground +import com.deadzon.app.core.ui.GlassCard import com.deadzon.app.core.ui.PresetChips import com.deadzon.app.core.ui.QuickSwitch import com.deadzon.app.core.ui.RootStatusCard +import com.deadzon.app.core.ui.SectionTitle import com.deadzon.app.core.ui.TargetRow @Composable fun MonetScreen(vm: MonetViewModel = hiltViewModel()) { val state by vm.uiState.collectAsState() - val selectedPreset = vm.presets.firstOrNull { it.id == state.selectedPresetId } ?: vm.presets.first() - Column(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { - Text("Monet Control", style = MaterialTheme.typography.headlineMedium) - RootStatusCard(rootAvailable = state.rootAvailable) - QuickSwitch("Master Monet switch", state.monetEnabled, vm::onMonetToggle) - QuickSwitch("Apply palette to Dead Zon", state.applyToApp, vm::onApplyToAppToggle) - PresetChips(vm.presets, state.selectedPresetId, vm::onPresetSelect) - ColorPreviewRow(selectedPreset) - - OutlinedTextField( - value = state.searchQuery, - onValueChange = vm::onSearchChange, - modifier = Modifier.fillMaxWidth(), - label = { Text("Search targets") } - ) - - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - Button(onClick = vm::selectAll) { Text("Select All") } - Button(onClick = vm::clearAll) { Text("Clear All") } - Button(onClick = { vm.apply(restartSystemUi = false) }) { Text("Apply") } - Button(onClick = vm::reset) { Text("Reset") } - } - - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - Button(onClick = { vm.apply(restartSystemUi = true) }) { Text("Apply + Restart SystemUI") } - if (state.busy) CircularProgressIndicator() - } - - state.lastResult?.let { Text(it, color = MaterialTheme.colorScheme.primary) } - - LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) { - val filtered = vm.targets.filter { - it.title.contains(state.searchQuery, true) || it.overlayPackage.contains(state.searchQuery, true) + DeadZonBackground { + Column(modifier = Modifier.fillMaxSize()) { + LazyColumn( + modifier = Modifier + .weight(1f) + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + item { + SectionTitle("Monet Control", "Temporary redesign pass inspired by red glass mockup") + } + item { RootStatusCard(rootAvailable = state.rootAvailable) } + item { QuickSwitch("Master Monet Switch", state.monetEnabled, vm::onMonetToggle) } + item { QuickSwitch("Apply to Dead Zon App", state.applyToApp, vm::onApplyToAppToggle) } + item { + GlassCard { + Text("Preset Palette", style = MaterialTheme.typography.titleMedium) + PresetChips(vm.presets, state.selectedPresetId, vm::onPresetSelect) + } + } + item { + val selectedPreset = vm.presets.firstOrNull { it.id == state.selectedPresetId } ?: vm.presets.first() + ColorPreviewRow(selectedPreset) + } + item { + GlassCard { + OutlinedTextField( + value = state.searchQuery, + onValueChange = vm::onSearchChange, + modifier = Modifier.fillMaxWidth(), + label = { Text("Search target app / package") } + ) + } + } + item { + Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) { + Button(onClick = vm::selectAll, modifier = Modifier.weight(1f)) { Text("Select All") } + Button(onClick = vm::clearAll, modifier = Modifier.weight(1f)) { Text("Clear All") } + } + } + val filtered = vm.targets.filter { + it.title.contains(state.searchQuery, true) || it.overlayPackage.contains(state.searchQuery, true) + } + items(filtered, key = { it.preferenceKey }) { target -> + TargetRow( + target = target, + checked = target.preferenceKey in state.selectedTargets, + onToggle = { vm.toggleTarget(target.preferenceKey) } + ) + } + item { + state.lastResult?.let { + GlassCard { Text(it, color = MaterialTheme.colorScheme.primary) } + } + } } - items(filtered, key = { it.preferenceKey }) { target -> - TargetRow( - target = target, - checked = target.preferenceKey in state.selectedTargets, - onToggle = { vm.toggleTarget(target.preferenceKey) } - ) + + BottomActionBar { + Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) { + Button( + onClick = { vm.apply(false) }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFB91010)) + ) { Text("Apply") } + Button(onClick = vm::reset, modifier = Modifier.weight(1f)) { Text("Reset") } + } + Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) { + Button(onClick = { vm.apply(true) }, modifier = Modifier.weight(1f)) { + Text("Apply + Restart SystemUI") + } + if (state.busy) CircularProgressIndicator(strokeWidth = 2.dp) + } } } } diff --git a/app/src/main/java/com/deadzon/app/feature/monet/MonetViewModel.kt b/app/src/main/java/com/deadzon/app/feature/monet/MonetViewModel.kt index 86878b31..96f6fe5f 100644 --- a/app/src/main/java/com/deadzon/app/feature/monet/MonetViewModel.kt +++ b/app/src/main/java/com/deadzon/app/feature/monet/MonetViewModel.kt @@ -42,9 +42,27 @@ class MonetViewModel @Inject constructor( } } + fun requestRootFromOnboarding() { + viewModelScope.launch { + _uiState.update { it.copy(busy = true, lastResult = null) } + val hasRoot = controller.hasRoot() + prefs.update { it.copy(rootGateCompleted = hasRoot) } + _uiState.update { + it.copy( + busy = false, + rootAvailable = hasRoot, + rootGateCompleted = hasRoot, + lastResult = if (hasRoot) "Root access granted" else "Root access is required to continue" + ) + } + } + } + fun onMonetToggle(value: Boolean) = persist { copy(monetEnabled = value) } fun onApplyToAppToggle(value: Boolean) = persist { copy(applyToApp = value) } - fun onSearchChange(query: String) { _uiState.update { it.copy(searchQuery = query) } } + fun onSearchChange(query: String) { + _uiState.update { it.copy(searchQuery = query) } + } fun onPresetSelect(id: String) = persist { val preset = presets.firstOrNull { it.id == id } @@ -85,10 +103,17 @@ class MonetViewModel @Inject constructor( monetEnabled = false, applyToApp = true, presetId = "stock", - selectedTargets = emptySet() + selectedTargets = emptySet(), + rootGateCompleted = it.rootGateCompleted + ) + } + _uiState.update { + it.copy( + busy = false, + logs = (result.logs + it.logs).takeLast(200), + lastResult = "Reset completed" ) } - _uiState.update { it.copy(busy = false, logs = (result.logs + it.logs).takeLast(200), lastResult = "Reset completed") } } } @@ -104,7 +129,8 @@ class MonetViewModel @Inject constructor( monetEnabled = stored.monetEnabled, applyToApp = stored.applyToApp, selectedPresetId = stored.presetId, - selectedTargets = stored.selectedTargets + selectedTargets = stored.selectedTargets, + rootGateCompleted = stored.rootGateCompleted ) } } diff --git a/app/src/main/java/com/deadzon/app/feature/settings/SettingsScreen.kt b/app/src/main/java/com/deadzon/app/feature/settings/SettingsScreen.kt index ec71c235..3cecf1e2 100644 --- a/app/src/main/java/com/deadzon/app/feature/settings/SettingsScreen.kt +++ b/app/src/main/java/com/deadzon/app/feature/settings/SettingsScreen.kt @@ -3,20 +3,41 @@ package com.deadzon.app.feature.settings import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.deadzon.app.core.ui.DeadZonBackground +import com.deadzon.app.core.ui.DeadZonLogoMark +import com.deadzon.app.core.ui.GlassCard +import com.deadzon.app.core.ui.SectionTitle @Composable fun SettingsScreen() { - Column(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { - Text("Settings", style = MaterialTheme.typography.headlineMedium) - Text("Dead Zon v1 keeps all Monet controls inside this app. No external ThemePicker or ThemesStub runtime dependency.") - Button(onClick = { }) { Text("Export profile (planned)") } - Button(onClick = { }) { Text("Import profile (planned)") } + DeadZonBackground { + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + GlassCard { + DeadZonLogoMark() + SectionTitle("Settings", "Temporary premium visual pass") + Text("Dead Zon keeps Monet and overlay controls fully in-app without ThemePicker or ThemesStub runtime dependency.") + } + GlassCard { + Text("Profiles", style = androidx.compose.material3.MaterialTheme.typography.titleMedium) + Button(onClick = {}, modifier = Modifier.fillMaxWidth()) { Text("Export Profile (placeholder)") } + Button(onClick = {}, modifier = Modifier.fillMaxWidth()) { Text("Import Profile (placeholder)") } + } + GlassCard { + Text("About") + Text("Version 1 visual redesign preview") + } + } } }