Add Bookmarks section to command overlay
Design's command switcher exposes Open tabs / History / Bookmarks / Actions. The implementation now includes a Bookmarks section sourced from snapshot.bookmarks: filtered by lowercase needle on title and URL, capped at RESULT_LIMIT, rendered with brand glyphs, opening the URL on click. Match helpers (matching_tabs / matching_history / matching_bookmarks) move into chrome::command_match so command_overlay.rs stays under the 500-line ceiling. Ask ELY remains skipped — no AI surface in domain yet, no fabrication.
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
use ely_browser_core::BrowserSnapshot;
|
||||||
|
use ely_domain::{BookmarkEntry, BrowserTab, HistoryEntry};
|
||||||
|
|
||||||
|
pub(crate) const RESULT_LIMIT: usize = 4;
|
||||||
|
|
||||||
|
pub(crate) fn matching_tabs<'a>(
|
||||||
|
snapshot: &'a BrowserSnapshot,
|
||||||
|
needle: &str,
|
||||||
|
) -> Vec<&'a BrowserTab> {
|
||||||
|
if needle.is_empty() {
|
||||||
|
return snapshot.tabs.iter().take(RESULT_LIMIT).collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot
|
||||||
|
.tabs
|
||||||
|
.iter()
|
||||||
|
.filter(|tab| matches_tab(tab, needle))
|
||||||
|
.take(RESULT_LIMIT)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matches_tab(tab: &BrowserTab, needle: &str) -> bool {
|
||||||
|
tab.title().to_lowercase().contains(needle)
|
||||||
|
|| tab.url().as_str().to_lowercase().contains(needle)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn matching_history<'a>(
|
||||||
|
snapshot: &'a BrowserSnapshot,
|
||||||
|
needle: &str,
|
||||||
|
) -> Vec<&'a HistoryEntry> {
|
||||||
|
if needle.is_empty() {
|
||||||
|
return snapshot.history_entries.iter().rev().take(RESULT_LIMIT).collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot
|
||||||
|
.history_entries
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.filter(|entry| matches_history(entry, needle))
|
||||||
|
.take(RESULT_LIMIT)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matches_history(entry: &HistoryEntry, needle: &str) -> bool {
|
||||||
|
entry.title().to_lowercase().contains(needle)
|
||||||
|
|| entry.url().as_str().to_lowercase().contains(needle)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn matching_bookmarks<'a>(
|
||||||
|
snapshot: &'a BrowserSnapshot,
|
||||||
|
needle: &str,
|
||||||
|
) -> Vec<&'a BookmarkEntry> {
|
||||||
|
if needle.is_empty() {
|
||||||
|
return snapshot.bookmarks.iter().take(RESULT_LIMIT).collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot
|
||||||
|
.bookmarks
|
||||||
|
.iter()
|
||||||
|
.filter(|bookmark| matches_bookmark(bookmark, needle))
|
||||||
|
.take(RESULT_LIMIT)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matches_bookmark(bookmark: &BookmarkEntry, needle: &str) -> bool {
|
||||||
|
bookmark.title().to_lowercase().contains(needle)
|
||||||
|
|| bookmark.url().as_str().to_lowercase().contains(needle)
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use ely_browser_core::BrowserSnapshot;
|
use ely_browser_core::BrowserSnapshot;
|
||||||
use ely_design_system::colors;
|
use ely_design_system::colors;
|
||||||
use ely_domain::{BrowserTab, HistoryEntry};
|
use ely_domain::{BookmarkEntry, BrowserTab, HistoryEntry};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, BoxShadow, Context, FontWeight, InteractiveElement, IntoElement, ParentElement,
|
AnyElement, BoxShadow, Context, FontWeight, InteractiveElement, IntoElement, ParentElement,
|
||||||
SharedString, StatefulInteractiveElement, Styled, div, hsla, point, px, rgb, rgba,
|
SharedString, StatefulInteractiveElement, Styled, div, hsla, point, px, rgb, rgba,
|
||||||
@@ -9,10 +9,12 @@ use gpui_component::IconName;
|
|||||||
|
|
||||||
use crate::shell::ElyShell;
|
use crate::shell::ElyShell;
|
||||||
use crate::shell::chrome::command_footer::{render_command_footer, render_kbd};
|
use crate::shell::chrome::command_footer::{render_command_footer, render_kbd};
|
||||||
|
use crate::shell::chrome::command_match::{
|
||||||
|
matching_bookmarks, matching_history, matching_tabs,
|
||||||
|
};
|
||||||
use crate::shell::chrome::render_glyph_for;
|
use crate::shell::chrome::render_glyph_for;
|
||||||
|
|
||||||
const COMMAND_PREFIX: &str = ">";
|
const COMMAND_PREFIX: &str = ">";
|
||||||
const RESULT_LIMIT: usize = 4;
|
|
||||||
|
|
||||||
pub(crate) fn render_command_overlay(
|
pub(crate) fn render_command_overlay(
|
||||||
snapshot: &BrowserSnapshot,
|
snapshot: &BrowserSnapshot,
|
||||||
@@ -114,6 +116,7 @@ fn render_results(
|
|||||||
) -> AnyElement {
|
) -> AnyElement {
|
||||||
let tabs = matching_tabs(snapshot, needle);
|
let tabs = matching_tabs(snapshot, needle);
|
||||||
let history = matching_history(snapshot, needle);
|
let history = matching_history(snapshot, needle);
|
||||||
|
let bookmarks = matching_bookmarks(snapshot, needle);
|
||||||
let actions = matching_actions(needle);
|
let actions = matching_actions(needle);
|
||||||
|
|
||||||
let mut sections: Vec<AnyElement> = Vec::new();
|
let mut sections: Vec<AnyElement> = Vec::new();
|
||||||
@@ -123,6 +126,12 @@ fn render_results(
|
|||||||
if !history.is_empty() {
|
if !history.is_empty() {
|
||||||
sections.push(render_section("History", render_history_rows(history, cx)));
|
sections.push(render_section("History", render_history_rows(history, cx)));
|
||||||
}
|
}
|
||||||
|
if !bookmarks.is_empty() {
|
||||||
|
sections.push(render_section(
|
||||||
|
"Bookmarks",
|
||||||
|
render_bookmark_rows(bookmarks, cx),
|
||||||
|
));
|
||||||
|
}
|
||||||
if !actions.is_empty() {
|
if !actions.is_empty() {
|
||||||
sections.push(render_section("Actions", render_action_rows(actions, cx)));
|
sections.push(render_section("Actions", render_action_rows(actions, cx)));
|
||||||
}
|
}
|
||||||
@@ -420,46 +429,39 @@ fn render_empty_state() -> AnyElement {
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matching_tabs<'a>(
|
fn render_bookmark_rows(
|
||||||
snapshot: &'a BrowserSnapshot,
|
entries: Vec<&BookmarkEntry>,
|
||||||
needle: &str,
|
cx: &mut Context<ElyShell>,
|
||||||
) -> Vec<&'a BrowserTab> {
|
) -> AnyElement {
|
||||||
if needle.is_empty() {
|
div()
|
||||||
return snapshot.tabs.iter().take(RESULT_LIMIT).collect();
|
.flex()
|
||||||
}
|
.flex_col()
|
||||||
|
.children(entries.into_iter().enumerate().map(|(index, bookmark)| {
|
||||||
|
let url = bookmark.url().clone();
|
||||||
|
let title = bookmark.title().to_string();
|
||||||
|
let host = bookmark.url().host().map(|host| host.to_string());
|
||||||
|
let display = host
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| bookmark.url().as_str().to_string());
|
||||||
|
let initial = title.chars().next().unwrap_or('?').to_string();
|
||||||
|
|
||||||
snapshot
|
render_row_with_glyph(
|
||||||
.tabs
|
CommandRowContent {
|
||||||
.iter()
|
id: format!("cmd-bookmark-{index}"),
|
||||||
.filter(|tab| matches_tab(tab, needle))
|
title,
|
||||||
.take(RESULT_LIMIT)
|
hint: Some(display),
|
||||||
.collect()
|
keys: None,
|
||||||
}
|
},
|
||||||
|
host.as_deref(),
|
||||||
fn matches_tab(tab: &BrowserTab, needle: &str) -> bool {
|
&initial,
|
||||||
tab.title().to_lowercase().contains(needle) || tab.url().as_str().to_lowercase().contains(needle)
|
cx,
|
||||||
}
|
move |shell, window, cx| {
|
||||||
|
shell.open_internal_tab(url.as_str(), window, cx);
|
||||||
fn matching_history<'a>(
|
shell.dismiss_command_mode(window, cx);
|
||||||
snapshot: &'a BrowserSnapshot,
|
},
|
||||||
needle: &str,
|
)
|
||||||
) -> Vec<&'a HistoryEntry> {
|
}))
|
||||||
if needle.is_empty() {
|
.into_any_element()
|
||||||
return snapshot.history_entries.iter().rev().take(RESULT_LIMIT).collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
snapshot
|
|
||||||
.history_entries
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.filter(|entry| matches_history(entry, needle))
|
|
||||||
.take(RESULT_LIMIT)
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn matches_history(entry: &HistoryEntry, needle: &str) -> bool {
|
|
||||||
entry.title().to_lowercase().contains(needle)
|
|
||||||
|| entry.url().as_str().to_lowercase().contains(needle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PANEL_BG: u32 = 0xfffffff5;
|
const PANEL_BG: u32 = 0xfffffff5;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ pub(crate) mod appearance_form;
|
|||||||
pub(crate) mod appearance_layout_cards;
|
pub(crate) mod appearance_layout_cards;
|
||||||
pub(crate) mod brand_glyph;
|
pub(crate) mod brand_glyph;
|
||||||
pub(crate) mod command_footer;
|
pub(crate) mod command_footer;
|
||||||
|
pub(crate) mod command_match;
|
||||||
pub(crate) mod command_overlay;
|
pub(crate) mod command_overlay;
|
||||||
pub(crate) mod home;
|
pub(crate) mod home;
|
||||||
pub(crate) mod plugin_detail_view;
|
pub(crate) mod plugin_detail_view;
|
||||||
|
|||||||
Reference in New Issue
Block a user