Merge pull request #1902 from LING71671/fix/config-effective-cost-currency

fix(tui): show effective cost currency context in config view
This commit is contained in:
Hunter Bown
2026-05-30 21:53:55 -07:00
committed by GitHub
+149 -2
View File
@@ -575,6 +575,7 @@ pub struct ConfigView {
filter: String,
status: Option<String>,
locale: Locale,
effective_cost_currency: String,
last_visible_rows: Cell<usize>,
last_row_hitboxes: RefCell<Vec<(u16, usize)>>,
}
@@ -819,6 +820,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()),
}
@@ -841,7 +843,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| {
@@ -1120,6 +1122,27 @@ 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 {
let saved_cost_currency = crate::pricing::CostCurrency::from_setting(&row.value);
let effective_cost_currency =
crate::pricing::CostCurrency::from_setting(&self.effective_cost_currency);
if saved_cost_currency != effective_cost_currency {
return format!("{} (effective {})", row.value, self.effective_cost_currency);
}
}
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 {
@@ -1138,6 +1161,7 @@ fn config_hint_for_key(key: &str) -> &'static str {
"locale" => "auto | en | ja | zh-Hans | pt-BR",
"background_color" => "#RRGGBB | default",
"base_url" => "save user config; e.g. https://api.deepseek.com/beta or https://gateway/v1",
"cost_currency" => "usd | cny",
"default_mode" => "agent | plan | yolo",
"sidebar_width" => "10..=50",
"sidebar_focus" => "auto | work | tasks | agents | context | hidden",
@@ -1445,7 +1469,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!(
" {:<key_width$} {:<value_width$} {}",
row.key,
@@ -2024,8 +2051,52 @@ mod tests {
KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind,
};
use ratatui::{buffer::Buffer, layout::Rect};
use std::ffi::OsString;
use std::fs;
use std::path::PathBuf;
use std::sync::MutexGuard;
use tempfile::TempDir;
struct ConfigSettingsEnvGuard {
_tmp: TempDir,
previous_config_path: Option<OsString>,
_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 {
@@ -2052,6 +2123,26 @@ mod tests {
App::new(options, &Config::default())
}
fn cost_currency_row_for_settings(
settings_toml: &str,
) -> (String, String, crate::pricing::CostCurrency, Locale) {
let _guard = ConfigSettingsEnvGuard::new(settings_toml);
let app = create_test_app();
let view = ConfigView::new_for_app(&app);
let row = view
.rows
.iter()
.find(|row| row.key == "cost_currency")
.expect("cost_currency row");
(
row.value.clone(),
view.row_display_value(row),
app.cost_currency,
app.ui_locale,
)
}
fn type_filter(view: &mut ConfigView, text: &str) {
for ch in text.chars() {
let action = view.handle_key(KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE));
@@ -2232,6 +2323,62 @@ mod tests {
assert_eq!(row.value, "https://ui-config-view.local/v1");
}
#[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_cost_currency_aliases_matching_effective_currency_are_silent() {
for alias in ["rmb", "yuan", "¥"] {
let (saved_value, display_value, effective_currency, locale) =
cost_currency_row_for_settings(&format!(
"locale = \"zh-Hans\"\ncost_currency = \"{alias}\"\n"
));
assert_eq!(locale, Locale::ZhHans);
assert_eq!(effective_currency, crate::pricing::CostCurrency::Cny);
assert_eq!(saved_value, alias);
assert_eq!(display_value, alias);
}
}
#[test]
fn config_view_cost_currency_matching_cny_setting_is_silent() {
let (saved_value, display_value, effective_currency, locale) =
cost_currency_row_for_settings("locale = \"zh-Hans\"\ncost_currency = \"cny\"\n");
assert_eq!(locale, Locale::ZhHans);
assert_eq!(effective_currency, crate::pricing::CostCurrency::Cny);
assert_eq!(saved_value, "cny");
assert_eq!(display_value, "cny");
}
#[test]
fn config_view_cost_currency_non_zh_hans_locale_uses_saved_currency() {
let (saved_value, display_value, effective_currency, locale) =
cost_currency_row_for_settings("locale = \"en\"\ncost_currency = \"cny\"\n");
assert_eq!(locale, Locale::En);
assert_eq!(effective_currency, crate::pricing::CostCurrency::Cny);
assert_eq!(saved_value, "cny");
assert_eq!(display_value, "cny");
}
#[test]
fn config_view_exposes_all_available_saved_settings() {
let app = create_test_app();