Fix browser preview URL tracking and reorganize layout

- Move preview panel to left, status panel to right
- Display current URL in preview panel title instead of status
- Add get_current_url() method to query browser directly (not cached)
- Update all screenshot captures to fetch fresh URL from browser
- Enhanced logging for debugging URL changes
- Fix URL updates for JavaScript navigation and redirects

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
This commit is contained in:
James Peter
2025-08-12 11:01:39 +10:00
co-authored by Claude
parent 3778243b76
commit 47bc2722ee
5 changed files with 52 additions and 31 deletions
@@ -50,7 +50,7 @@ impl BrowserInjector {
let ttl_ms = 300000;
let images = self.asset_manager.store_screenshots(screenshots, ttl_ms).await?;
let current_url = page.get_url().await.unwrap_or_else(|_| "about:blank".to_string());
let current_url = page.get_current_url().await.unwrap_or_else(|_| "about:blank".to_string());
let system_hint = format!(
"A fresh screenshot of the active page ({}) is attached; use browser.* tools to navigate or capture more.",
+3 -3
View File
@@ -202,7 +202,7 @@ impl BrowserManager {
pub async fn get_current_url(&self) -> Option<String> {
let page_guard = self.page.lock().await;
if let Some(page) = page_guard.as_ref() {
page.get_url().await.ok()
page.get_current_url().await.ok()
} else {
None
}
@@ -404,8 +404,8 @@ impl BrowserManager {
crate::page::ScreenshotMode::Viewport
};
// Get current URL
let current_url = page.get_url().await.unwrap_or_else(|_| "about:blank".to_string());
// Get current URL directly from the browser (not cached)
let current_url = page.get_current_url().await.unwrap_or_else(|_| "about:blank".to_string());
// Capture screenshots
let screenshots = page.screenshot(mode).await?;
+8
View File
@@ -242,6 +242,14 @@ impl Page {
.ok_or(BrowserError::PageNotLoaded)
}
/// Get the current URL directly from the browser (not cached)
pub async fn get_current_url(&self) -> Result<String> {
match self.cdp_page.url().await? {
Some(url) => Ok(url),
None => Err(BrowserError::PageNotLoaded)
}
}
pub async fn update_viewport(&self, viewport: ViewportConfig) -> Result<()> {
let params = SetDeviceMetricsOverrideParams::builder()
.width(viewport.width as i64)
+14 -3
View File
@@ -2877,19 +2877,26 @@ async fn capture_browser_screenshot(sess: &Session) -> Option<(PathBuf, String)>
// Get current URL first
let url = browser_manager.get_current_url().await
.unwrap_or_else(|| "Browser".to_string());
tracing::debug!("Attempting to capture screenshot at URL: {}", url);
match browser_manager.capture_screenshot().await {
Ok(screenshots) => {
if let Some(first_screenshot) = screenshots.first() {
tracing::info!("Captured browser screenshot: {} at URL: {}", first_screenshot.display(), url);
return Some((first_screenshot.clone(), url));
} else {
tracing::warn!("Screenshot capture returned empty results at URL: {}", url);
}
}
Err(e) => {
tracing::warn!("Failed to capture browser screenshot: {}", e);
tracing::warn!("Failed to capture browser screenshot at URL {}: {}", url, e);
}
}
} else {
tracing::debug!("Browser manager is not enabled, skipping screenshot capture");
}
} else {
tracing::debug!("No browser manager available for screenshot capture");
}
None
}
@@ -2990,9 +2997,13 @@ async fn handle_browser_open(
// Navigate to the URL
match browser_manager.goto(url).await {
Ok(_) => {
tracing::info!("Browser navigation to {} completed successfully", url);
// Capture screenshot after navigation
if let Some((screenshot_path, url)) = capture_browser_screenshot(sess).await {
add_pending_screenshot(sess, screenshot_path, url);
if let Some((screenshot_path, updated_url)) = capture_browser_screenshot(sess).await {
tracing::info!("Screenshot captured after navigation: {} at URL: {}", screenshot_path.display(), updated_url);
add_pending_screenshot(sess, screenshot_path, updated_url);
} else {
tracing::warn!("Failed to capture screenshot after navigation to {}", url);
}
ResponseInputItem::FunctionCallOutput {
+26 -24
View File
@@ -37,7 +37,6 @@ use ratatui::buffer::Buffer;
use ratatui::layout::Constraint;
use ratatui::layout::Layout;
use ratatui::layout::Rect;
use ratatui::style::Modifier;
use ratatui::text::Line;
use ratatui::widgets::Widget;
use ratatui::widgets::WidgetRef;
@@ -1014,7 +1013,14 @@ impl ChatWidget<'_> {
// Update the latest screenshot and URL for display
if let Ok(mut latest) = self.latest_browser_screenshot.lock() {
*latest = Some((screenshot_path, url));
let old_url = latest.as_ref().map(|(_, u)| u.clone());
*latest = Some((screenshot_path.clone(), url.clone()));
if old_url.as_ref() != Some(&url) {
tracing::info!("Browser URL changed from {:?} to {}", old_url, url);
}
tracing::debug!("Updated browser screenshot display with path: {} and URL: {}", screenshot_path.display(), url);
} else {
tracing::warn!("Failed to acquire lock for browser screenshot update");
}
// Request a redraw to update the display immediately
@@ -1661,31 +1667,39 @@ impl ChatWidget<'_> {
if let Ok(screenshot_lock) = self.latest_browser_screenshot.lock() {
if let Some((screenshot_path, url)) = &*screenshot_lock {
// Split the HUD into two parts: left for info, right for screenshot (50% width)
// Split the HUD into two parts: left for preview, right for status (50% width)
let chunks = Layout::horizontal([
Constraint::Percentage(50),
Constraint::Percentage(50),
])
.areas::<2>(padded_area);
let info_area = chunks[0];
let screenshot_area = chunks[1];
let screenshot_area = chunks[0]; // Preview on the left
let info_area = chunks[1]; // Status on the right
// Left side: Browser info and URL
// Left side: Screenshot with URL in title
let screenshot_block = Block::default()
.borders(Borders::ALL)
.title(format!(" {} ", url)) // URL in the title
.border_style(Style::default().fg(crate::colors::border()));
let inner_screenshot = screenshot_block.inner(screenshot_area);
screenshot_block.render(screenshot_area, buf);
// Render the screenshot
self.render_screenshot_highlevel(screenshot_path, inner_screenshot, buf);
// Right side: Browser status
let info_block = Block::default()
.borders(Borders::ALL)
.title(" Browser ")
.title(" Browser Status ")
.border_style(Style::default().fg(crate::colors::border()));
let inner_info = info_block.inner(info_area);
info_block.render(info_area, buf);
// Display URL and browser status
// Display browser status information
let mut lines = vec![];
lines.push(RLine::from(vec![
Span::styled("URL: ", Style::default().fg(crate::colors::text_dim())),
Span::styled(url.clone(), Style::default().fg(crate::colors::text()).add_modifier(Modifier::BOLD)),
]));
// Add browser status information
if self.browser_manager.is_enabled_sync() {
@@ -1702,18 +1716,6 @@ impl ChatWidget<'_> {
let info_paragraph = Paragraph::new(lines);
info_paragraph.render(inner_info, buf);
// Right side: Screenshot with border
let screenshot_block = Block::default()
.borders(Borders::ALL)
.title(" Preview ")
.border_style(Style::default().fg(crate::colors::border()));
let inner_screenshot = screenshot_block.inner(screenshot_area);
screenshot_block.render(screenshot_area, buf);
// Render the screenshot
self.render_screenshot_highlevel(screenshot_path, inner_screenshot, buf);
}
}
}