diff --git a/app/src/main/java/com/m57/hermescontrol/ui/analytics/AnalyticsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/analytics/AnalyticsScreen.kt index cc66d31f..8a4ce327 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/analytics/AnalyticsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/analytics/AnalyticsScreen.kt @@ -39,7 +39,9 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel +import com.m57.hermescontrol.NavigationController import com.m57.hermescontrol.R +import com.m57.hermescontrol.SkillsScreen import com.m57.hermescontrol.data.model.AnalyticsDailyEntry import com.m57.hermescontrol.data.model.ModelsAnalyticsModelEntry import com.m57.hermescontrol.theme.LocalHermesStatusColors @@ -89,6 +91,8 @@ fun AnalyticsScreen( title = stringResource(R.string.analytics_empty_title), subtitle = stringResource(R.string.analytics_empty_desc), icon = Icons.Filled.BarChart, + actionLabel = stringResource(R.string.empty_action_explore), + onAction = { NavigationController.navigateTo(SkillsScreen) }, ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/channels/ChannelsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/channels/ChannelsScreen.kt index 7717f9a3..a4e46e0f 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/channels/ChannelsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/channels/ChannelsScreen.kt @@ -147,6 +147,8 @@ fun ChannelsScreen( EmptyState( title = stringResource(R.string.channels_empty_title), subtitle = stringResource(R.string.channels_empty_desc), + actionLabel = stringResource(R.string.empty_action_connect_telegram), + onAction = { viewModel.startTelegramOnboarding() }, modifier = Modifier.padding(paddingValues), ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/cron/CronJobsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/cron/CronJobsScreen.kt index aca6a9e8..0e6e3f83 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/cron/CronJobsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/cron/CronJobsScreen.kt @@ -112,6 +112,8 @@ fun CronJobsScreen( icon = Icons.Filled.Schedule, title = stringResource(R.string.cron_empty_title), subtitle = stringResource(R.string.cron_empty_desc), + actionLabel = stringResource(R.string.empty_action_create_job), + onAction = { viewModel.openNewJobDialog() }, ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/keys/KeysScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/keys/KeysScreen.kt index 78d74c18..6270874d 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/keys/KeysScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/keys/KeysScreen.kt @@ -158,8 +158,10 @@ fun KeysScreen( if (filteredCategories.isEmpty() && query.isNotBlank()) { item(key = "no-results") { EmptyState( - title = "No matching keys", - subtitle = "Try a different search term.", + title = stringResource(R.string.keys_no_matching_title), + subtitle = stringResource(R.string.keys_no_matching_desc), + actionLabel = stringResource(R.string.empty_action_clear_search), + onAction = { query = "" }, modifier = Modifier.padding(paddingValues), ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/mcp/McpServersScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/mcp/McpServersScreen.kt index b76cba13..7e3357d6 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/mcp/McpServersScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/mcp/McpServersScreen.kt @@ -155,8 +155,10 @@ fun McpServersScreen( if (filteredServers.isEmpty() && query.isEmpty()) { item(key = "empty") { EmptyState( - title = "No MCP servers", - subtitle = "Add a server above or from the catalog.", + title = stringResource(R.string.mcp_servers_empty_title), + subtitle = stringResource(R.string.mcp_servers_empty_desc), + actionLabel = stringResource(R.string.empty_action_add_server), + onAction = { viewModel.toggleAddForm() }, ) } } else if (filteredServers.isEmpty()) { diff --git a/app/src/main/java/com/m57/hermescontrol/ui/model/ModelScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/model/ModelScreen.kt index 3d6c552a..baec759c 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/model/ModelScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/model/ModelScreen.kt @@ -54,7 +54,9 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel +import com.m57.hermescontrol.NavigationController import com.m57.hermescontrol.R +import com.m57.hermescontrol.SettingsConnection import com.m57.hermescontrol.ui.common.EmptyState import com.m57.hermescontrol.ui.common.ErrorState import com.m57.hermescontrol.ui.common.HermesScaffold @@ -116,8 +118,8 @@ fun ModelScreen( EmptyState( title = stringResource(R.string.model_empty_title), subtitle = stringResource(R.string.model_empty_desc), - onAction = { viewModel.loadAll() }, - actionLabel = stringResource(R.string.content_desc_refresh), + actionLabel = stringResource(R.string.empty_action_configure_model), + onAction = { NavigationController.navigateTo(SettingsConnection) }, modifier = Modifier.padding(paddingValues), ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/sessions/SessionsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/sessions/SessionsScreen.kt index ce6a47f7..2599a5d8 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/sessions/SessionsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/sessions/SessionsScreen.kt @@ -595,6 +595,8 @@ fun SessionsScreen( title = stringResource(R.string.history_empty_title), subtitle = stringResource(R.string.history_empty_desc), icon = Icons.Filled.History, + actionLabel = stringResource(R.string.empty_action_start_chat), + onAction = { NavigationController.navigateTo(ChatScreen) }, ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/skills/SkillsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/skills/SkillsScreen.kt index 5bd1565b..b9679db5 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/skills/SkillsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/skills/SkillsScreen.kt @@ -150,6 +150,7 @@ fun SkillsScreen( isUninstalling = state.isUninstalling, uninstallingSkillName = state.uninstallingSkillName, onRefresh = viewModel::loadSkills, + onBrowseHub = { viewModel.setViewMode(SkillsViewMode.HUB) }, ) } @@ -219,6 +220,7 @@ private fun InstalledSkillsView( isUninstalling: Boolean, uninstallingSkillName: String?, onRefresh: () -> Unit, + onBrowseHub: () -> Unit, ) { var showDetail by remember { mutableStateOf(null) } @@ -332,6 +334,8 @@ private fun InstalledSkillsView( EmptyState( icon = Icons.Filled.Extension, title = stringResource(R.string.skills_empty_message), + actionLabel = stringResource(R.string.empty_action_browse_hub), + onAction = onBrowseHub, ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/skills/components/HubSkillsTab.kt b/app/src/main/java/com/m57/hermescontrol/ui/skills/components/HubSkillsTab.kt index 66ec3063..80a67627 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/skills/components/HubSkillsTab.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/skills/components/HubSkillsTab.kt @@ -131,6 +131,8 @@ internal fun HubBrowseView( EmptyState( icon = Icons.Filled.Extension, title = stringResource(R.string.skills_hub_empty_results), + actionLabel = stringResource(R.string.empty_action_retry_search), + onAction = { onSearch(hubQuery) }, ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/webhooks/WebhooksScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/webhooks/WebhooksScreen.kt index 07d30840..6a6fa8e3 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/webhooks/WebhooksScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/webhooks/WebhooksScreen.kt @@ -341,7 +341,7 @@ fun WebhooksScreen( EmptyState( title = if (state.subscriptions.isEmpty()) { - "No subscriptions" + stringResource(R.string.webhooks_empty_title) } else { stringResource(R.string.webhooks_no_matching) }, @@ -351,6 +351,18 @@ fun WebhooksScreen( } else { stringResource(R.string.webhooks_no_matching_desc) }, + actionLabel = + if (state.subscriptions.isEmpty()) { + stringResource(R.string.webhooks_action_add) + } else { + null + }, + onAction = + if (state.subscriptions.isEmpty()) { + { viewModel.showCreateDialog() } + } else { + null + }, ) } } else { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1e4bedad..2fcc8d7e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -36,6 +36,19 @@ Open navigation drawer Refresh Save + + + Browse skill hub + Retry search + Create your first job + Add a server + Create subscription + Connect a Telegram channel + Configure model + Start a new chat + Install from URL + Explore Skills or Cron jobs + Clear search Cancel Clear search @@ -487,6 +500,7 @@ Global Webhooks Status Subscriptions No webhook subscriptions configured. + No subscriptions Search subscriptions… Add subscription Create @@ -645,6 +659,8 @@ Test Add server HTTP URL + No MCP servers + Add a server above or from the catalog. Stdio command Server name URL (e.g. http://localhost:8000/sse) @@ -747,6 +763,8 @@ Not configured Toggle Visibility Search keys… + No matching keys + Try a different search term. Add new key Key Value