Skip to content
Merged
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
13 changes: 10 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub enum Focus {
MessageList,
RequestSection,
ResponseSection,
StatusHeader,
}

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -370,7 +371,8 @@ impl App {
self.focus = match self.focus {
Focus::MessageList => Focus::RequestSection,
Focus::RequestSection => Focus::ResponseSection,
Focus::ResponseSection => Focus::MessageList,
Focus::ResponseSection => Focus::StatusHeader,
Focus::StatusHeader => Focus::MessageList,
};
self.reset_details_scroll();
self.request_details_scroll = 0;
Expand All @@ -379,9 +381,10 @@ impl App {

pub fn switch_focus_reverse(&mut self) {
self.focus = match self.focus {
Focus::MessageList => Focus::ResponseSection,
Focus::MessageList => Focus::StatusHeader,
Focus::RequestSection => Focus::MessageList,
Focus::ResponseSection => Focus::RequestSection,
Focus::StatusHeader => Focus::ResponseSection,
};
self.reset_details_scroll();
self.request_details_scroll = 0;
Expand All @@ -400,6 +403,10 @@ impl App {
matches!(self.focus, Focus::ResponseSection)
}

pub fn is_status_focused(&self) -> bool {
matches!(self.focus, Focus::StatusHeader)
}

pub fn next_request_tab(&mut self) {
self.request_tab = 1 - self.request_tab; // Toggle between 0 and 1
self.reset_details_scroll();
Expand Down Expand Up @@ -441,7 +448,7 @@ impl App {
// Target editing methods
pub fn start_editing_target(&mut self) {
self.input_mode = InputMode::EditingTarget;
self.input_buffer.clear();
self.input_buffer = self.proxy_config.target_url.clone();
}

pub fn cancel_editing(&mut self) {
Expand Down
140 changes: 111 additions & 29 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,21 @@ async fn run_app(
}
},
KeyCode::Left => {
if app.app_mode == app::AppMode::Normal {
if app.is_status_focused() {
let desired_running = !app.is_running;
if set_proxy_running(
&mut app,
desired_running,
&mut proxy_server,
&message_sender,
&proxy_state,
)
.await
{
terminal.clear()?;
terminal.draw(|f| ui::draw(f, &app))?;
}
} else if app.app_mode == app::AppMode::Normal {
if app.is_request_section_focused() {
app.previous_request_tab();
} else if app.is_response_section_focused() {
Expand All @@ -312,7 +326,21 @@ async fn run_app(
}
}
KeyCode::Right => {
if app.app_mode == app::AppMode::Normal {
if app.is_status_focused() {
let desired_running = !app.is_running;
if set_proxy_running(
&mut app,
desired_running,
&mut proxy_server,
&message_sender,
&proxy_state,
)
.await
{
terminal.clear()?;
terminal.draw(|f| ui::draw(f, &app))?;
}
} else if app.app_mode == app::AppMode::Normal {
if app.is_request_section_focused() {
app.next_request_tab();
} else if app.is_response_section_focused() {
Expand Down Expand Up @@ -495,33 +523,19 @@ async fn run_app(
}
}
KeyCode::Char('s') => {
if app.is_running {
// Stop proxy server first
if let Some(handle) = proxy_server.take() {
handle.abort();
// Wait a bit for cleanup
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
}
app.toggle_proxy();
} else {
// Start proxy server
app.toggle_proxy();
let server = ProxyServer::new(
app.proxy_config.listen_port,
app.proxy_config.target_url.clone(),
message_sender.clone(),
)
.with_state(proxy_state.clone());
proxy_server = Some(tokio::spawn(async move {
if let Err(e) = server.start().await {
eprintln!("Proxy server error: {}", e);
}
}));
let desired_running = !app.is_running;
if set_proxy_running(
&mut app,
desired_running,
&mut proxy_server,
&message_sender,
&proxy_state,
)
.await
{
terminal.clear()?;
terminal.draw(|f| ui::draw(f, &app))?;
}

// Clear and force a redraw after state change
terminal.clear()?;
terminal.draw(|f| ui::draw(f, &app))?;
}
// Pause/Intercept key bindings
KeyCode::Char('p') => {
Expand Down Expand Up @@ -571,6 +585,23 @@ async fn run_app(
}
}
KeyCode::Char('h') => {
if app.is_status_focused() && app.app_mode == app::AppMode::Normal {
let desired_running = !app.is_running;
if set_proxy_running(
&mut app,
desired_running,
&mut proxy_server,
&message_sender,
&proxy_state,
)
.await
{
terminal.clear()?;
terminal.draw(|f| ui::draw(f, &app))?;
}
continue;
}

// Edit selected pending request headers with external editor (intercept mode)
if (app.app_mode == app::AppMode::Paused
|| app.app_mode == app::AppMode::Intercepting)
Expand Down Expand Up @@ -723,7 +754,21 @@ async fn run_app(
terminal.clear()?;
}
KeyCode::Char('l') => {
if app.app_mode == app::AppMode::Normal
if app.is_status_focused() && app.app_mode == app::AppMode::Normal {
let desired_running = !app.is_running;
if set_proxy_running(
&mut app,
desired_running,
&mut proxy_server,
&message_sender,
&proxy_state,
)
.await
{
terminal.clear()?;
terminal.draw(|f| ui::draw(f, &app))?;
}
} else if app.app_mode == app::AppMode::Normal
&& (app.is_request_section_focused()
|| app.is_response_section_focused())
{
Expand Down Expand Up @@ -752,3 +797,40 @@ async fn run_app(
}
}
}

async fn set_proxy_running(
app: &mut App,
should_run: bool,
proxy_server: &mut Option<JoinHandle<()>>,
message_sender: &mpsc::UnboundedSender<app::JsonRpcMessage>,
proxy_state: &ProxyState,
) -> bool {
if should_run == app.is_running {
return false;
}

if should_run {
app.toggle_proxy();

let listen_port = app.proxy_config.listen_port;
let target_url = app.proxy_config.target_url.clone();
let sender_clone = message_sender.clone();
let state_clone = proxy_state.clone();

*proxy_server = Some(tokio::spawn(async move {
let server =
ProxyServer::new(listen_port, target_url, sender_clone).with_state(state_clone);
if let Err(e) = server.start().await {
eprintln!("Proxy server error: {}", e);
}
}));
} else {
if let Some(handle) = proxy_server.take() {
handle.abort();
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
}
app.toggle_proxy();
}

true
}
Loading