Restore archived tabs from command scope
This commit is contained in:
@@ -128,6 +128,29 @@ impl BrowserCore {
|
|||||||
pub fn restore_last_archived_tab(&mut self) -> Result<TabId, CoreError> {
|
pub fn restore_last_archived_tab(&mut self) -> Result<TabId, CoreError> {
|
||||||
let archived_tab = self.archived_tabs.pop().ok_or(CoreError::NoArchivedTabs)?;
|
let archived_tab = self.archived_tabs.pop().ok_or(CoreError::NoArchivedTabs)?;
|
||||||
let tab = archived_tab.into_tab();
|
let tab = archived_tab.into_tab();
|
||||||
|
self.restore_tab(tab)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restore_archived_tab_match(&mut self, query: &str) -> Result<Option<TabId>, CoreError> {
|
||||||
|
let normalized_query = query.trim().to_lowercase();
|
||||||
|
if normalized_query.is_empty() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(index) = self
|
||||||
|
.archived_tabs
|
||||||
|
.iter()
|
||||||
|
.rposition(|archived| tab_matches_query(archived.tab(), &normalized_query))
|
||||||
|
else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let archived_tab = self.archived_tabs.remove(index);
|
||||||
|
let tab = archived_tab.into_tab();
|
||||||
|
self.restore_tab(tab).map(Some)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore_tab(&mut self, tab: BrowserTab) -> Result<TabId, CoreError> {
|
||||||
let tab_id = tab.id().clone();
|
let tab_id = tab.id().clone();
|
||||||
let insert_index = self
|
let insert_index = self
|
||||||
.tabs
|
.tabs
|
||||||
@@ -219,6 +242,11 @@ impl BrowserCore {
|
|||||||
self.command_query.clear();
|
self.command_query.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CommandIntent::ScopedSearch { scope: CommandScope::Archive, query }
|
||||||
|
if self.restore_archived_tab_match(query)?.is_some() =>
|
||||||
|
{
|
||||||
|
self.command_query.clear();
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,47 @@ fn restore_tab_command_reopens_last_archived_tab() -> Result<(), Box<dyn Error>>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn archive_scoped_search_restores_matching_archived_tab() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
core.open_tab(UrlText::parse("https://example.com")?);
|
||||||
|
let servo_tab_id = core.open_tab(UrlText::parse("https://servo.org")?);
|
||||||
|
core.close_active_tab()?;
|
||||||
|
|
||||||
|
core.set_command_query("@archive servo");
|
||||||
|
let intent = core.submit_command()?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
intent,
|
||||||
|
Some(CommandIntent::ScopedSearch {
|
||||||
|
scope: ely_domain::CommandScope::Archive,
|
||||||
|
query: "servo".to_string()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
assert_eq!(snapshot.active_tab_id, servo_tab_id);
|
||||||
|
assert!(snapshot.archived_tabs.is_empty());
|
||||||
|
assert_eq!(snapshot.command_query, "");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn archive_scoped_search_preserves_query_without_match() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
core.open_tab(UrlText::parse("https://example.com")?);
|
||||||
|
core.close_active_tab()?;
|
||||||
|
let active_tab_id = core.active_tab()?.id().clone();
|
||||||
|
|
||||||
|
core.set_command_query("@archive absent");
|
||||||
|
core.submit_command()?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
|
||||||
|
assert_eq!(snapshot.active_tab_id, active_tab_id);
|
||||||
|
assert_eq!(snapshot.archived_tabs.len(), 1);
|
||||||
|
assert_eq!(snapshot.command_query, "@archive absent");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unknown_command_preserves_query() -> Result<(), Box<dyn Error>> {
|
fn unknown_command_preserves_query() -> Result<(), Box<dyn Error>> {
|
||||||
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
|||||||
@@ -73,6 +73,42 @@ fn restores_last_archived_tab() -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn restores_matching_archived_tab() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
let example_tab_id = core.open_tab(UrlText::parse("https://example.com")?);
|
||||||
|
let servo_tab_id = core.open_tab(UrlText::parse("https://servo.org")?);
|
||||||
|
|
||||||
|
core.close_active_tab()?;
|
||||||
|
core.select_tab(&example_tab_id)?;
|
||||||
|
core.close_active_tab()?;
|
||||||
|
|
||||||
|
let restored_tab_id = core.restore_archived_tab_match("servo")?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
|
||||||
|
assert_eq!(restored_tab_id, Some(servo_tab_id.clone()));
|
||||||
|
assert_eq!(snapshot.active_tab_id, servo_tab_id);
|
||||||
|
assert_eq!(snapshot.archived_tabs.len(), 1);
|
||||||
|
assert_eq!(snapshot.archived_tabs[0].tab().id(), &example_tab_id);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ignores_empty_archived_tab_match_query() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
core.open_tab(UrlText::parse("https://example.com")?);
|
||||||
|
core.close_active_tab()?;
|
||||||
|
let active_tab_id = core.active_tab()?.id().clone();
|
||||||
|
|
||||||
|
let restored_tab_id = core.restore_archived_tab_match(" ")?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
|
||||||
|
assert_eq!(restored_tab_id, None);
|
||||||
|
assert_eq!(snapshot.active_tab_id, active_tab_id);
|
||||||
|
assert_eq!(snapshot.archived_tabs.len(), 1);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn restore_without_archived_tabs_returns_error() -> Result<(), Box<dyn Error>> {
|
fn restore_without_archived_tabs_returns_error() -> Result<(), Box<dyn Error>> {
|
||||||
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use crate::{DomainError, UrlText};
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum CommandScope {
|
pub enum CommandScope {
|
||||||
|
Archive,
|
||||||
Tabs,
|
Tabs,
|
||||||
Bookmarks,
|
Bookmarks,
|
||||||
History,
|
History,
|
||||||
@@ -43,6 +44,7 @@ impl CommandIntent {
|
|||||||
fn parse_scope(value: &str) -> Option<(CommandScope, &str)> {
|
fn parse_scope(value: &str) -> Option<(CommandScope, &str)> {
|
||||||
let (scope, query) = value.split_once(' ')?;
|
let (scope, query) = value.split_once(' ')?;
|
||||||
let scope = match scope {
|
let scope = match scope {
|
||||||
|
"@archive" => CommandScope::Archive,
|
||||||
"@tabs" => CommandScope::Tabs,
|
"@tabs" => CommandScope::Tabs,
|
||||||
"@bookmarks" => CommandScope::Bookmarks,
|
"@bookmarks" => CommandScope::Bookmarks,
|
||||||
"@history" => CommandScope::History,
|
"@history" => CommandScope::History,
|
||||||
|
|||||||
Reference in New Issue
Block a user