UI: add visualizer UI for Arm features

This commit is contained in:
Han Yin 2025-06-27 11:59:03 -07:00
parent 70ec1f7de7
commit d211c4c605
2 changed files with 150 additions and 17 deletions

View File

@ -0,0 +1,97 @@
package com.example.llama.ui.components
import android.content.Intent
import android.llama.cpp.ArmFeature
import android.llama.cpp.ArmFeaturesMapper
import android.llama.cpp.LLamaTier
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MultiChoiceSegmentedButtonRow
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.core.net.toUri
import kotlin.math.sqrt
/**
* ARM Features visualization using segmented buttons.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ArmFeaturesVisualizer(
detectedTier: LLamaTier?,
modifier: Modifier = Modifier,
onFeatureClick: ((ArmFeature) -> Unit)? = null
) {
val featuresData = remember(detectedTier) {
ArmFeaturesMapper.getFeatureDisplayData(detectedTier)
}
Column(
modifier = modifier.fillMaxWidth()
) {
// Segmented Button Row for Features
MultiChoiceSegmentedButtonRow(
modifier = Modifier.fillMaxWidth()
) {
featuresData.forEachIndexed { index, item ->
val weight = sqrt(item.feature.displayName.length.toFloat())
SegmentedButton(
modifier = Modifier.weight(weight),
shape = SegmentedButtonDefaults.itemShape(
index = index,
count = featuresData.size
),
icon = {},
onCheckedChange = { onFeatureClick?.invoke(item.feature) },
checked = item.isSupported,
) {
Text(
text = item.feature.displayName,
style = MaterialTheme.typography.labelSmall,
fontWeight = if (item.isSupported) {
FontWeight.Medium
} else {
FontWeight.Light
},
color = if (item.isSupported) {
MaterialTheme.colorScheme.onSurface
} else {
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f)
}
)
}
}
}
}
}
/**
* Alternative version with clickable features that open ARM documentation.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ArmFeaturesVisualizerClickable(
detectedTier: LLamaTier?,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
ArmFeaturesVisualizer(
detectedTier = detectedTier,
modifier = modifier,
onFeatureClick = { feature ->
// Open ARM documentation in browser
val intent = Intent(Intent.ACTION_VIEW, feature.armDocUrl.toUri())
context.startActivity(intent)
}
)
}

View File

@ -25,6 +25,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.example.llama.APP_NAME import com.example.llama.APP_NAME
import com.example.llama.data.preferences.UserPreferences import com.example.llama.data.preferences.UserPreferences
import com.example.llama.ui.components.ArmFeaturesVisualizerClickable
import com.example.llama.viewmodel.SettingsViewModel import com.example.llama.viewmodel.SettingsViewModel
/** /**
@ -38,6 +39,7 @@ fun SettingsGeneralScreen(
val isMonitoringEnabled by viewModel.isMonitoringEnabled.collectAsState() val isMonitoringEnabled by viewModel.isMonitoringEnabled.collectAsState()
val useFahrenheit by viewModel.useFahrenheitUnit.collectAsState() val useFahrenheit by viewModel.useFahrenheitUnit.collectAsState()
val themeMode by viewModel.themeMode.collectAsState() val themeMode by viewModel.themeMode.collectAsState()
val detectedTier = viewModel.detectedTier
Column( Column(
modifier = Modifier modifier = Modifier
@ -110,33 +112,67 @@ fun SettingsGeneralScreen(
} }
} }
SettingsCategory(title = "About") { // ARM Features Visualizer with Tier Information description
Card( SettingsCategory(title = "About your device") {
modifier = Modifier.fillMaxWidth() Column(
modifier = Modifier.padding(16.dp)
) { ) {
Column( Text(
modifier = Modifier.padding(16.dp) text = "ARM Capabilities",
) { style = MaterialTheme.typography.titleLarge
Text( )
text = APP_NAME,
style = MaterialTheme.typography.titleLarge
)
Text( Text(
text = "Version 1.0.0", text = "Hardware-accelerated AI features",
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant color = MaterialTheme.colorScheme.onSurfaceVariant
) )
detectedTier?.let { tier ->
Spacer(modifier = Modifier.height(8.dp))
ArmFeaturesVisualizerClickable(detectedTier = detectedTier)
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
Text( Text(
text = "Local inference for LLM models on your device.", text = "Optimization Tier: ${tier.name}",
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.bodyLarge
)
Text(
text = tier.description,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(top = 4.dp)
) )
} }
} }
} }
SettingsCategory(title = "About this app") {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(
text = APP_NAME,
style = MaterialTheme.typography.titleLarge
)
Text(
text = "Version 1.0.0",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "Local inference for LLM models on your device powered by Arm® technologies.",
style = MaterialTheme.typography.bodyLarge
)
}
}
} }
} }