Wire topbar tab history navigation

This commit is contained in:
2026-05-13 00:49:52 -04:00
parent 8cd5e969dc
commit 4cb7ff089e
5 changed files with 207 additions and 80 deletions
+35 -1
View File
@@ -28,7 +28,7 @@ impl BrowserCore {
.iter()
.position(|tab| tab.id() == &active_id)
.ok_or_else(|| CoreError::TabNotFound { id: active_id.clone() })?;
self.tabs[tab_index].set_url(url);
self.tabs[tab_index].navigate_to(url);
self.tabs[tab_index].mark_ready();
let snapshot_tab = self.tabs[tab_index].clone();
self.record_history_entry(&snapshot_tab);
@@ -36,6 +36,14 @@ impl BrowserCore {
Ok(())
}
pub fn navigate_active_tab_back(&mut self) -> Result<bool, CoreError> {
self.navigate_active_tab_history(TabHistoryDirection::Back)
}
pub fn navigate_active_tab_forward(&mut self) -> Result<bool, CoreError> {
self.navigate_active_tab_history(TabHistoryDirection::Forward)
}
pub fn open_tab(&mut self, url: UrlText) -> TabId {
let tab = self.build_tab(url);
let tab_id = tab.id().clone();
@@ -369,6 +377,27 @@ impl BrowserCore {
self.tabs.get_mut(active_index).ok_or(CoreError::MissingActiveTab)
}
fn navigate_active_tab_history(
&mut self,
direction: TabHistoryDirection,
) -> Result<bool, CoreError> {
let active_id = self.active_tab_id.clone();
let tab_index = self.active_tab_index()?;
let navigated_url = match direction {
TabHistoryDirection::Back => self.tabs[tab_index].navigate_back(),
TabHistoryDirection::Forward => self.tabs[tab_index].navigate_forward(),
};
let Some(_url) = navigated_url else {
return Ok(false);
};
self.tabs[tab_index].mark_ready();
let snapshot_tab = self.tabs[tab_index].clone();
self.record_history_entry(&snapshot_tab);
self.record_tab_activity(&active_id, SystemTime::now());
Ok(true)
}
pub(super) fn build_tab(&self, url: UrlText) -> BrowserTab {
self.build_tab_for(self.active_space_id.clone(), self.active_profile_id.clone(), url)
.with_parent_tab_id(self.active_tab_id.clone())
@@ -425,3 +454,8 @@ impl BrowserCore {
)
}
}
enum TabHistoryDirection {
Back,
Forward,
}
@@ -0,0 +1,53 @@
use std::error::Error;
use ely_browser_core::{BrowserCore, InitialBrowserConfig};
use ely_domain::UrlText;
#[test]
fn active_tab_tracks_back_and_forward_navigation() -> Result<(), Box<dyn Error>> {
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
core.navigate_active_tab(UrlText::parse("https://example.com/a")?)?;
core.navigate_active_tab(UrlText::parse("https://example.com/b")?)?;
assert!(core.active_tab()?.can_navigate_back());
assert!(!core.active_tab()?.can_navigate_forward());
assert!(core.navigate_active_tab_back()?);
assert_eq!(core.active_tab()?.url().as_str(), "https://example.com/a");
assert!(core.active_tab()?.can_navigate_back());
assert!(core.active_tab()?.can_navigate_forward());
assert!(core.navigate_active_tab_forward()?);
assert_eq!(core.active_tab()?.url().as_str(), "https://example.com/b");
assert!(core.active_tab()?.can_navigate_back());
assert!(!core.active_tab()?.can_navigate_forward());
Ok(())
}
#[test]
fn new_navigation_clears_forward_stack() -> Result<(), Box<dyn Error>> {
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
core.navigate_active_tab(UrlText::parse("https://example.com/a")?)?;
core.navigate_active_tab(UrlText::parse("https://example.com/b")?)?;
assert!(core.navigate_active_tab_back()?);
core.navigate_active_tab(UrlText::parse("https://example.com/c")?)?;
assert_eq!(core.active_tab()?.url().as_str(), "https://example.com/c");
assert!(core.active_tab()?.can_navigate_back());
assert!(!core.active_tab()?.can_navigate_forward());
Ok(())
}
#[test]
fn empty_history_navigation_keeps_active_url() -> Result<(), Box<dyn Error>> {
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
let url = core.active_tab()?.url().clone();
assert!(!core.navigate_active_tab_back()?);
assert!(!core.navigate_active_tab_forward()?);
assert_eq!(core.active_tab()?.url(), &url);
Ok(())
}