From d394b1ee91f57e88bc6afc3971262f2b8b713be1 Mon Sep 17 00:00:00 2001 From: LING71671 <1739677116@qq.com> Date: Thu, 21 May 2026 19:23:35 +0800 Subject: [PATCH] fix(tui): show effective cost currency in config view --- crates/tui/src/tui/views/mod.rs | 92 ++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/crates/tui/src/tui/views/mod.rs b/crates/tui/src/tui/views/mod.rs index fcf1eb40a..9036f9cc0 100644 --- a/crates/tui/src/tui/views/mod.rs +++ b/crates/tui/src/tui/views/mod.rs @@ -569,6 +569,7 @@ pub struct ConfigView { filter: String, status: Option, locale: Locale, + effective_cost_currency: String, last_visible_rows: Cell, last_row_hitboxes: RefCell>, } @@ -804,6 +805,7 @@ impl ConfigView { filter: String::new(), status: None, locale: app.ui_locale, + effective_cost_currency: cost_currency_config_value(app), last_visible_rows: Cell::new(0), last_row_hitboxes: RefCell::new(Vec::new()), } @@ -826,7 +828,7 @@ impl ConfigView { let section = row.section.label().to_lowercase(); let key = row.key.to_lowercase(); - let value = row.value.to_lowercase(); + let value = self.row_display_value(row).to_lowercase(); let scope = row.scope.label().to_lowercase(); filter.split_whitespace().all(|term| { @@ -1105,6 +1107,25 @@ impl ConfigView { self.update_filter(|filter| filter.clear()); } + + fn row_display_value(&self, row: &ConfigRow) -> String { + if row.key == "cost_currency" + && row.scope == ConfigScope::Saved + && row.value != self.effective_cost_currency + { + format!("{} (effective {})", row.value, self.effective_cost_currency) + } else { + row.value.clone() + } + } +} + +fn cost_currency_config_value(app: &App) -> String { + match app.cost_currency { + crate::pricing::CostCurrency::Usd => "usd", + crate::pricing::CostCurrency::Cny => "cny", + } + .to_string() } fn config_hint_for_key(key: &str) -> &'static str { @@ -1122,6 +1143,7 @@ fn config_hint_for_key(key: &str) -> &'static str { "theme" => "system | dark | light | grayscale", "locale" => "auto | en | ja | zh-Hans | pt-BR", "background_color" => "#RRGGBB | default", + "cost_currency" => "usd | cny", "default_mode" => "agent | plan | yolo", "sidebar_width" => "10..=50", "sidebar_focus" => "auto | work | tasks | agents | context | hidden", @@ -1417,7 +1439,10 @@ impl ModalView for ConfigView { } else { Style::default().fg(palette::TEXT_PRIMARY) }; - let value = truncate_view_text(&row.value, CONFIG_VALUE_COLUMN_WIDTH); + let value = truncate_view_text( + &self.row_display_value(row), + CONFIG_VALUE_COLUMN_WIDTH, + ); let mut line = Line::from(format!( " {:, + _lock: MutexGuard<'static, ()>, + } + + impl ConfigSettingsEnvGuard { + fn new(settings_toml: &str) -> Self { + let lock = crate::test_support::lock_test_env(); + let tmp = TempDir::new().expect("settings tempdir"); + let config_path = tmp.path().join(".deepseek").join("config.toml"); + let settings_path = config_path + .parent() + .expect("settings parent") + .join("settings.toml"); + std::fs::create_dir_all(config_path.parent().expect("config parent")) + .expect("config dir"); + std::fs::write(&settings_path, settings_toml).expect("settings file"); + let previous_config_path = std::env::var_os("DEEPSEEK_CONFIG_PATH"); + unsafe { + std::env::set_var("DEEPSEEK_CONFIG_PATH", &config_path); + } + Self { + _tmp: tmp, + previous_config_path, + _lock: lock, + } + } + } + + impl Drop for ConfigSettingsEnvGuard { + fn drop(&mut self) { + unsafe { + match self.previous_config_path.take() { + Some(previous) => std::env::set_var("DEEPSEEK_CONFIG_PATH", previous), + None => std::env::remove_var("DEEPSEEK_CONFIG_PATH"), + } + } + } + } fn create_test_app() -> App { let options = TuiOptions { @@ -2168,6 +2237,25 @@ mod tests { assert!(view.rows.iter().all(|row| row.editable)); } + #[test] + fn config_view_cost_currency_shows_saved_and_effective_runtime_currency() { + let _guard = ConfigSettingsEnvGuard::new("locale = \"zh-Hans\"\ncost_currency = \"usd\"\n"); + let app = create_test_app(); + assert_eq!(app.ui_locale, Locale::ZhHans); + assert_eq!(app.cost_currency, crate::pricing::CostCurrency::Cny); + + let view = ConfigView::new_for_app(&app); + let row = view + .rows + .iter() + .find(|row| row.key == "cost_currency") + .expect("cost_currency row"); + + assert_eq!(row.value, "usd"); + assert_eq!(view.row_display_value(row), "usd (effective cny)"); + assert_eq!(Settings::load().expect("settings").cost_currency, "usd"); + } + #[test] fn config_view_exposes_all_available_saved_settings() { let app = create_test_app();