diff --git a/codex-rs/tui/src/chatwidget/plugins.rs b/codex-rs/tui/src/chatwidget/plugins.rs index a04cf249c5e5..dc1dfd5836d7 100644 --- a/codex-rs/tui/src/chatwidget/plugins.rs +++ b/codex-rs/tui/src/chatwidget/plugins.rs @@ -673,14 +673,21 @@ impl ChatWidget { .then_with(|| left.1.name.cmp(&right.1.name)) .then_with(|| left.1.id.cmp(&right.1.id)) }); + let status_label_width = plugin_entries + .iter() + .map(|(_, plugin, _)| plugin_status_label(plugin).chars().count()) + .max() + .unwrap_or(0); let mut items: Vec = Vec::new(); for (marketplace, plugin, display_name) in plugin_entries { let marketplace_label = marketplace_display_name(marketplace); let status_label = plugin_status_label(plugin); - let description = plugin_brief_description(plugin, &marketplace_label); + let description = + plugin_brief_description(plugin, &marketplace_label, status_label_width); + let selected_status_label = format!("{status_label: String { .unwrap_or_else(|| plugin.name.clone()) } -fn plugin_brief_description(plugin: &PluginSummary, marketplace_label: &str) -> String { +fn plugin_brief_description( + plugin: &PluginSummary, + marketplace_label: &str, + status_label_width: usize, +) -> String { let status_label = plugin_status_label(plugin); + let status_label = format!("{status_label: format!("{status_label} · {marketplace_label} · {description}"), None => format!("{status_label} · {marketplace_label}"), @@ -894,7 +906,7 @@ fn plugin_status_label(plugin: &PluginSummary) -> &'static str { } else { match plugin.install_policy { PluginInstallPolicy::NotAvailable => "Not installable", - PluginInstallPolicy::Available => "Can be installed", + PluginInstallPolicy::Available => "Available", PluginInstallPolicy::InstalledByDefault => "Available by default", } } diff --git a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugin_detail_popup_installable.snap b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugin_detail_popup_installable.snap index d2461ec72f3a..4b4a84a3bd0b 100644 --- a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugin_detail_popup_installable.snap +++ b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugin_detail_popup_installable.snap @@ -4,7 +4,7 @@ expression: popup --- Plugins Figma · ChatGPT Marketplace - Can be installed + Available Turn Figma files into implementation context. › 1. Back to plugins Return to the plugin list. diff --git a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugins_popup_curated_marketplace.snap b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugins_popup_curated_marketplace.snap index c23daeea1b64..1eca54406393 100644 --- a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugins_popup_curated_marketplace.snap +++ b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugins_popup_curated_marketplace.snap @@ -9,12 +9,9 @@ expression: popup Using cached marketplace data: remote sync timed out Type to search plugins -› Alpha Sync · ChatGPT Marketplace Installed · Disabled. Press Enter to view plugin details. - Bravo Search · ChatGPT Marketplace Can be installed · ChatGPT Marketplace · Search docs and - tickets. - Hidden Repo Plugin · Repo Marketplace Can be installed · Repo Marketplace · Should not be shown - in /plugins. - Starter · ChatGPT Marketplace Available by default · ChatGPT Marketplace · Included by - default. +› Alpha Sync Installed · Disabled Press Enter to view plugin details. + Bravo Search Available · ChatGPT Marketplace · Search docs and tickets. + Hidden Repo Plugin Available · Repo Marketplace · Should not be shown in /plugins. + Starter Available by default · ChatGPT Marketplace · Included by default. Press esc to close. diff --git a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugins_popup_search_filtered.snap b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugins_popup_search_filtered.snap index 65a4c6b034df..a9239b37970f 100644 --- a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugins_popup_search_filtered.snap +++ b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__plugins_popup_search_filtered.snap @@ -8,6 +8,6 @@ expression: popup Installed 0 of 3 available plugins. sla -› Slack · ChatGPT Marketplace Can be installed. Press Enter to view plugin details. +› Slack Available Press Enter to view plugin details. Press esc to close. diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 78bb4cf22da4..6a6eac9b1433 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -7411,7 +7411,7 @@ async fn plugins_popup_refresh_replaces_selection_with_first_row() { "expected refresh to rebuild the popup from the new first row, got:\n{after}" ); assert!( - after.contains("Slack · ChatGPT Marketplace"), + after.contains("Slack"), "expected refreshed popup to include the updated plugin list, got:\n{after}" ); } @@ -7447,7 +7447,7 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { "expected initial installed count before refresh, got:\n{before}" ); assert!( - before.contains("Can be installed"), + before.contains("Available"), "expected pre-install popup copy before refresh, got:\n{before}" ); @@ -7480,7 +7480,7 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { "expected /plugins to refresh installed counts after install, got:\n{after}" ); assert!( - after.contains("Installed. Press Enter to view plugin details."), + after.contains("Installed Press Enter to view plugin details."), "expected refreshed selected row copy to reflect the installed plugin state, got:\n{after}" ); } @@ -7528,8 +7528,7 @@ async fn plugins_popup_search_filters_visible_rows_snapshot() { let popup = render_bottom_popup(&chat, 100); assert_snapshot!("plugins_popup_search_filtered", popup); assert!( - !popup.contains("Calendar · ChatGPT Marketplace") - && !popup.contains("Drive · ChatGPT Marketplace"), + !popup.contains("Calendar") && !popup.contains("Drive"), "expected search to leave only matching rows visible, got:\n{popup}" ); } @@ -7581,8 +7580,7 @@ async fn plugins_popup_search_no_matches_and_backspace_restores_results() { let restored = render_bottom_popup(&chat, 100); assert!( - restored.contains("Calendar · ChatGPT Marketplace") - && restored.contains("Slack · ChatGPT Marketplace"), + restored.contains("Calendar") && restored.contains("Slack"), "expected clearing the query to restore the plugin rows, got:\n{restored}" ); assert!( diff --git a/codex-rs/tui_app_server/src/chatwidget/plugins.rs b/codex-rs/tui_app_server/src/chatwidget/plugins.rs index a04cf249c5e5..dc1dfd5836d7 100644 --- a/codex-rs/tui_app_server/src/chatwidget/plugins.rs +++ b/codex-rs/tui_app_server/src/chatwidget/plugins.rs @@ -673,14 +673,21 @@ impl ChatWidget { .then_with(|| left.1.name.cmp(&right.1.name)) .then_with(|| left.1.id.cmp(&right.1.id)) }); + let status_label_width = plugin_entries + .iter() + .map(|(_, plugin, _)| plugin_status_label(plugin).chars().count()) + .max() + .unwrap_or(0); let mut items: Vec = Vec::new(); for (marketplace, plugin, display_name) in plugin_entries { let marketplace_label = marketplace_display_name(marketplace); let status_label = plugin_status_label(plugin); - let description = plugin_brief_description(plugin, &marketplace_label); + let description = + plugin_brief_description(plugin, &marketplace_label, status_label_width); + let selected_status_label = format!("{status_label: String { .unwrap_or_else(|| plugin.name.clone()) } -fn plugin_brief_description(plugin: &PluginSummary, marketplace_label: &str) -> String { +fn plugin_brief_description( + plugin: &PluginSummary, + marketplace_label: &str, + status_label_width: usize, +) -> String { let status_label = plugin_status_label(plugin); + let status_label = format!("{status_label: format!("{status_label} · {marketplace_label} · {description}"), None => format!("{status_label} · {marketplace_label}"), @@ -894,7 +906,7 @@ fn plugin_status_label(plugin: &PluginSummary) -> &'static str { } else { match plugin.install_policy { PluginInstallPolicy::NotAvailable => "Not installable", - PluginInstallPolicy::Available => "Can be installed", + PluginInstallPolicy::Available => "Available", PluginInstallPolicy::InstalledByDefault => "Available by default", } } diff --git a/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugin_detail_popup_installable.snap b/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugin_detail_popup_installable.snap index fe88135b86a7..59bc85e7f10a 100644 --- a/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugin_detail_popup_installable.snap +++ b/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugin_detail_popup_installable.snap @@ -4,7 +4,7 @@ expression: popup --- Plugins Figma · ChatGPT Marketplace - Can be installed + Available Turn Figma files into implementation context. › 1. Back to plugins Return to the plugin list. diff --git a/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugins_popup_curated_marketplace.snap b/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugins_popup_curated_marketplace.snap index f553f9074758..70e6b9d40ee4 100644 --- a/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugins_popup_curated_marketplace.snap +++ b/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugins_popup_curated_marketplace.snap @@ -8,12 +8,9 @@ expression: popup Using cached marketplace data: remote sync timed out Type to search plugins -› Alpha Sync · ChatGPT Marketplace Installed · Disabled. Press Enter to view plugin details. - Bravo Search · ChatGPT Marketplace Can be installed · ChatGPT Marketplace · Search docs and - tickets. - Hidden Repo Plugin · Repo Marketplace Can be installed · Repo Marketplace · Should not be shown - in /plugins. - Starter · ChatGPT Marketplace Available by default · ChatGPT Marketplace · Included by - default. +› Alpha Sync Installed · Disabled Press Enter to view plugin details. + Bravo Search Available · ChatGPT Marketplace · Search docs and tickets. + Hidden Repo Plugin Available · Repo Marketplace · Should not be shown in /plugins. + Starter Available by default · ChatGPT Marketplace · Included by default. Press esc to close. diff --git a/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugins_popup_search_filtered.snap b/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugins_popup_search_filtered.snap index 849db2c28acc..ab0724d344b8 100644 --- a/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugins_popup_search_filtered.snap +++ b/codex-rs/tui_app_server/src/chatwidget/snapshots/codex_tui_app_server__chatwidget__tests__plugins_popup_search_filtered.snap @@ -7,6 +7,6 @@ expression: popup Installed 0 of 3 available plugins. sla -› Slack · ChatGPT Marketplace Can be installed. Press Enter to view plugin details. +› Slack Available Press Enter to view plugin details. Press esc to close. diff --git a/codex-rs/tui_app_server/src/chatwidget/tests.rs b/codex-rs/tui_app_server/src/chatwidget/tests.rs index 3e73b4455c1f..2915881eedf9 100644 --- a/codex-rs/tui_app_server/src/chatwidget/tests.rs +++ b/codex-rs/tui_app_server/src/chatwidget/tests.rs @@ -8008,7 +8008,7 @@ async fn plugins_popup_refresh_replaces_selection_with_first_row() { "expected refresh to rebuild the popup from the new first row, got:\n{after}" ); assert!( - after.contains("Slack · ChatGPT Marketplace"), + after.contains("Slack"), "expected refreshed popup to include the updated plugin list, got:\n{after}" ); } @@ -8044,7 +8044,7 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { "expected initial installed count before refresh, got:\n{before}" ); assert!( - before.contains("Can be installed"), + before.contains("Available"), "expected pre-install popup copy before refresh, got:\n{before}" ); @@ -8077,7 +8077,7 @@ async fn plugins_popup_refreshes_installed_counts_after_install() { "expected /plugins to refresh installed counts after install, got:\n{after}" ); assert!( - after.contains("Installed. Press Enter to view plugin details."), + after.contains("Installed Press Enter to view plugin details."), "expected refreshed selected row copy to reflect the installed plugin state, got:\n{after}" ); } @@ -8125,8 +8125,7 @@ async fn plugins_popup_search_filters_visible_rows_snapshot() { let popup = render_bottom_popup(&chat, 100); assert_snapshot!("plugins_popup_search_filtered", popup); assert!( - !popup.contains("Calendar · ChatGPT Marketplace") - && !popup.contains("Drive · ChatGPT Marketplace"), + !popup.contains("Calendar") && !popup.contains("Drive"), "expected search to leave only matching rows visible, got:\n{popup}" ); } @@ -8178,8 +8177,7 @@ async fn plugins_popup_search_no_matches_and_backspace_restores_results() { let restored = render_bottom_popup(&chat, 100); assert!( - restored.contains("Calendar · ChatGPT Marketplace") - && restored.contains("Slack · ChatGPT Marketplace"), + restored.contains("Calendar") && restored.contains("Slack"), "expected clearing the query to restore the plugin rows, got:\n{restored}" ); assert!(