- Fix a bug where deleting a local model when there are >1 local models shows the wrong download status.

- Don't go back to model selection screen automatically when there is an error during model initialization, so that users have a chance to change model parameters (e.g. accelerator) to retry the initialization.
- Show error dialog properly in prompt lab screen.
This commit is contained in:
Jing Jin 2025-05-19 14:46:00 -07:00
parent e53acf6065
commit 7d567c3499
6 changed files with 92 additions and 43 deletions

View file

@ -30,7 +30,7 @@ android {
minSdk = 26
targetSdk = 35
versionCode = 1
versionName = "0.9.3"
versionName = "0.9.4"
// Needed for HuggingFace auth workflows.
manifestPlaceholders["appAuthRedirectScheme"] = "com.google.aiedge.gallery.oauth"

View file

@ -0,0 +1,67 @@
/*
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.aiedge.gallery.ui.common
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
@Composable
fun ErrorDialog(error: String, onDismiss: () -> Unit) {
Dialog(
onDismissRequest = onDismiss
) {
Card(modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp)) {
Column(
modifier = Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// Title
Text(
"Error",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(bottom = 8.dp)
)
// Error
Text(
error,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error,
)
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
Button(
onClick = onDismiss
) {
Text("Close")
}
}
}
}
}
}

View file

@ -43,14 +43,11 @@ import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Timer
import androidx.compose.material.icons.rounded.Close
import androidx.compose.material.icons.rounded.ContentCopy
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@ -97,11 +94,11 @@ import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.google.aiedge.gallery.R
import com.google.aiedge.gallery.data.Model
import com.google.aiedge.gallery.data.Task
import com.google.aiedge.gallery.data.TaskType
import com.google.aiedge.gallery.ui.common.ErrorDialog
import com.google.aiedge.gallery.ui.modelmanager.ModelInitializationStatusType
import com.google.aiedge.gallery.ui.modelmanager.ModelManagerViewModel
import com.google.aiedge.gallery.ui.preview.PreviewChatModel
@ -581,44 +578,12 @@ fun ChatPanel(
// Error dialog.
if (showErrorDialog) {
Dialog(
onDismissRequest = {
ErrorDialog(error = modelInitializationStatus?.error ?: "", onDismiss = {
showErrorDialog = false
navigateUp()
},
) {
Card(modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp)) {
Column(
modifier = Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// Title
Text(
"Error",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(bottom = 8.dp)
)
// Error
Text(
modelInitializationStatus?.error ?: "",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error,
)
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
Button(onClick = {
showErrorDialog = false
navigateUp()
}) {
Text("Close")
}
}
}
}
}
})
}
// Benchmark config dialog.
// Benchmark config dialog.
if (showBenchmarkConfigsDialog) {
BenchmarkConfigDialog(onDismissed = { showBenchmarkConfigsDialog = false },
messageToBenchmark = benchmarkMessage.value,
@ -627,7 +592,7 @@ fun ChatPanel(
})
}
// Sheet to show when a message is long-pressed.
// Sheet to show when a message is long-pressed.
if (showMessageLongPressedSheet) {
val message = longPressedMessage.value
if (message != null && message is ChatMessageText) {

View file

@ -43,8 +43,10 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.viewmodel.compose.viewModel
import com.google.aiedge.gallery.data.ModelDownloadStatusType
import com.google.aiedge.gallery.ui.ViewModelProvider
import com.google.aiedge.gallery.ui.common.ErrorDialog
import com.google.aiedge.gallery.ui.common.ModelPageAppBar
import com.google.aiedge.gallery.ui.common.chat.ModelDownloadStatusInfoPanel
import com.google.aiedge.gallery.ui.modelmanager.ModelInitializationStatusType
import com.google.aiedge.gallery.ui.modelmanager.ModelManagerViewModel
import com.google.aiedge.gallery.ui.preview.PreviewLlmSingleTurnViewModel
import com.google.aiedge.gallery.ui.preview.PreviewModelManagerViewModel
@ -78,6 +80,7 @@ fun LlmSingleTurnScreen(
val scope = rememberCoroutineScope()
val context = LocalContext.current
var navigatingUp by remember { mutableStateOf(false) }
var showErrorDialog by remember { mutableStateOf(false) }
val handleNavigateUp = {
navigatingUp = true
@ -110,6 +113,11 @@ fun LlmSingleTurnScreen(
}
}
val modelInitializationStatus = modelManagerUiState.modelInitializationStatus[selectedModel.name]
LaunchedEffect(modelInitializationStatus) {
showErrorDialog = modelInitializationStatus?.status == ModelInitializationStatusType.ERROR
}
Scaffold(modifier = modifier, topBar = {
ModelPageAppBar(
task = task,
@ -186,6 +194,12 @@ fun LlmSingleTurnScreen(
}
})
}
if (showErrorDialog) {
ErrorDialog(error = modelInitializationStatus?.error ?: "", onDismiss = {
showErrorDialog = false
})
}
}
}
}

View file

@ -160,7 +160,7 @@ fun ModelList(
}
// List of imported models within a task.
items(items = importedModels) { model ->
items(items = importedModels, key = { it.name }) { model ->
Box {
ModelItem(
model = model,

View file

@ -683,6 +683,9 @@ open class ModelManagerViewModel(
Log.d(TAG, "Allowlist: $modelAllowlist")
// Convert models in the allowlist.
TASK_LLM_CHAT.models.clear()
TASK_LLM_PROMPT_LAB.models.clear()
TASK_LLM_ASK_IMAGE.models.clear()
for (allowedModel in modelAllowlist.models) {
if (allowedModel.disabled == true) {
continue