pkg: restructure TopBarApps into separate files in a child package
This commit is contained in:
parent
3c539dc146
commit
b1831c4053
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue