fix(#372): plugin install/uninstall 400 — enable instead of install for on-disk plugins, gate uninstall behind canRemove, parse FastAPI error bodies (#416)
- Replace installPlugin(name) with activatePlugin(plugin) that calls enable endpoint instead of the install endpoint for plugins already on disk (bundled/inactive). - Gate Uninstall button behind plugin.canRemove — bundled plugins don't show it. - Update PluginsScreen to call activatePlugin(plugin) instead of installPlugin(name). - Parse FastAPI 'detail' field from 400 response bodies in mapHttpError/safeApiCall so users see the actual error message instead of a generic placeholder. - Import ButtonDefaults to fix max-line-length lint warning. Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
b10495c6e2
commit
2ae6cce929
3 files changed
+44
-22
No files matched your search
@@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
@@ -159,18 +160,20 @@ fun PluginsScreen(
|
||||
OutlinedButton(onClick = { viewModel.updatePlugin(plugin.name) }) {
|
||||
Text(stringResource(R.string.plugins_action_update))
|
||||
}
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
OutlinedButton(
|
||||
onClick = { viewModel.uninstallPlugin(plugin.name) },
|
||||
colors =
|
||||
androidx.compose.material3.ButtonDefaults.outlinedButtonColors(
|
||||
contentColor = MaterialTheme.colorScheme.error,
|
||||
),
|
||||
) {
|
||||
Text(stringResource(R.string.plugins_action_uninstall))
|
||||
if (plugin.canRemove) {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
OutlinedButton(
|
||||
onClick = { viewModel.uninstallPlugin(plugin.name) },
|
||||
colors =
|
||||
ButtonDefaults.outlinedButtonColors(
|
||||
contentColor = MaterialTheme.colorScheme.error,
|
||||
),
|
||||
) {
|
||||
Text(stringResource(R.string.plugins_action_uninstall))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Button(onClick = { viewModel.installPlugin(plugin.name) }) {
|
||||
Button(onClick = { viewModel.activatePlugin(plugin) }) {
|
||||
Text(stringResource(R.string.plugins_action_install))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,25 +79,20 @@ class PluginsViewModel : ViewModel(), ToastHost {
|
||||
}
|
||||
}
|
||||
|
||||
fun installPlugin(name: String) {
|
||||
fun activatePlugin(plugin: PluginInfo) {
|
||||
viewModelScope.launch {
|
||||
val result =
|
||||
withContext(Dispatchers.IO) {
|
||||
safeApiCall {
|
||||
ApiClient.hermesApi.installPlugin(
|
||||
com.m57.hermescontrol.data.model
|
||||
.AgentPluginInstallBody(name),
|
||||
)
|
||||
}
|
||||
safeApiCall { ApiClient.hermesApi.enablePlugin(plugin.name) }
|
||||
}
|
||||
when (result) {
|
||||
is NetworkResult.Success -> {
|
||||
_uiState.update { it.copy(toastMessage = "Plugin installed successfully") }
|
||||
_uiState.update { it.copy(toastMessage = "Plugin enabled successfully") }
|
||||
loadPlugins()
|
||||
}
|
||||
|
||||
is NetworkResult.Failure -> {
|
||||
_uiState.update { it.copy(toastMessage = "Failed to install plugin: ${result.error.message}") }
|
||||
_uiState.update { it.copy(toastMessage = "Failed to enable plugin: ${result.error.message}") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user