From 05ce4afba46c05e48922768363f2c6523beeab74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Wed, 13 May 2026 01:54:51 -0400 Subject: [PATCH] Poll only visible web surfaces --- crates/ely_app/src/shell/web_surface.rs | 4 +-- .../src/shell/web_surface_controller.rs | 8 +++++- .../src/shell/web_surface_live_site_tests.rs | 2 +- .../ely_app/src/shell/web_surface_runtime.rs | 5 +++- crates/ely_browser_core/src/state.rs | 1 + .../src/state/visible_content.rs | 22 ++++++++++++++++ crates/ely_browser_core/tests/splits.rs | 25 +++++++++++++++++++ 7 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 crates/ely_browser_core/src/state/visible_content.rs diff --git a/crates/ely_app/src/shell/web_surface.rs b/crates/ely_app/src/shell/web_surface.rs index eade280..12d4299 100644 --- a/crates/ely_app/src/shell/web_surface.rs +++ b/crates/ely_app/src/shell/web_surface.rs @@ -74,8 +74,8 @@ impl WebSurfaceStore { } } - pub(super) fn tick(&mut self) -> WebSurfaceTickResult { - let frames = self.runtime.tick(); + pub(super) fn tick(&mut self, visible_tab_ids: &[TabId]) -> WebSurfaceTickResult { + let frames = self.runtime.tick(visible_tab_ids); let mut result = WebSurfaceTickResult::default(); for frame in frames { diff --git a/crates/ely_app/src/shell/web_surface_controller.rs b/crates/ely_app/src/shell/web_surface_controller.rs index f3d570b..3b7e075 100644 --- a/crates/ely_app/src/shell/web_surface_controller.rs +++ b/crates/ely_app/src/shell/web_surface_controller.rs @@ -51,7 +51,13 @@ impl ElyShell { } pub(super) fn tick_external_web_surfaces(&mut self) -> bool { - let result = self.web_surfaces.tick(); + let visible_tab_ids = match &self.state { + super::ShellState::Ready(core) => { + core.visible_content_tab_ids().unwrap_or_else(|_| Vec::new()) + } + super::ShellState::StartupError(_) => Vec::new(), + }; + let result = self.web_surfaces.tick(&visible_tab_ids); let mut url_changed = false; for url_change in result.url_changes { url_changed |= self.apply_web_surface_url_change(url_change); diff --git a/crates/ely_app/src/shell/web_surface_live_site_tests.rs b/crates/ely_app/src/shell/web_surface_live_site_tests.rs index 132bf5f..87e71c9 100644 --- a/crates/ely_app/src/shell/web_surface_live_site_tests.rs +++ b/crates/ely_app/src/shell/web_surface_live_site_tests.rs @@ -134,7 +134,7 @@ fn wait_for_ready_frame( return Err(format!("timed out rendering {}", case.url)); } - store.tick(); + store.tick(std::slice::from_ref(tab_id)); match store.state(tab_id) { Some(WebSurfaceState::Ready(frame)) => { validate_prd_frame(frame, case)?; diff --git a/crates/ely_app/src/shell/web_surface_runtime.rs b/crates/ely_app/src/shell/web_surface_runtime.rs index d141446..ae1bdfc 100644 --- a/crates/ely_app/src/shell/web_surface_runtime.rs +++ b/crates/ely_app/src/shell/web_surface_runtime.rs @@ -101,7 +101,7 @@ impl WebSurfaceRuntime { Ok(WebSurfaceEnsureResult { requested_url, started_loading, frame, url_change }) } - pub(super) fn tick(&mut self) -> Vec { + pub(super) fn tick(&mut self, visible_tab_ids: &[TabId]) -> Vec { let (state, sessions) = (&mut self.state, &mut self.sessions); let RuntimeState::Ready { client, .. } = state else { return Vec::new(); @@ -109,6 +109,9 @@ impl WebSurfaceRuntime { let mut frames = Vec::new(); for (tab_id, session) in sessions { + if !visible_tab_ids.iter().any(|visible_tab_id| visible_tab_id == tab_id) { + continue; + } match client.poll(tab_id.as_str().to_string()) { Ok(Some(frame)) => match WebSurfaceFrame::from_live_frame( session.requested_url.clone(), diff --git a/crates/ely_browser_core/src/state.rs b/crates/ely_browser_core/src/state.rs index 458d7df..604bb78 100644 --- a/crates/ely_browser_core/src/state.rs +++ b/crates/ely_browser_core/src/state.rs @@ -36,6 +36,7 @@ mod tab_lifecycle; mod tab_order; mod tab_selection; mod tabs; +mod visible_content; pub use bookmarks::{ BookmarkImportSummary, ELYBOOKMARKS_FILE_EXTENSION, ELYBOOKMARKS_SCHEMA_VERSION, diff --git a/crates/ely_browser_core/src/state/visible_content.rs b/crates/ely_browser_core/src/state/visible_content.rs new file mode 100644 index 0000000..4e5ddb2 --- /dev/null +++ b/crates/ely_browser_core/src/state/visible_content.rs @@ -0,0 +1,22 @@ +use ely_domain::TabId; + +use super::BrowserCore; +use crate::CoreError; + +impl BrowserCore { + pub fn visible_content_tab_ids(&self) -> Result, CoreError> { + let active_tab = self.active_tab()?; + let Some(split_id) = active_tab.split_id() else { + return Ok(vec![active_tab.id().clone()]); + }; + let layout = self + .split_layouts + .iter() + .find(|layout| layout.id() == split_id) + .ok_or_else(|| CoreError::SplitNotFound { id: split_id.clone() })?; + if layout.pane_count() < 2 { + return Ok(vec![active_tab.id().clone()]); + } + Ok(layout.panes().iter().map(|pane| pane.tab_id().clone()).collect()) + } +} diff --git a/crates/ely_browser_core/tests/splits.rs b/crates/ely_browser_core/tests/splits.rs index 1e9c869..de968da 100644 --- a/crates/ely_browser_core/tests/splits.rs +++ b/crates/ely_browser_core/tests/splits.rs @@ -25,6 +25,31 @@ fn split_right_creates_two_pane_layout() -> Result<(), Box> { Ok(()) } +#[test] +fn visible_content_tab_ids_returns_active_tab_without_split() -> Result<(), Box> { + let core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?; + let active_tab_id = core.active_tab()?.id().clone(); + + assert_eq!(core.visible_content_tab_ids()?, vec![active_tab_id]); + Ok(()) +} + +#[test] +fn visible_content_tab_ids_returns_split_panes() -> Result<(), Box> { + let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?; + let split_id = core.split_active_tab_right()?; + let snapshot = core.snapshot()?; + let layout = snapshot + .split_layouts + .iter() + .find(|layout| layout.id() == &split_id) + .ok_or("missing split layout")?; + let pane_ids = layout.panes().iter().map(|pane| pane.tab_id().clone()).collect::>(); + + assert_eq!(core.visible_content_tab_ids()?, pane_ids); + Ok(()) +} + #[test] fn split_right_command_focuses_new_pane() -> Result<(), Box> { let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;