UI: address Rojin's UX feedbacks
This commit is contained in:
parent
6fb4a94cc3
commit
e067f7051b
|
|
@ -99,6 +99,7 @@ fun AppContent(
|
|||
val engineState by mainViewModel.engineState.collectAsState()
|
||||
val showModelImportTooltip by mainViewModel.showModelImportTooltip.collectAsState()
|
||||
val showChatTooltip by mainViewModel.showChatTooltip.collectAsState()
|
||||
val showManagementTooltip by mainViewModel.showModelManagementTooltip.collectAsState()
|
||||
|
||||
// Model state
|
||||
val modelScreenUiMode by modelsViewModel.modelScreenUiMode.collectAsState()
|
||||
|
|
@ -223,9 +224,11 @@ fun AppContent(
|
|||
modelsViewModel.resetPreselection()
|
||||
openDrawer()
|
||||
},
|
||||
showTooltip = showManagementTooltip && !showChatTooltip && hasModelsInstalled,
|
||||
showManagingToggle = !showChatTooltip && hasModelsInstalled,
|
||||
onToggleManaging = {
|
||||
if (hasModelsInstalled) {
|
||||
mainViewModel.waiveModelManagementTooltip()
|
||||
modelsViewModel.toggleMode(ModelScreenUiMode.MANAGING)
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class AppPreferences @Inject constructor (
|
|||
// Preference keys
|
||||
private val USER_HAS_IMPORTED_FIRST_MODEL = booleanPreferencesKey("user_has_imported_first_model")
|
||||
private val USER_HAS_CHATTED_WITH_MODEL = booleanPreferencesKey("user_has_chatted_with_model")
|
||||
private val USER_HAS_NAVIGATED_TO_MANAGEMENT = booleanPreferencesKey("user_has_navigated_to_management")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -64,4 +65,21 @@ class AppPreferences @Inject constructor (
|
|||
preferences[USER_HAS_CHATTED_WITH_MODEL] = done
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the user has navigated to model management screen.
|
||||
*/
|
||||
fun userHasNavigatedToManagement(): Flow<Boolean> =
|
||||
context.appDataStore.data.map { preferences ->
|
||||
preferences[USER_HAS_NAVIGATED_TO_MANAGEMENT] == true
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the user has navigated to model management screen.
|
||||
*/
|
||||
suspend fun setUserHasNavigatedToManagement(done: Boolean) = withContext(Dispatchers.IO) {
|
||||
context.appDataStore.edit { preferences ->
|
||||
preferences[USER_HAS_NAVIGATED_TO_MANAGEMENT] = done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ fun AppScaffold(
|
|||
|
||||
is TopBarConfig.ModelsBrowsing -> ModelsBrowsingTopBar(
|
||||
title = topBarconfig.title,
|
||||
showTooltip = topBarconfig.showTooltip,
|
||||
showManagingToggle = topBarconfig.showManagingToggle,
|
||||
onToggleManaging = topBarconfig.onToggleManaging,
|
||||
onNavigateBack = topBarconfig.navigationIcon.backAction,
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ fun ModelsManagementBottomBar(
|
|||
onDismissRequest = { importingConfig.toggleMenu(false) }
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text("Import a local GGUF model") },
|
||||
text = { Text("Import a local model") },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.FolderOpen,
|
||||
|
|
@ -217,7 +217,7 @@ fun ModelsManagementBottomBar(
|
|||
onClick = importingConfig.importFromLocal
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Download from HuggingFace") },
|
||||
text = { Text("Download a model from Hugging Face") },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.logo_huggingface),
|
||||
|
|
|
|||
|
|
@ -12,10 +12,16 @@ import androidx.compose.material3.FilledTonalButton
|
|||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
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.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTooltipState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -24,11 +30,23 @@ import androidx.compose.ui.unit.dp
|
|||
@Composable
|
||||
fun ModelsBrowsingTopBar(
|
||||
title: String,
|
||||
showTooltip: Boolean,
|
||||
showManagingToggle: Boolean,
|
||||
onToggleManaging: () -> Unit,
|
||||
onNavigateBack: (() -> Unit)? = null,
|
||||
onMenuOpen: (() -> Unit)? = null,
|
||||
) {
|
||||
val tooltipState = rememberTooltipState(
|
||||
initialIsVisible = showTooltip,
|
||||
isPersistent = showTooltip
|
||||
)
|
||||
|
||||
LaunchedEffect(showTooltip, showManagingToggle) {
|
||||
if (showTooltip && showManagingToggle) {
|
||||
tooltipState.show()
|
||||
}
|
||||
}
|
||||
|
||||
TopAppBar(
|
||||
title = { Text(title) },
|
||||
navigationIcon = {
|
||||
|
|
@ -54,8 +72,20 @@ fun ModelsBrowsingTopBar(
|
|||
},
|
||||
actions = {
|
||||
if (showManagingToggle) {
|
||||
TooltipBox(
|
||||
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(
|
||||
TooltipAnchorPosition.Below),
|
||||
state = tooltipState,
|
||||
tooltip = {
|
||||
PlainTooltip {
|
||||
Text("Tap this button to install another model or manage your models!")
|
||||
}
|
||||
},
|
||||
onDismissRequest = {}
|
||||
) {
|
||||
ModelManageActionToggle(onToggleManaging)
|
||||
}
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ sealed class TopBarConfig {
|
|||
data class ModelsBrowsing(
|
||||
override val title: String,
|
||||
override val navigationIcon: NavigationIcon,
|
||||
val showTooltip: Boolean,
|
||||
val showManagingToggle: Boolean,
|
||||
val onToggleManaging: () -> Unit,
|
||||
) : TopBarConfig()
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import androidx.compose.material3.RadioButton
|
|||
import androidx.compose.material3.SegmentedButton
|
||||
import androidx.compose.material3.SegmentedButtonDefaults
|
||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -250,6 +251,7 @@ fun ModelLoadingScreen(
|
|||
if (!showedSystemPromptWarning) {
|
||||
onScaffoldEvent(ScaffoldEvent.ShowSnackbar(
|
||||
message = "Model may not support system prompt!\nProceed with caution.",
|
||||
duration = SnackbarDuration.Long,
|
||||
))
|
||||
showedSystemPromptWarning = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ fun ModelsManagementAndDeletingScreen(
|
|||
} else if (filteredModels.isEmpty()) {
|
||||
// Prompt the user to import a model
|
||||
val title = when (activeFiltersCount) {
|
||||
0 -> "Import or download,\n have it your way"
|
||||
0 -> "Choose a model:\nImport locally or download online"
|
||||
1 -> "No models match\n the selected filter"
|
||||
else -> "No models match\n the selected filters"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ class MainViewModel @Inject constructor (
|
|||
private val _showChatTooltip = MutableStateFlow(true)
|
||||
val showChatTooltip: StateFlow<Boolean> = _showChatTooltip.asStateFlow()
|
||||
|
||||
private val _showModelManagementTooltip = MutableStateFlow(true)
|
||||
val showModelManagementTooltip: StateFlow<Boolean> = _showModelManagementTooltip.asStateFlow()
|
||||
|
||||
|
||||
/**
|
||||
* Unload the current model and release the resources
|
||||
|
|
@ -47,12 +50,11 @@ class MainViewModel @Inject constructor (
|
|||
_showChatTooltip.value = !it
|
||||
}
|
||||
}
|
||||
launch {
|
||||
appPreferences.userHasNavigatedToManagement().collect {
|
||||
_showModelManagementTooltip.value = !it
|
||||
}
|
||||
}
|
||||
|
||||
fun waiveModelImportTooltip() {
|
||||
viewModelScope.launch {
|
||||
appPreferences.setUserHasImportedFirstModel(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,4 +63,15 @@ class MainViewModel @Inject constructor (
|
|||
appPreferences.setUserHasChattedWithModel(true)
|
||||
}
|
||||
}
|
||||
fun waiveModelImportTooltip() {
|
||||
viewModelScope.launch {
|
||||
appPreferences.setUserHasImportedFirstModel(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun waiveModelManagementTooltip() {
|
||||
viewModelScope.launch {
|
||||
appPreferences.setUserHasNavigatedToManagement(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue