Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions src-tauri/src/cli/i18n.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4260,11 +4260,19 @@ pub mod texts {
}
}

pub fn tui_settings_proxy_stop_before_edit_hint() -> &'static str {
pub fn tui_settings_proxy_stop_before_edit_hint(current_app_is_active: bool) -> &'static str {
if is_chinese() {
"请先停止本地代理,再修改监听地址或端口"
if current_app_is_active {
"修改监听地址:需先停止本地代理。修改监听端口:需先停止当前应用的代理路由。改完后重新启动路由生效。"
} else {
"修改监听地址:需先停止本地代理。监听端口可以修改。改完后重新启动路由生效。"
}
} else {
"Stop the local proxy before editing listen address or port"
if current_app_is_active {
"Listen address: stop the proxy to edit. Listen port: stop this app's route to edit. Restart routing after changes."
} else {
"Listen address: stop the proxy to edit. Listen port can be edited. Restart routing after changes."
}
}
}

Expand Down Expand Up @@ -4300,11 +4308,19 @@ pub mod texts {
}
}

pub fn tui_toast_proxy_settings_stop_before_edit() -> &'static str {
pub fn tui_toast_proxy_settings_stop_proxy_before_edit_address() -> &'static str {
if is_chinese() {
"本地代理正在运行。请先停止代理,再修改监听地址。"
} else {
"The local proxy is running. Stop it before editing listen address."
}
}

pub fn tui_toast_proxy_settings_stop_app_route_before_edit_port() -> &'static str {
if is_chinese() {
"本地代理正在运行。请先停止代理,再修改监听地址或端口。"
"当前应用正在使用代理。请先停止当前应用的代理路由,再修改监听端口。"
} else {
"The local proxy is running. Stop it before editing listen address or port."
"This app is using the proxy. Stop this app's proxy route before editing listen port."
}
}

Expand Down
28 changes: 22 additions & 6 deletions src-tauri/src/cli/i18n/texts/config_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,19 @@ pub fn tui_settings_proxy_restart_hint() -> &'static str {
}
}

pub fn tui_settings_proxy_stop_before_edit_hint() -> &'static str {
pub fn tui_settings_proxy_stop_before_edit_hint(current_app_has_active_worker: bool) -> &'static str {
if is_chinese() {
"请先停止本地代理,再修改监听地址或端口"
if current_app_has_active_worker {
"修改监听地址:需先停止本地代理。修改监听端口:需先停止当前应用的代理路由。改完后重新启动路由生效。"
} else {
"修改监听地址:需先停止本地代理。监听端口可以修改。改完后重新启动路由生效。"
}
} else {
"Stop the local proxy before editing listen address or port"
if current_app_has_active_worker {
"Listen address: stop the proxy to edit. Listen port: stop this app's route to edit. Restart routing after changes."
} else {
"Listen address: stop the proxy to edit. Listen port can be edited. Restart routing after changes."
}
}
}

Expand Down Expand Up @@ -47,11 +55,19 @@ pub fn tui_toast_proxy_settings_restart_required() -> &'static str {
}
}

pub fn tui_toast_proxy_settings_stop_before_edit() -> &'static str {
pub fn tui_toast_proxy_settings_stop_proxy_before_edit_address() -> &'static str {
if is_chinese() {
"本地代理正在运行。请先停止代理,再修改监听地址。"
} else {
"The local proxy is running. Stop it before editing listen address."
}
}

pub fn tui_toast_proxy_settings_stop_app_route_before_edit_port() -> &'static str {
if is_chinese() {
"本地代理正在运行。请先停止代理,再修改监听地址或端口。"
"当前应用正在使用代理。请先停止当前应用的代理路由,再修改监听端口。"
} else {
"The local proxy is running. Stop it before editing listen address or port."
"This app is using the proxy. Stop this app's proxy route before editing listen port."
}
}

Expand Down
16 changes: 8 additions & 8 deletions src-tauri/src/cli/tui/app/content_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ impl App {
Some(LocalProxySettingsItem::ListenAddress) => {
if data.proxy.running {
self.push_toast(
texts::tui_toast_proxy_settings_stop_before_edit(),
texts::tui_toast_proxy_settings_stop_proxy_before_edit_address(),
ToastKind::Info,
);
return Action::None;
Expand All @@ -891,9 +891,9 @@ impl App {
Action::None
}
Some(LocalProxySettingsItem::ListenPort) => {
if data.proxy.running {
if data.proxy.has_active_worker_for(&self.app_type) {
self.push_toast(
texts::tui_toast_proxy_settings_stop_before_edit(),
texts::tui_toast_proxy_settings_stop_app_route_before_edit_port(),
ToastKind::Info,
);
return Action::None;
Expand Down Expand Up @@ -1110,18 +1110,18 @@ impl App {
),
]);
} else {
let current_app_has_active_worker = data.proxy.has_active_worker_for(&self.app_type);
let port_edit_hint =
texts::tui_settings_proxy_stop_before_edit_hint(current_app_has_active_worker)
.to_string();
lines.extend([
format!(
"{}: {}:{}",
crate::t!("Listen", "监听"),
data.proxy.configured_listen_address,
data.proxy.configured_listen_port
),
crate::t!(
"Stop the local proxy before editing listen address or port. Restart routing after those settings change.",
"修改监听地址或端口前需要先停止本地代理;改完后重新启动路由才会生效。"
)
.to_string(),
port_edit_hint,
]);
}

Expand Down
6 changes: 3 additions & 3 deletions src-tauri/src/cli/tui/app/overlay_handlers/dialogs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ impl App {
) -> Action {
if data.proxy.running {
self.push_toast(
texts::tui_toast_proxy_settings_stop_before_edit(),
texts::tui_toast_proxy_settings_stop_proxy_before_edit_address(),
ToastKind::Info,
);
return Action::None;
Expand All @@ -509,9 +509,9 @@ impl App {
}

fn handle_settings_proxy_listen_port_submit(&mut self, data: &UiData, raw: String) -> Action {
if data.proxy.running {
if data.proxy.has_active_worker_for(&self.app_type) {
self.push_toast(
texts::tui_toast_proxy_settings_stop_before_edit(),
texts::tui_toast_proxy_settings_stop_app_route_before_edit_port(),
ToastKind::Info,
);
return Action::None;
Expand Down
105 changes: 103 additions & 2 deletions src-tauri/src/cli/tui/app/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9868,6 +9868,7 @@ mod tests {

let mut data = UiData::default();
data.proxy.running = true;
data.proxy.claude_takeover = true;
data.proxy.configured_listen_address = "127.0.0.1".to_string();
data.proxy.configured_listen_port = 15721;

Expand All @@ -9880,7 +9881,106 @@ mod tests {
message,
kind: ToastKind::Info,
..
}) if message == "The local proxy is running. Stop it before editing listen address or port."
}) if message == "The local proxy is running. Stop it before editing listen address."
));
}

#[test]
fn settings_proxy_port_editable_when_proxy_running_but_app_not_routed() {
let mut app = App::new(Some(AppType::Claude));
app.route = Route::SettingsProxy;
app.focus = Focus::Content;
app.settings_proxy_idx = LocalProxySettingsItem::ALL
.iter()
.position(|item| matches!(item, LocalProxySettingsItem::ListenPort))
.expect("ListenPort missing");

let mut data = UiData::default();
data.proxy.running = true;
data.proxy.claude_takeover = false;
data.proxy.configured_listen_port = 15721;

let action = app.on_key(key(KeyCode::Enter), &data);
assert!(matches!(action, Action::None));
assert!(matches!(
app.overlay,
Overlay::TextInput(TextInputState {
submit: TextSubmit::SettingsProxyListenPort,
..
})
));

app.overlay = Overlay::TextInput(TextInputState {
title: "Listen Port".to_string(),
prompt: "port".to_string(),
input: TextInput::new("15721".to_string()),
submit: TextSubmit::SettingsProxyListenPort,
secret: false,
});
let action = app.on_key(key(KeyCode::Enter), &data);
assert!(matches!(
action,
Action::SetProxyListenPort { port } if port == 15721
));
}

#[test]
fn settings_proxy_port_blocked_when_active_worker_exists() {
let mut app = App::new(Some(AppType::Claude));
app.route = Route::SettingsProxy;
app.focus = Focus::Content;
app.settings_proxy_idx = LocalProxySettingsItem::ALL
.iter()
.position(|item| matches!(item, LocalProxySettingsItem::ListenPort))
.expect("ListenPort missing");

let mut data = UiData::default();
data.proxy.running = true;
data.proxy.active_worker_apps =
std::collections::HashSet::from([AppType::Claude.as_str().to_string()]);
data.proxy.configured_listen_port = 15721;

let action = app.on_key(key(KeyCode::Enter), &data);
assert!(matches!(action, Action::None));
assert!(matches!(app.overlay, Overlay::None));
assert!(matches!(
app.toast.as_ref(),
Some(Toast {
message,
kind: ToastKind::Info,
..
}) if message == "This app is using the proxy. Stop this app's proxy route before editing listen port."
));
}

#[test]
fn settings_proxy_port_submit_blocked_when_active_worker_starts_before_confirm() {
let mut app = App::new(Some(AppType::Claude));
app.route = Route::SettingsProxy;
app.focus = Focus::Content;
app.overlay = Overlay::TextInput(TextInputState {
title: "Listen Port".to_string(),
prompt: "port".to_string(),
input: TextInput::new("15721".to_string()),
submit: TextSubmit::SettingsProxyListenPort,
secret: false,
});

let mut data = UiData::default();
data.proxy.running = true;
data.proxy.active_worker_apps =
std::collections::HashSet::from([AppType::Claude.as_str().to_string()]);

let action = app.on_key(key(KeyCode::Enter), &data);
assert!(matches!(action, Action::None));
assert!(matches!(app.overlay, Overlay::None));
assert!(matches!(
app.toast.as_ref(),
Some(Toast {
message,
kind: ToastKind::Info,
..
}) if message == "This app is using the proxy. Stop this app's proxy route before editing listen port."
));
}

Expand Down Expand Up @@ -9975,6 +10075,7 @@ mod tests {

let mut data = UiData::default();
data.proxy.running = true;
data.proxy.claude_takeover = true;

let action = app.on_key(key(KeyCode::Enter), &data);
assert!(matches!(action, Action::None));
Expand All @@ -9985,7 +10086,7 @@ mod tests {
message,
kind: ToastKind::Info,
..
}) if message == "The local proxy is running. Stop it before editing listen address or port."
}) if message == "The local proxy is running. Stop it before editing listen address."
));
}

Expand Down
10 changes: 6 additions & 4 deletions src-tauri/src/cli/tui/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ pub struct ProxySnapshot {
}

impl ProxySnapshot {
pub fn has_active_worker_for(&self, app_type: &AppType) -> bool {
self.active_worker_apps
.contains(&app_type.as_str().to_ascii_lowercase())
}

pub fn takeover_enabled_for(&self, app_type: &AppType) -> Option<bool> {
match app_type {
AppType::Claude => Some(self.claude_takeover),
Expand All @@ -317,10 +322,7 @@ impl ProxySnapshot {
}

if self.managed_runtime && !self.active_worker_apps.is_empty() {
return Some(
self.active_worker_apps
.contains(&app_type.as_str().to_ascii_lowercase()),
);
return Some(self.has_active_worker_for(app_type));
}

Some(true)
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/src/cli/tui/runtime_actions/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub(super) fn set_proxy_listen_port(
if app_running {
*ctx.data = UiData::load(&ctx.app.app_type)?;
ctx.app.push_toast(
texts::tui_toast_proxy_settings_stop_before_edit(),
texts::tui_toast_proxy_settings_stop_app_route_before_edit_port(),
super::super::app::ToastKind::Info,
);
return Ok(());
Expand Down Expand Up @@ -527,7 +527,7 @@ fn update_proxy_config(
if status.running {
*ctx.data = UiData::load(&ctx.app.app_type)?;
ctx.app.push_toast(
texts::tui_toast_proxy_settings_stop_before_edit(),
texts::tui_toast_proxy_settings_stop_proxy_before_edit_address(),
super::super::app::ToastKind::Info,
);
return Ok(());
Expand Down
23 changes: 15 additions & 8 deletions src-tauri/src/cli/tui/ui/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3163,7 +3163,12 @@ pub(super) fn render_settings_proxy(
if app.focus == Focus::Content {
let key_label = match LocalProxySettingsItem::ALL.get(app.settings_proxy_idx) {
Some(LocalProxySettingsItem::AutoFailover) => texts::tui_key_toggle(),
_ if data.proxy.running => "",
Some(LocalProxySettingsItem::ListenAddress) if data.proxy.running => "",
Some(LocalProxySettingsItem::ListenPort)
if data.proxy.has_active_worker_for(&app.app_type) =>
{
""
}
_ => texts::tui_key_edit(),
};
if !key_label.is_empty() {
Expand All @@ -3184,14 +3189,16 @@ pub(super) fn render_settings_proxy(
state.select(Some(app.settings_proxy_idx));
frame.render_stateful_widget(table, inset_left(chunks[1], CONTENT_INSET_LEFT), &mut state);

let hint = if !data.proxy.running {
texts::tui_settings_proxy_restart_hint()
} else {
let current_app_has_active_worker = data.proxy.has_active_worker_for(&app.app_type);
texts::tui_settings_proxy_stop_before_edit_hint(current_app_has_active_worker)
};
frame.render_widget(
Paragraph::new(if data.proxy.running {
texts::tui_settings_proxy_stop_before_edit_hint()
} else {
texts::tui_settings_proxy_restart_hint()
})
.alignment(Alignment::Center)
.style(Style::default().fg(theme.dim)),
Paragraph::new(hint)
.alignment(Alignment::Center)
.style(Style::default().fg(theme.dim)),
chunks[2],
);
}
Loading