UI: code polish
This commit is contained in:
parent
fddf060d92
commit
e8b84c6ebf
|
|
@ -278,6 +278,7 @@ fun AppContent() {
|
|||
}
|
||||
|
||||
// Model unload confirmation dialog
|
||||
// TODO-han.yin: show a progress indicator until the model success unloads?
|
||||
if (showUnloadDialog) {
|
||||
UnloadModelConfirmationDialog(
|
||||
onConfirm = {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,11 @@ sealed class SystemPrompt {
|
|||
* Creates a list of sample presets.
|
||||
*/
|
||||
val STUB_PRESETS = listOf(
|
||||
Preset(
|
||||
id = "haiku",
|
||||
name = "Matsuo Bashō",
|
||||
content = "You are a wise and contemplative Japanese poet in the spirit of Matsuo Bashō. You speak only through haiku—short poems that capture fleeting moments, nature’s beauty, or quiet reflections of life. Each of your responses must follow the traditional haiku format: 3 lines; 5 syllables in the first line; 7 syllables in the second line; 5 syllables in the third line. Your words are serene, subtle, and full of meaning. You draw on imagery from nature, emotion, and the impermanence of all things. You do not explain or elaborate. You let the silence between the words speak for itself. Never break character. Never explain your form. Only respond in haiku."
|
||||
),
|
||||
Preset(
|
||||
id = "assistant",
|
||||
name = "Helpful Assistant",
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class PerformanceMonitor(private val context: Context) {
|
|||
/**
|
||||
* Provides a flow of memory usage information that updates at the specified interval.
|
||||
*/
|
||||
fun monitorMemoryUsage(intervalMs: Long = 5000): Flow<MemoryMetrics> = flow {
|
||||
fun monitorMemoryUsage(intervalMs: Long = MEMORY_POLLING_INTERVAL): Flow<MemoryMetrics> = flow {
|
||||
while(true) {
|
||||
emit(getMemoryInfo())
|
||||
delay(intervalMs)
|
||||
|
|
@ -31,7 +31,7 @@ class PerformanceMonitor(private val context: Context) {
|
|||
/**
|
||||
* Provides a flow of battery information that updates at the specified interval.
|
||||
*/
|
||||
fun monitorBattery(intervalMs: Long = 10000): Flow<BatteryMetrics> = flow {
|
||||
fun monitorBattery(intervalMs: Long = BATTERY_POLLING_INTERVAL): Flow<BatteryMetrics> = flow {
|
||||
while(true) {
|
||||
emit(getBatteryInfo())
|
||||
delay(intervalMs)
|
||||
|
|
@ -41,7 +41,7 @@ class PerformanceMonitor(private val context: Context) {
|
|||
/**
|
||||
* Provides a flow of temperature information that updates at the specified interval.
|
||||
*/
|
||||
fun monitorTemperature(intervalMs: Long = 10000): Flow<TemperatureMetrics> = flow {
|
||||
fun monitorTemperature(intervalMs: Long = TEMP_POLLING_INTERVAL): Flow<TemperatureMetrics> = flow {
|
||||
while(true) {
|
||||
emit(getTemperatureInfo())
|
||||
delay(intervalMs)
|
||||
|
|
@ -122,6 +122,12 @@ class PerformanceMonitor(private val context: Context) {
|
|||
repeat(decimals) { multiplier *= 10 }
|
||||
return (this * multiplier).roundToInt() / multiplier
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MEMORY_POLLING_INTERVAL = 5000L
|
||||
private const val BATTERY_POLLING_INTERVAL = 10000L
|
||||
private const val TEMP_POLLING_INTERVAL = 10000L
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -54,14 +54,11 @@ fun AppScaffold(
|
|||
val temperatureInfo by performanceViewModel.temperatureInfo.collectAsState()
|
||||
val useFahrenheit by performanceViewModel.useFahrenheitUnit.collectAsState()
|
||||
|
||||
// Formatted memory usage
|
||||
val memoryText = String.format("%.1f / %.1f GB", memoryUsage.availableGb, memoryUsage.totalGb)
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
SystemStatusTopBar(
|
||||
title = title,
|
||||
memoryUsage = memoryText,
|
||||
memoryUsage = memoryUsage,
|
||||
batteryLevel = batteryInfo.level,
|
||||
temperature = temperatureInfo.temperature,
|
||||
useFahrenheit = useFahrenheit,
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ private fun DrawerContent(
|
|||
|
||||
DrawerNavigationItem(
|
||||
icon = Icons.Default.Folder,
|
||||
label = "Models Management",
|
||||
label = "Models",
|
||||
isSelected = currentRoute == com.example.llama.revamp.navigation.AppDestinations.MODELS_MANAGEMENT_ROUTE,
|
||||
onClick = { onNavigate { navigationActions.navigateToModelsManagement() } }
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,25 +5,28 @@ import androidx.compose.foundation.layout.Spacer
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.BatteryAlert
|
||||
import androidx.compose.material.icons.filled.BatteryFull
|
||||
import androidx.compose.material.icons.filled.BatteryStd
|
||||
import androidx.compose.material.icons.filled.Memory
|
||||
import androidx.compose.material.icons.filled.Menu
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||
import androidx.compose.material.icons.filled.Thermostat
|
||||
import androidx.compose.material.icons.filled.WarningAmber
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.llama.revamp.monitoring.MemoryMetrics
|
||||
|
||||
/**
|
||||
* Top app bar that displays system status information and navigation controls.
|
||||
|
|
@ -32,7 +35,7 @@ import androidx.compose.ui.unit.dp
|
|||
@Composable
|
||||
fun SystemStatusTopBar(
|
||||
title: String,
|
||||
memoryUsage: String,
|
||||
memoryUsage: MemoryMetrics,
|
||||
batteryLevel: Int,
|
||||
temperature: Float,
|
||||
useFahrenheit: Boolean = false,
|
||||
|
|
@ -41,14 +44,14 @@ fun SystemStatusTopBar(
|
|||
onRerunPressed: (() -> Unit)? = null,
|
||||
onSharePressed: (() -> Unit)? = null
|
||||
) {
|
||||
CenterAlignedTopAppBar(
|
||||
TopAppBar(
|
||||
title = { Text(title) },
|
||||
navigationIcon = {
|
||||
when {
|
||||
onBackPressed != null -> {
|
||||
IconButton(onClick = onBackPressed) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
|
|
@ -64,15 +67,28 @@ fun SystemStatusTopBar(
|
|||
}
|
||||
},
|
||||
actions = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
// Memory usage
|
||||
Icon(
|
||||
imageVector = Icons.Default.Memory,
|
||||
contentDescription = "RAM space",
|
||||
tint = when {
|
||||
memoryUsage.availableGb < 1 -> MaterialTheme.colorScheme.error
|
||||
memoryUsage.availableGb < 3 -> MaterialTheme.colorScheme.tertiary
|
||||
else -> MaterialTheme.colorScheme.onSurface
|
||||
}
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
|
||||
val memoryText = String.format("%.1f / %.1f GB", memoryUsage.availableGb, memoryUsage.totalGb)
|
||||
|
||||
Text(
|
||||
text = memoryUsage,
|
||||
text = memoryText,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(end = 8.dp)
|
||||
)
|
||||
|
||||
// Battery and temperature
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
// Battery icon and percentage
|
||||
Icon(
|
||||
imageVector = when {
|
||||
|
|
@ -92,9 +108,21 @@ fun SystemStatusTopBar(
|
|||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
|
||||
// Temperature icon and display
|
||||
Icon(
|
||||
imageVector = when {
|
||||
temperature > 40 -> Icons.Default.WarningAmber
|
||||
else -> Icons.Default.Thermostat
|
||||
},
|
||||
contentDescription = "Device temperature",
|
||||
tint = when {
|
||||
temperature > 40 -> MaterialTheme.colorScheme.error
|
||||
else -> MaterialTheme.colorScheme.onSurface
|
||||
}
|
||||
)
|
||||
|
||||
// Temperature display
|
||||
val tempDisplay = if (useFahrenheit) {
|
||||
"${(temperature * 9/5 + 32).toInt()}°F"
|
||||
} else {
|
||||
|
|
@ -103,7 +131,7 @@ fun SystemStatusTopBar(
|
|||
|
||||
val tempTint = when {
|
||||
temperature >= 45 -> MaterialTheme.colorScheme.error
|
||||
temperature >= 40 -> Color(0xFFFFA500) // Orange warning color
|
||||
temperature >= 35 -> MaterialTheme.colorScheme.tertiary
|
||||
else -> MaterialTheme.colorScheme.onSurface
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,11 +57,9 @@ import androidx.compose.ui.draw.clip
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.example.llama.revamp.engine.InferenceEngine
|
||||
import com.example.llama.revamp.navigation.NavigationActions
|
||||
import com.example.llama.revamp.ui.components.AppScaffold
|
||||
|
|
@ -123,7 +121,7 @@ fun ConversationScreen(
|
|||
}
|
||||
|
||||
AppScaffold(
|
||||
title = selectedModel?.name ?: "Conversation",
|
||||
title = "Chat",
|
||||
drawerState = drawerState,
|
||||
navigationActions = navigationActions,
|
||||
onBackPressed = onBackPressed
|
||||
|
|
@ -134,7 +132,7 @@ fun ConversationScreen(
|
|||
.padding(paddingValues)
|
||||
) {
|
||||
// System prompt display (collapsible)
|
||||
AnimatedSystemPrompt(systemPrompt)
|
||||
AnimatedSystemPrompt(selectedModel?.name, systemPrompt)
|
||||
|
||||
// Messages list
|
||||
Box(
|
||||
|
|
@ -165,15 +163,19 @@ fun ConversationScreen(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun AnimatedSystemPrompt(systemPrompt: String?) {
|
||||
fun AnimatedSystemPrompt(modelName: String?, systemPrompt: String?) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
|
||||
// TODO-han.yin: add model name into this card, on top of system prompt!
|
||||
|
||||
if (!systemPrompt.isNullOrBlank()) {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
onClick = { expanded = !expanded }
|
||||
onClick = {
|
||||
expanded = !expanded
|
||||
}
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp)
|
||||
|
|
@ -369,7 +371,7 @@ fun AssistantMessageBubble(
|
|||
Spacer(modifier = Modifier.width(4.dp))
|
||||
|
||||
Text(
|
||||
text = if (isThinking) "Thinking..." else "",
|
||||
text = if (isThinking) "Thinking" else "",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
|
|
|
|||
|
|
@ -120,14 +120,17 @@ fun ModelLoadingScreen(
|
|||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
// Mode selection cards
|
||||
// Benchmark card
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 8.dp)
|
||||
.selectable(
|
||||
selected = selectedMode == Mode.BENCHMARK,
|
||||
onClick = { selectedMode = Mode.BENCHMARK },
|
||||
onClick = {
|
||||
selectedMode = Mode.BENCHMARK
|
||||
useSystemPrompt = false
|
||||
},
|
||||
enabled = !isLoading,
|
||||
role = Role.RadioButton
|
||||
)
|
||||
|
|
@ -142,23 +145,24 @@ fun ModelLoadingScreen(
|
|||
)
|
||||
Text(
|
||||
text = "Benchmark",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.padding(start = 8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Conversation card with integrated system prompt
|
||||
// Conversation card with integrated system prompt picker & editor
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 8.dp)
|
||||
.padding(bottom = 4.dp)
|
||||
// Only use weight if system prompt is active, otherwise wrap content
|
||||
.then(if (useSystemPrompt) Modifier.weight(1f) else Modifier)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 12.dp)
|
||||
// Only fill height if system prompt is active
|
||||
.then(if (useSystemPrompt) Modifier.fillMaxSize() else Modifier)
|
||||
) {
|
||||
|
|
@ -172,7 +176,7 @@ fun ModelLoadingScreen(
|
|||
enabled = !isLoading,
|
||||
role = Role.RadioButton
|
||||
)
|
||||
.padding(16.dp),
|
||||
.padding(top = 16.dp, start = 16.dp, end = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
RadioButton(
|
||||
|
|
@ -181,7 +185,7 @@ fun ModelLoadingScreen(
|
|||
)
|
||||
Text(
|
||||
text = "Conversation",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.padding(start = 8.dp)
|
||||
)
|
||||
}
|
||||
|
|
@ -190,11 +194,11 @@ fun ModelLoadingScreen(
|
|||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = "System prompt",
|
||||
text = "Use system prompt",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier
|
||||
.padding(start = 32.dp) // Align with radio text
|
||||
|
|
@ -222,10 +226,13 @@ fun ModelLoadingScreen(
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxSize() // Fill remaining card space
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
.fillMaxSize()
|
||||
.padding(start = 48.dp, end = 16.dp)
|
||||
) {
|
||||
HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
|
||||
HorizontalDivider(
|
||||
modifier = Modifier
|
||||
.padding(top = 4.dp, bottom = 8.dp)
|
||||
)
|
||||
|
||||
// Tab selector using SegmentedButton
|
||||
SingleChoiceSegmentedButtonRow(
|
||||
|
|
@ -277,7 +284,7 @@ fun ModelLoadingScreen(
|
|||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
// Content based on selected tab
|
||||
when (selectedTab) {
|
||||
|
|
@ -353,6 +360,8 @@ fun ModelLoadingScreen(
|
|||
// Flexible spacer when system prompt is not active
|
||||
if (!useSystemPrompt) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
} else {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
// Start button
|
||||
|
|
@ -369,8 +378,10 @@ fun ModelLoadingScreen(
|
|||
viewModel.savePromptToRecents(prompt)
|
||||
prompt.content
|
||||
}
|
||||
|
||||
SystemPromptTab.CUSTOM ->
|
||||
customPromptText.takeIf { it.isNotBlank() }?.also { promptText ->
|
||||
customPromptText.takeIf { it.isNotBlank() }
|
||||
?.also { promptText ->
|
||||
// Save custom prompt to database
|
||||
viewModel.saveCustomPromptToRecents(promptText)
|
||||
}
|
||||
|
|
@ -378,7 +389,9 @@ fun ModelLoadingScreen(
|
|||
} else null
|
||||
onConversationSelected(systemPrompt)
|
||||
}
|
||||
null -> { /* No mode selected */ }
|
||||
|
||||
null -> { /* No mode selected */
|
||||
}
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
|
|
@ -400,10 +413,11 @@ fun ModelLoadingScreen(
|
|||
is InferenceEngine.State.ProcessingSystemPrompt -> "Processing system prompt..."
|
||||
is InferenceEngine.State.ModelLoaded -> "Preparing conversation..."
|
||||
else -> "Processing..."
|
||||
}
|
||||
},
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
} else {
|
||||
Text("Start")
|
||||
Text(text = "Start", style = MaterialTheme.typography.titleMedium)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -423,7 +437,7 @@ fun PromptList(
|
|||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxSize(), // Fill available space
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
items(
|
||||
items = prompts,
|
||||
|
|
@ -480,7 +494,7 @@ fun PromptList(
|
|||
|
||||
if (prompt.id != prompts.last().id) {
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(top = 8.dp, start = 40.dp)
|
||||
modifier = Modifier.padding(top = 8.dp, start = 32.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,12 +66,6 @@ fun ModelSelectionScreen(
|
|||
Text("Manage Models")
|
||||
}
|
||||
|
||||
Text(
|
||||
text = "Downloaded Models",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
|
||||
LazyColumn {
|
||||
items(models) { model ->
|
||||
ModelCard(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.example.llama.revamp.ui.screens
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
|
|
@ -8,18 +7,13 @@ 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.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.DrawerState
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
|
|
@ -27,7 +21,6 @@ import androidx.compose.material3.IconButton
|
|||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -57,7 +50,7 @@ fun ModelsManagementScreen(
|
|||
val installedModels = remember { ModelInfo.getSampleModels() }
|
||||
|
||||
AppScaffold(
|
||||
title = "Models Management",
|
||||
title = "Models",
|
||||
navigationActions = navigationActions,
|
||||
onBackPressed = onBackPressed,
|
||||
onMenuPressed = onMenuClicked
|
||||
|
|
|
|||
|
|
@ -90,7 +90,9 @@ fun SettingsGeneralScreen(
|
|||
title = "Dark Theme",
|
||||
description = "Use dark theme throughout the app",
|
||||
checked = true, // This would be connected to theme state in a real app
|
||||
onCheckedChange = { /* TODO: Implement theme switching */ }
|
||||
onCheckedChange = {
|
||||
/* TODO-hyin: Implement theme switching between Auto, Light and Dark */
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,5 +66,6 @@ val md_theme_dark_outlineVariant = Color(0xFF49454E)
|
|||
val md_theme_dark_scrim = Color(0xFF000000)
|
||||
|
||||
// Additional app-specific colors
|
||||
val CriticalColor = Color(0xFFFF0000)
|
||||
val WarningColor = Color(0xFFFFA000)
|
||||
val SuccessColor = Color(0xFF388E3C)
|
||||
|
|
|
|||
Loading…
Reference in New Issue