pkg: restructure TopBarApps into separate files in a child package

This commit is contained in:
Han Yin 2025-04-21 19:11:27 -07:00
parent 3c539dc146
commit b1831c4053
7 changed files with 329 additions and 273 deletions

View File

@ -38,11 +38,11 @@ import com.example.llama.revamp.navigation.NavigationActions
import com.example.llama.revamp.ui.scaffold.AnimatedNavHost import com.example.llama.revamp.ui.scaffold.AnimatedNavHost
import com.example.llama.revamp.ui.scaffold.AppNavigationDrawer import com.example.llama.revamp.ui.scaffold.AppNavigationDrawer
import com.example.llama.revamp.ui.scaffold.AppScaffold import com.example.llama.revamp.ui.scaffold.AppScaffold
import com.example.llama.revamp.ui.scaffold.NavigationIcon
import com.example.llama.revamp.ui.scaffold.ScaffoldConfig import com.example.llama.revamp.ui.scaffold.ScaffoldConfig
import com.example.llama.revamp.ui.scaffold.ScaffoldEvent import com.example.llama.revamp.ui.scaffold.ScaffoldEvent
import com.example.llama.revamp.ui.scaffold.TopBarConfig
import com.example.llama.revamp.ui.scaffold.bottombar.BottomBarConfig import com.example.llama.revamp.ui.scaffold.bottombar.BottomBarConfig
import com.example.llama.revamp.ui.scaffold.topbar.NavigationIcon
import com.example.llama.revamp.ui.scaffold.topbar.TopBarConfig
import com.example.llama.revamp.ui.screens.BenchmarkScreen import com.example.llama.revamp.ui.screens.BenchmarkScreen
import com.example.llama.revamp.ui.screens.ConversationScreen import com.example.llama.revamp.ui.screens.ConversationScreen
import com.example.llama.revamp.ui.screens.ModelLoadingScreen import com.example.llama.revamp.ui.screens.ModelLoadingScreen

View File

@ -12,6 +12,11 @@ import com.example.llama.revamp.ui.scaffold.bottombar.BottomBarConfig
import com.example.llama.revamp.ui.scaffold.bottombar.ConversationBottomBar import com.example.llama.revamp.ui.scaffold.bottombar.ConversationBottomBar
import com.example.llama.revamp.ui.scaffold.bottombar.ModelSelectionBottomBar import com.example.llama.revamp.ui.scaffold.bottombar.ModelSelectionBottomBar
import com.example.llama.revamp.ui.scaffold.bottombar.ModelsManagementBottomBar import com.example.llama.revamp.ui.scaffold.bottombar.ModelsManagementBottomBar
import com.example.llama.revamp.ui.scaffold.topbar.DefaultTopBar
import com.example.llama.revamp.ui.scaffold.topbar.NavigationIcon
import com.example.llama.revamp.ui.scaffold.topbar.PerformanceTopBar
import com.example.llama.revamp.ui.scaffold.topbar.StorageTopBar
import com.example.llama.revamp.ui.scaffold.topbar.TopBarConfig
/** /**
* Configuration of both [TopBarConfig] and [BottomBarConfig] * Configuration of both [TopBarConfig] and [BottomBarConfig]

View File

@ -1,271 +0,0 @@
package com.example.llama.revamp.ui.scaffold
import androidx.compose.foundation.layout.Row
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.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Memory
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.SdStorage
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.unit.dp
import com.example.llama.revamp.data.repository.StorageMetrics
import com.example.llama.revamp.monitoring.MemoryMetrics
import com.example.llama.revamp.monitoring.TemperatureMetrics
import com.example.llama.revamp.monitoring.TemperatureWarningLevel
import java.util.Locale
/**
* [TopAppBar] configurations
*/
sealed class TopBarConfig {
abstract val title: String
abstract val navigationIcon: NavigationIcon
// No top bar at all
data class None(
override val title: String = "",
override val navigationIcon: NavigationIcon = NavigationIcon.None
) : TopBarConfig()
// Default/simple top bar with only a navigation icon
data class Default(
override val title: String,
override val navigationIcon: NavigationIcon
) : TopBarConfig()
// Performance monitoring top bar with RAM and optional temperature
data class Performance(
override val title: String,
override val navigationIcon: NavigationIcon,
val memoryMetrics: MemoryMetrics,
val temperatureInfo: Pair<TemperatureMetrics, Boolean>?,
) : TopBarConfig()
// Storage management top bar with used & total storage
data class Storage(
override val title: String,
override val navigationIcon: NavigationIcon,
val storageMetrics: StorageMetrics?
) : TopBarConfig()
}
/**
* Helper class for navigation icon configuration
*/
sealed class NavigationIcon {
data class Back(val onNavigateBack: () -> Unit) : NavigationIcon()
data class Menu(val onMenuOpen: () -> Unit) : NavigationIcon()
object None : NavigationIcon()
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DefaultTopBar(
title: String,
onNavigateBack: (() -> Unit)? = null,
onMenuOpen: (() -> Unit)? = null
) {
TopAppBar(
title = { Text(title) },
navigationIcon = {
when {
onNavigateBack != null -> {
IconButton(onClick = onNavigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back"
)
}
}
onMenuOpen != null -> {
IconButton(onClick = onMenuOpen) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = "Menu"
)
}
}
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
titleContentColor = MaterialTheme.colorScheme.onSurface
)
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PerformanceTopBar(
title: String,
memoryMetrics: MemoryMetrics,
temperatureDisplay: Pair<TemperatureMetrics, Boolean>?,
onNavigateBack: (() -> Unit)? = null,
onMenuOpen: (() -> Unit)? = null,
) {
TopAppBar(
title = { Text(title) },
navigationIcon = {
when {
onNavigateBack != null -> {
IconButton(onClick = onNavigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back"
)
}
}
onMenuOpen != null -> {
IconButton(onClick = onMenuOpen) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = "Menu"
)
}
}
}
},
actions = {
// Temperature indicator (optional)
temperatureDisplay?.let { (temperatureMetrics, useFahrenheit) ->
TemperatureIndicator(
temperatureMetrics = temperatureMetrics,
useFahrenheit = useFahrenheit
)
Spacer(modifier = Modifier.width(8.dp))
}
// Memory indicator
MemoryIndicator(memoryUsage = memoryMetrics)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
titleContentColor = MaterialTheme.colorScheme.onSurface
)
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StorageTopBar(
title: String,
storageMetrics: StorageMetrics?,
onNavigateBack: (() -> Unit)? = null,
) {
TopAppBar(
title = { Text(title) },
navigationIcon = {
if (onNavigateBack != null) {
IconButton(onClick = onNavigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back"
)
}
}
},
actions = {
storageMetrics?.let {
StorageIndicator(storageMetrics = it)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
titleContentColor = MaterialTheme.colorScheme.onSurface
)
)
}
@Composable
fun MemoryIndicator(memoryUsage: MemoryMetrics) {
Row(modifier = Modifier.padding(end = 8.dp), verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Default.Memory,
contentDescription = "RAM usage",
tint = when {
memoryUsage.availableGb < 1 -> MaterialTheme.colorScheme.error
memoryUsage.availableGb < 3 -> MaterialTheme.colorScheme.tertiary
else -> MaterialTheme.colorScheme.onSurface
}
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = String.format(
Locale.getDefault(), "%.1f / %.1f GB", memoryUsage.availableGb, memoryUsage.totalGb
),
style = MaterialTheme.typography.bodySmall,
)
}
}
@Composable
fun TemperatureIndicator(temperatureMetrics: TemperatureMetrics, useFahrenheit: Boolean) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = when (temperatureMetrics.warningLevel) {
TemperatureWarningLevel.HIGH -> Icons.Default.WarningAmber
else -> Icons.Default.Thermostat
},
contentDescription = "Device temperature",
tint = when (temperatureMetrics.warningLevel) {
TemperatureWarningLevel.HIGH -> MaterialTheme.colorScheme.error
TemperatureWarningLevel.MEDIUM -> MaterialTheme.colorScheme.tertiary
else -> MaterialTheme.colorScheme.onSurface
}
)
Spacer(modifier = Modifier.width(2.dp))
Text(
text = temperatureMetrics.getDisplay(useFahrenheit),
style = MaterialTheme.typography.bodySmall,
color = when (temperatureMetrics.warningLevel) {
TemperatureWarningLevel.HIGH -> MaterialTheme.colorScheme.error
TemperatureWarningLevel.MEDIUM -> MaterialTheme.colorScheme.tertiary
else -> MaterialTheme.colorScheme.onSurface
}
)
}
}
@Composable
fun StorageIndicator(storageMetrics: StorageMetrics) {
val usedGb = storageMetrics.usedGB
val availableGb = storageMetrics.availableGB
Row(modifier = Modifier.padding(end = 8.dp), verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Default.SdStorage,
contentDescription = "Storage",
tint = when {
availableGb < 5.0f -> MaterialTheme.colorScheme.error
availableGb < 10.0f -> MaterialTheme.colorScheme.tertiary
else -> MaterialTheme.colorScheme.onSurface
}
)
Spacer(modifier = Modifier.width(2.dp))
Text(
text = String.format(Locale.getDefault(), "%.1f / %.1f GB", usedGb, availableGb),
style = MaterialTheme.typography.bodySmall
)
}
}

View File

@ -0,0 +1,50 @@
package com.example.llama.revamp.ui.scaffold.topbar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Menu
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
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DefaultTopBar(
title: String,
onNavigateBack: (() -> Unit)? = null,
onMenuOpen: (() -> Unit)? = null
) {
TopAppBar(
title = { Text(title) },
navigationIcon = {
when {
onNavigateBack != null -> {
IconButton(onClick = onNavigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back"
)
}
}
onMenuOpen != null -> {
IconButton(onClick = onMenuOpen) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = "Menu"
)
}
}
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
titleContentColor = MaterialTheme.colorScheme.onSurface
)
)
}

View File

@ -0,0 +1,137 @@
package com.example.llama.revamp.ui.scaffold.topbar
import androidx.compose.foundation.layout.Row
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.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Memory
import androidx.compose.material.icons.filled.Menu
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.unit.dp
import com.example.llama.revamp.monitoring.MemoryMetrics
import com.example.llama.revamp.monitoring.TemperatureMetrics
import com.example.llama.revamp.monitoring.TemperatureWarningLevel
import java.util.Locale
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PerformanceTopBar(
title: String,
memoryMetrics: MemoryMetrics,
temperatureDisplay: Pair<TemperatureMetrics, Boolean>?,
onNavigateBack: (() -> Unit)? = null,
onMenuOpen: (() -> Unit)? = null,
) {
TopAppBar(
title = { Text(title) },
navigationIcon = {
when {
onNavigateBack != null -> {
IconButton(onClick = onNavigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back"
)
}
}
onMenuOpen != null -> {
IconButton(onClick = onMenuOpen) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = "Menu"
)
}
}
}
},
actions = {
// Temperature indicator (optional)
temperatureDisplay?.let { (temperatureMetrics, useFahrenheit) ->
TemperatureIndicator(
temperatureMetrics = temperatureMetrics,
useFahrenheit = useFahrenheit
)
Spacer(modifier = Modifier.Companion.width(8.dp))
}
// Memory indicator
MemoryIndicator(memoryUsage = memoryMetrics)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
titleContentColor = MaterialTheme.colorScheme.onSurface
)
)
}
@Composable
private fun MemoryIndicator(memoryUsage: MemoryMetrics) {
Row(
modifier = Modifier.Companion.padding(end = 8.dp),
verticalAlignment = Alignment.Companion.CenterVertically
) {
Icon(
imageVector = Icons.Default.Memory,
contentDescription = "RAM usage",
tint = when {
memoryUsage.availableGb < 1 -> MaterialTheme.colorScheme.error
memoryUsage.availableGb < 3 -> MaterialTheme.colorScheme.tertiary
else -> MaterialTheme.colorScheme.onSurface
}
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = String.Companion.format(
Locale.getDefault(), "%.1f / %.1f GB", memoryUsage.availableGb, memoryUsage.totalGb
),
style = MaterialTheme.typography.bodySmall,
)
}
}
@Composable
private fun TemperatureIndicator(temperatureMetrics: TemperatureMetrics, useFahrenheit: Boolean) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = when (temperatureMetrics.warningLevel) {
TemperatureWarningLevel.HIGH -> Icons.Default.WarningAmber
else -> Icons.Default.Thermostat
},
contentDescription = "Device temperature",
tint = when (temperatureMetrics.warningLevel) {
TemperatureWarningLevel.HIGH -> MaterialTheme.colorScheme.error
TemperatureWarningLevel.MEDIUM -> MaterialTheme.colorScheme.tertiary
else -> MaterialTheme.colorScheme.onSurface
}
)
Spacer(modifier = Modifier.width(2.dp))
Text(
text = temperatureMetrics.getDisplay(useFahrenheit),
style = MaterialTheme.typography.bodySmall,
color = when (temperatureMetrics.warningLevel) {
TemperatureWarningLevel.HIGH -> MaterialTheme.colorScheme.error
TemperatureWarningLevel.MEDIUM -> MaterialTheme.colorScheme.tertiary
else -> MaterialTheme.colorScheme.onSurface
}
)
}
}

View File

@ -0,0 +1,86 @@
package com.example.llama.revamp.ui.scaffold.topbar
import androidx.compose.foundation.layout.Row
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.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.SdStorage
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.unit.dp
import com.example.llama.revamp.data.repository.StorageMetrics
import java.util.Locale
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StorageTopBar(
title: String,
storageMetrics: StorageMetrics?,
onNavigateBack: (() -> Unit)? = null,
) {
TopAppBar(
title = { Text(title) },
navigationIcon = {
if (onNavigateBack != null) {
IconButton(onClick = onNavigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back"
)
}
}
},
actions = {
storageMetrics?.let {
StorageIndicator(storageMetrics = it)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
titleContentColor = MaterialTheme.colorScheme.onSurface
)
)
}
@Composable
private fun StorageIndicator(storageMetrics: StorageMetrics) {
val usedGb = storageMetrics.usedGB
val availableGb = storageMetrics.availableGB
Row(
modifier = Modifier.Companion.padding(end = 8.dp),
verticalAlignment = Alignment.Companion.CenterVertically
) {
Icon(
imageVector = Icons.Default.SdStorage,
contentDescription = "Storage",
tint = when {
availableGb < 5.0f -> MaterialTheme.colorScheme.error
availableGb < 10.0f -> MaterialTheme.colorScheme.tertiary
else -> MaterialTheme.colorScheme.onSurface
}
)
Spacer(modifier = Modifier.Companion.width(2.dp))
Text(
text = String.Companion.format(
Locale.getDefault(),
"%.1f / %.1f GB",
usedGb,
availableGb
),
style = MaterialTheme.typography.bodySmall
)
}
}

View File

@ -0,0 +1,49 @@
package com.example.llama.revamp.ui.scaffold.topbar
import com.example.llama.revamp.data.repository.StorageMetrics
import com.example.llama.revamp.monitoring.MemoryMetrics
import com.example.llama.revamp.monitoring.TemperatureMetrics
/**
* [TopAppBar] configurations
*/
sealed class TopBarConfig {
abstract val title: String
abstract val navigationIcon: NavigationIcon
// No top bar at all
data class None(
override val title: String = "",
override val navigationIcon: NavigationIcon = NavigationIcon.None
) : TopBarConfig()
// Default/simple top bar with only a navigation icon
data class Default(
override val title: String,
override val navigationIcon: NavigationIcon
) : TopBarConfig()
// Performance monitoring top bar with RAM and optional temperature
data class Performance(
override val title: String,
override val navigationIcon: NavigationIcon,
val memoryMetrics: MemoryMetrics,
val temperatureInfo: Pair<TemperatureMetrics, Boolean>?,
) : TopBarConfig()
// Storage management top bar with used & total storage
data class Storage(
override val title: String,
override val navigationIcon: NavigationIcon,
val storageMetrics: StorageMetrics?
) : TopBarConfig()
}
/**
* Helper class for navigation icon configuration
*/
sealed class NavigationIcon {
data class Back(val onNavigateBack: () -> Unit) : NavigationIcon()
data class Menu(val onMenuOpen: () -> Unit) : NavigationIcon()
object None : NavigationIcon()
}