Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 104 additions & 24 deletions app/src/main/java/com/deadzon/app/app/DeadZonApp.kt
Original file line number Diff line number Diff line change
@@ -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")
}
}
}
}
}
}
27 changes: 13 additions & 14 deletions app/src/main/java/com/deadzon/app/core/theme/DeadZonTheme.kt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
)
}
153 changes: 153 additions & 0 deletions app/src/main/java/com/deadzon/app/core/ui/DeadZonGlass.kt
Original file line number Diff line number Diff line change
@@ -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()
}
}
Loading
Loading