UI: add Tooltip on Import FAB for user onboarding

This commit is contained in:
Han Yin 2025-08-30 22:03:14 -07:00
parent 98016791a6
commit a9b84b9db3
7 changed files with 57 additions and 23 deletions

View File

@ -220,7 +220,9 @@ fun AppContent(
modelsViewModel.resetPreselection()
openDrawer()
},
onToggleMode = modelsViewModel::toggleMode,
onToggleManaging = if (hasModelsInstalled) {
{ modelsViewModel.toggleMode(ModelScreenUiMode.MANAGING) }
} else null,
)
ModelScreenUiMode.SEARCHING ->
TopBarConfig.None()
@ -321,6 +323,7 @@ fun AppContent(
toggleMenu = modelsViewModel::toggleFilterMenu
),
importing = BottomBarConfig.Models.Managing.ImportConfig(
showTooltip = true,
isMenuVisible = showImportModelMenu,
toggleMenu = { show -> modelsManagementViewModel.toggleImportMenu(show) },
importFromLocal = {

View File

@ -71,7 +71,7 @@ fun AppScaffold(
is TopBarConfig.ModelsBrowsing -> ModelsBrowsingTopBar(
title = topBarconfig.title,
onToggleMode = topBarconfig.onToggleMode,
onToggleManaging = topBarconfig.onToggleManaging,
onNavigateBack = topBarconfig.navigationIcon.backAction,
onMenuOpen = topBarconfig.navigationIcon.menuAction
)

View File

@ -72,6 +72,7 @@ sealed class BottomBarConfig {
)
data class ImportConfig(
val showTooltip: Boolean,
val isMenuVisible: Boolean,
val toggleMenu: (Boolean) -> Unit,
val importFromLocal: () -> Unit,

View File

@ -15,14 +15,21 @@ import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
@ -30,6 +37,7 @@ import androidx.compose.ui.unit.dp
import com.example.llama.R
import com.example.llama.data.model.ModelSortOrder
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ModelsManagementBottomBar(
isDeletionEnabled: Boolean,
@ -38,6 +46,14 @@ fun ModelsManagementBottomBar(
filteringConfig: BottomBarConfig.Models.Managing.FilteringConfig,
importingConfig: BottomBarConfig.Models.Managing.ImportConfig,
) {
val tooltipState = rememberTooltipState()
LaunchedEffect(importingConfig) {
if (importingConfig.showTooltip && !importingConfig.isMenuVisible) {
tooltipState.show()
}
}
BottomAppBar(
actions = {
// Batch-deletion action
@ -162,13 +178,24 @@ fun ModelsManagementBottomBar(
}
},
floatingActionButton = {
FloatingActionButton(
onClick = { importingConfig.toggleMenu(true) },
TooltipBox(
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(
TooltipAnchorPosition.Above),
tooltip = {
PlainTooltip {
Text("Tap this button to install your first model!")
}
},
state = tooltipState
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Add model"
)
FloatingActionButton(
onClick = { importingConfig.toggleMenu(true) },
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Add model"
)
}
}
// Add model dropdown menu
@ -177,7 +204,7 @@ fun ModelsManagementBottomBar(
onDismissRequest = { importingConfig.toggleMenu(false) }
) {
DropdownMenuItem(
text = { Text("Import local model") },
text = { Text("Import a local model") },
leadingIcon = {
Icon(
imageVector = Icons.Default.FolderOpen,

View File

@ -18,13 +18,12 @@ 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.viewmodel.ModelScreenUiMode
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ModelsBrowsingTopBar(
title: String,
onToggleMode: (ModelScreenUiMode) -> Unit,
onToggleManaging: (() -> Unit)? = null,
onNavigateBack: (() -> Unit)? = null,
onMenuOpen: (() -> Unit)? = null,
) {
@ -52,9 +51,9 @@ fun ModelsBrowsingTopBar(
}
},
actions = {
ModelManageActionToggle(onToggleManageMode = {
onToggleMode(ModelScreenUiMode.MANAGING)
})
onToggleManaging?.let {
ModelManageActionToggle(it)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
@ -65,11 +64,11 @@ fun ModelsBrowsingTopBar(
@Composable
private fun ModelManageActionToggle(
onToggleManageMode: () -> Unit,
onToggleManaging: () -> Unit,
) {
FilledTonalButton(
modifier = Modifier.padding(end = 12.dp),
onClick = onToggleManageMode
onClick = onToggleManaging
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(

View File

@ -3,7 +3,6 @@ package com.example.llama.ui.scaffold.topbar
import com.example.llama.monitoring.MemoryMetrics
import com.example.llama.monitoring.StorageMetrics
import com.example.llama.monitoring.TemperatureMetrics
import com.example.llama.ui.scaffold.ScaffoldEvent
import com.example.llama.viewmodel.ModelScreenUiMode
/**
@ -29,7 +28,7 @@ sealed class TopBarConfig {
data class ModelsBrowsing(
override val title: String,
override val navigationIcon: NavigationIcon,
val onToggleMode: (ModelScreenUiMode) -> Unit,
val onToggleManaging: (() -> Unit)?,
) : TopBarConfig()
// Model batch-deletion top bar with a toggle to turn on/off manage mode

View File

@ -25,7 +25,7 @@ import androidx.compose.material.icons.filled.Attribution
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Error
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FolderOpen
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Today
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Card
@ -108,17 +108,22 @@ fun ModelsManagementAndDeletingScreen(
if (filteredModels == null) {
ModelsLoadingInProgressView()
} else if (filteredModels.isEmpty()) {
// Import model prompt
// Prompt the user to import a model
val title = when (activeFiltersCount) {
0 -> "Tap the \"+\" button\n to install a model"
0 -> "Import or download,\n have it your way"
1 -> "No models match\n the selected filter"
else -> "No models match\n the selected filters"
}
val message = "If you already have GGUF models on your computer, " +
"please transfer it onto your device, and then select \"Import a local model\".\n\n" +
"Otherwise, select \"Download from HuggingFace\" and pick one you like."
InfoView(
modifier = Modifier.fillMaxSize(0.9f).align(Alignment.Center),
title = title,
icon = Icons.Default.FolderOpen,
message = "Import a local GGUF model file, or download directly from HuggingFace!",
icon = Icons.Default.Info,
message = message,
action = InfoAction(
label = "Learn More",
icon = Icons.AutoMirrored.Default.Help,