Apply cargo fmt across chrome and internal pages

This commit is contained in:
2026-05-15 16:42:00 -04:00
parent 90c029eddb
commit 00a8ff1fef
30 changed files with 287 additions and 814 deletions
+4 -11
View File
@@ -16,11 +16,9 @@ pub(crate) fn blink<E>(id: impl Into<ElementId>, element: E) -> impl IntoElement
where
E: IntoElement + Styled + 'static,
{
element.with_animation(
id,
Animation::new(Duration::from_secs(1)).repeat(),
|element, t| element.opacity(if t < 0.5 { 1.0 } else { 0.0 }),
)
element.with_animation(id, Animation::new(Duration::from_secs(1)).repeat(), |element, t| {
element.opacity(if t < 0.5 { 1.0 } else { 0.0 })
})
}
/// Soft fade-in over `panel_transition_ms` once the element first mounts.
@@ -28,15 +26,10 @@ where
/// Drives the design's `panel transition` motion token (180 ms productive)
/// for surfaces like the command overlay and workspace disclosure that
/// appear / disappear in response to user input.
pub(crate) fn fade_in<E>(
id: impl Into<ElementId>,
duration_ms: u64,
element: E,
) -> impl IntoElement
pub(crate) fn fade_in<E>(id: impl Into<ElementId>, duration_ms: u64, element: E) -> impl IntoElement
where
E: IntoElement + Styled + 'static,
{
let animation = Animation::new(Duration::from_millis(duration_ms));
element.with_animation(id, animation, |element, t| element.opacity(t))
}
@@ -46,12 +46,7 @@ fn render_header() -> AnyElement {
.flex()
.flex_col()
.gap(px(6.0))
.child(
div()
.text_size(px(11.0))
.text_color(rgb(colors::INK_4))
.child("GENERAL"),
)
.child(div().text_size(px(11.0)).text_color(rgb(colors::INK_4)).child("GENERAL"))
.child(
div()
.font_family(SERIF_FAMILY)
@@ -60,23 +55,14 @@ fn render_header() -> AnyElement {
.text_color(rgb(colors::INK))
.child("Appearance"),
)
.child(
div()
.max_w(px(520.0))
.text_size(px(13.0))
.text_color(rgb(colors::INK_3))
.child(
.child(div().max_w(px(520.0)).text_size(px(13.0)).text_color(rgb(colors::INK_3)).child(
"Tune the atmosphere of your browser. ELY's wallpaper sets the ambient \
palette of every surface; pick one and let it breathe.",
),
)
))
.into_any_element()
}
fn render_wallpaper_grid(
snapshot: &BrowserSnapshot,
cx: &mut Context<ElyShell>,
) -> AnyElement {
fn render_wallpaper_grid(snapshot: &BrowserSnapshot, cx: &mut Context<ElyShell>) -> AnyElement {
let active = snapshot.appearance.wallpaper();
div()
.grid()
@@ -114,35 +100,21 @@ fn render_wallpaper_swatch(
div()
.h(px(96.0))
.rounded(px(10.0))
.when(selected, |el| {
el.border_2().border_color(rgb(colors::ACCENT))
})
.when(!selected, |el| {
el.border_1().border_color(rgba(colors::STROKE))
})
.when(selected, |el| el.border_2().border_color(rgb(colors::ACCENT)))
.when(!selected, |el| el.border_1().border_color(rgba(colors::STROKE)))
.relative()
.overflow_hidden()
.bg(rgb(base))
.child(
div()
.absolute()
.inset_0()
.bg(linear_gradient(
.child(div().absolute().inset_0().bg(linear_gradient(
225.0,
linear_color_stop(upper, 0.0),
linear_color_stop(transparent_like(upper), 0.6),
)),
)
.child(
div()
.absolute()
.inset_0()
.bg(linear_gradient(
)))
.child(div().absolute().inset_0().bg(linear_gradient(
45.0,
linear_color_stop(lower, 0.0),
linear_color_stop(transparent_like(lower), 0.6),
)),
),
))),
)
.child(
div()
@@ -158,11 +130,7 @@ fn render_wallpaper_swatch(
.child(label),
)
.when(selected, |el| {
el.child(
div()
.text_color(rgb(colors::ACCENT))
.child(IconName::Check),
)
el.child(div().text_color(rgb(colors::ACCENT)).child(IconName::Check))
}),
)
.into_any_element()
@@ -186,10 +154,7 @@ fn render_appearance_rows(
.into_any_element()
}
fn render_translucency_row(
shell: &mut ElyShell,
pct: u8,
) -> AnyElement {
fn render_translucency_row(shell: &mut ElyShell, pct: u8) -> AnyElement {
let slider_state = shell.translucency_slider.clone();
settings_row(
"Translucency",
@@ -216,12 +181,7 @@ fn render_translucency_presets(cx: &mut Context<ElyShell>) -> AnyElement {
.items_center()
.gap(px(8.0))
.pt(px(2.0))
.child(
div()
.text_size(px(10.5))
.text_color(rgb(colors::INK_4))
.child("Presets"),
)
.child(div().text_size(px(10.5)).text_color(rgb(colors::INK_4)).child("Presets"))
.child(translucency_preset("Solid", 0, cx))
.child(translucency_preset("Default", 40, cx))
.child(translucency_preset("Glassy", 75, cx))
@@ -254,10 +214,7 @@ fn translucency_preset(
.into_any_element()
}
fn render_theme_mode_row(
active: ThemeMode,
cx: &mut Context<ElyShell>,
) -> AnyElement {
fn render_theme_mode_row(active: ThemeMode, cx: &mut Context<ElyShell>) -> AnyElement {
settings_row(
"Theme mode",
"Match system appearance, or pick one to lock.",
@@ -329,9 +286,7 @@ fn swatch(color: u32, selected: bool) -> AnyElement {
.border_1()
.border_color(rgba(0x0000000d));
if selected {
element = element
.border_2()
.border_color(rgb(colors::ACCENT));
element = element.border_2().border_color(rgb(colors::ACCENT));
}
element.into_any_element()
}
@@ -408,12 +363,7 @@ fn settings_row(title: &'static str, detail: &'static str, control: AnyElement)
.text_color(rgb(colors::INK))
.child(title),
)
.child(
div()
.text_size(px(11.5))
.text_color(rgb(colors::INK_3))
.child(detail),
),
.child(div().text_size(px(11.5)).text_color(rgb(colors::INK_3)).child(detail)),
)
.child(control)
.into_any_element()
@@ -430,26 +380,18 @@ fn wallpaper_label(theme: WallpaperTheme) -> &'static str {
fn swatch_colors(theme: WallpaperTheme) -> (Hsla, Hsla, u32) {
match theme {
WallpaperTheme::Dawn => (
hsla(351.0 / 360.0, 1.0, 0.91, 0.95),
hsla(228.0 / 360.0, 1.0, 0.86, 0.85),
0xefe8e1,
),
WallpaperTheme::Violet => (
hsla(263.0 / 360.0, 1.0, 0.88, 0.95),
hsla(33.0 / 360.0, 1.0, 0.87, 0.85),
0xe9e2ee,
),
WallpaperTheme::Mint => (
hsla(146.0 / 360.0, 0.69, 0.85, 0.95),
hsla(40.0 / 360.0, 1.0, 0.86, 0.85),
0xe6ece2,
),
WallpaperTheme::Slate => (
hsla(218.0 / 360.0, 0.20, 0.85, 0.95),
hsla(20.0 / 360.0, 0.0, 0.10, 0.40),
0xd6dae3,
),
WallpaperTheme::Dawn => {
(hsla(351.0 / 360.0, 1.0, 0.91, 0.95), hsla(228.0 / 360.0, 1.0, 0.86, 0.85), 0xefe8e1)
}
WallpaperTheme::Violet => {
(hsla(263.0 / 360.0, 1.0, 0.88, 0.95), hsla(33.0 / 360.0, 1.0, 0.87, 0.85), 0xe9e2ee)
}
WallpaperTheme::Mint => {
(hsla(146.0 / 360.0, 0.69, 0.85, 0.95), hsla(40.0 / 360.0, 1.0, 0.86, 0.85), 0xe6ece2)
}
WallpaperTheme::Slate => {
(hsla(218.0 / 360.0, 0.20, 0.85, 0.95), hsla(20.0 / 360.0, 0.0, 0.10, 0.40), 0xd6dae3)
}
}
}
@@ -1,8 +1,6 @@
use ely_browser_core::BrowserSnapshot;
use ely_design_system::colors;
use ely_domain::{
COLLAPSED_SIDEBAR_WIDTH_PX, DEFAULT_SIDEBAR_WIDTH_PX, HIDDEN_SIDEBAR_WIDTH_PX,
};
use ely_domain::{COLLAPSED_SIDEBAR_WIDTH_PX, DEFAULT_SIDEBAR_WIDTH_PX, HIDDEN_SIDEBAR_WIDTH_PX};
use gpui::{
AnyElement, Context, FontWeight, InteractiveElement, IntoElement, ParentElement, SharedString,
StatefulInteractiveElement, Styled, div, prelude::FluentBuilder, px, rgb, rgba,
@@ -28,12 +26,7 @@ pub(crate) fn render_sidebar_layout_section(
.flex_col()
.gap(px(14.0))
.pt(px(8.0))
.child(
div()
.text_size(px(11.0))
.text_color(rgb(colors::INK_4))
.child("SIDEBAR"),
)
.child(div().text_size(px(11.0)).text_color(rgb(colors::INK_4)).child("SIDEBAR"))
.child(
div()
.font_family(SERIF_FAMILY)
@@ -151,12 +144,7 @@ fn render_layout_card(
.text_color(rgb(colors::INK))
.child(title),
)
.child(
div()
.text_size(px(11.0))
.text_color(rgb(colors::INK_4))
.child(detail),
),
.child(div().text_size(px(11.0)).text_color(rgb(colors::INK_4)).child(detail)),
)
.into_any_element()
}
@@ -126,9 +126,7 @@ pub(crate) fn brand_accent_color(brand: Brand) -> u32 {
/// unknown sites still render the design's colored dot instead of looking
/// stranded.
pub(crate) fn accent_color_for_host(host: Option<&str>) -> u32 {
host.and_then(Brand::from_host)
.map(brand_accent_color)
.unwrap_or(colors::ACCENT)
host.and_then(Brand::from_host).map(brand_accent_color).unwrap_or(colors::ACCENT)
}
fn render_notion(size: f32) -> AnyElement {
@@ -322,4 +320,3 @@ mod tests {
assert_eq!(Brand::from_host(""), None);
}
}
@@ -1,7 +1,5 @@
use ely_design_system::colors;
use gpui::{
AnyElement, IntoElement, ParentElement, Styled, div, px, rgb, rgba,
};
use gpui::{AnyElement, IntoElement, ParentElement, Styled, div, px, rgb, rgba};
use gpui_component::IconName;
pub(crate) fn render_command_footer() -> AnyElement {
@@ -28,24 +26,14 @@ pub(crate) fn render_command_footer() -> AnyElement {
.flex()
.items_center()
.gap(px(6.0))
.child(
div()
.text_color(rgb(colors::ACCENT))
.child(IconName::Asterisk),
)
.child(div().text_color(rgb(colors::ACCENT)).child(IconName::Asterisk))
.child("Powered by ELY"),
)
.into_any_element()
}
fn footer_chunk(keys: &'static str, label: &'static str) -> AnyElement {
div()
.flex()
.items_center()
.gap(px(4.0))
.child(render_kbd(keys))
.child(label)
.into_any_element()
div().flex().items_center().gap(px(4.0)).child(render_kbd(keys)).child(label).into_any_element()
}
pub(crate) fn render_kbd(label: &'static str) -> AnyElement {
@@ -82,9 +82,7 @@ pub(crate) fn visible_command_rows(
.map(|bookmark| CommandSelection::OpenUrl(bookmark.url().clone())),
);
rows.extend(
matching_actions(needle)
.iter()
.map(|action| CommandSelection::OpenRoute(action.route)),
matching_actions(needle).iter().map(|action| CommandSelection::OpenRoute(action.route)),
);
rows
}
@@ -97,12 +95,7 @@ pub(crate) fn matching_tabs<'a>(
return snapshot.tabs.iter().take(RESULT_LIMIT).collect();
}
snapshot
.tabs
.iter()
.filter(|tab| matches_tab(tab, needle))
.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 {
@@ -61,11 +61,8 @@ fn render_panel(
selected_index: usize,
cx: &mut Context<ElyShell>,
) -> AnyElement {
let query_label = if needle.is_empty() {
"Type to search…".to_string()
} else {
needle.to_string()
};
let query_label =
if needle.is_empty() { "Type to search…".to_string() } else { needle.to_string() };
div()
.w(px(640.0))
@@ -94,11 +91,7 @@ fn render_header(query_label: String, is_empty: bool) -> AnyElement {
.py(px(16.0))
.border_b_1()
.border_color(rgba(colors::DIVIDER))
.child(
div()
.text_color(rgb(colors::INK_3))
.child(IconName::Search),
)
.child(div().text_color(rgb(colors::INK_3)).child(IconName::Search))
.child(
div()
.flex_1()
@@ -110,10 +103,7 @@ fn render_header(query_label: String, is_empty: bool) -> AnyElement {
.child(query_label)
.child(blink(
"command-overlay-caret",
div()
.w(px(1.0))
.h(px(18.0))
.bg(rgb(colors::ACCENT)),
div().w(px(1.0)).h(px(18.0)).bg(rgb(colors::ACCENT)),
)),
)
.child(
@@ -145,10 +135,8 @@ fn render_results(
let mut sections: Vec<AnyElement> = Vec::new();
if !tabs.is_empty() {
let count = tabs.len();
sections.push(render_section(
"Open tabs",
render_tab_rows(tabs, offset, selected_index, cx),
));
sections
.push(render_section("Open tabs", render_tab_rows(tabs, offset, selected_index, cx)));
offset += count;
}
if !history.is_empty() {
@@ -178,13 +166,7 @@ fn render_results(
sections.push(render_empty_state());
}
div()
.max_h(px(440.0))
.py(px(8.0))
.flex()
.flex_col()
.children(sections)
.into_any_element()
div().max_h(px(440.0)).py(px(8.0)).flex().flex_col().children(sections).into_any_element()
}
fn render_section(label: &'static str, body: AnyElement) -> AnyElement {
@@ -68,9 +68,7 @@ pub(crate) fn render_history_rows(
let url = entry.url().clone();
let title = entry.title().to_string();
let host = entry.url().host().map(|host| host.to_string());
let display = host
.clone()
.unwrap_or_else(|| entry.url().as_str().to_string());
let display = host.clone().unwrap_or_else(|| entry.url().as_str().to_string());
let initial = title.chars().next().unwrap_or('?').to_string();
let is_selected = offset + index == selected_index;
@@ -107,9 +105,7 @@ pub(crate) fn render_bookmark_rows(
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 display = host.clone().unwrap_or_else(|| bookmark.url().as_str().to_string());
let initial = title.chars().next().unwrap_or('?').to_string();
let is_selected = offset + index == selected_index;
@@ -144,11 +140,7 @@ pub(crate) fn render_action_rows(
.flex_col()
.children(actions.into_iter().enumerate().map(|(index, action)| {
let route = action.route;
let keys = if action.keys.is_empty() {
None
} else {
Some(action.keys.to_string())
};
let keys = if action.keys.is_empty() { None } else { Some(action.keys.to_string()) };
let icon = action.icon.clone();
let is_selected = offset + index == selected_index;
@@ -261,18 +253,11 @@ where
.child(title),
)
.children(hint.map(|hint| {
div()
.text_size(px(11.0))
.text_color(rgb(colors::INK_4))
.truncate()
.child(hint)
div().text_size(px(11.0)).text_color(rgb(colors::INK_4)).truncate().child(hint)
})),
)
.children(keys.map(|key_label| {
div()
.text_size(px(10.5))
.text_color(rgb(colors::INK_3))
.child(key_label)
div().text_size(px(10.5)).text_color(rgb(colors::INK_3)).child(key_label)
}))
.into_any_element()
}
@@ -43,11 +43,7 @@ pub(crate) fn render_favorites_grid(
.into_any_element()
}
fn render_favorite_tile(
index: usize,
tab: &BrowserTab,
cx: &mut Context<ElyShell>,
) -> AnyElement {
fn render_favorite_tile(index: usize, tab: &BrowserTab, cx: &mut Context<ElyShell>) -> AnyElement {
let tab_id = tab.id().clone();
let host = tab.url().host().map(|host| host.to_string());
let title = tab.title().to_string();
+5 -18
View File
@@ -9,9 +9,7 @@ use crate::shell::ElyShell;
use crate::shell::chrome::{SERIF_FAMILY, render_glyph_for};
use super::style::{
ARROW_CHIP_BG, PILL_BG, PILL_BG_HOVER, SEARCH_BG, card_shadow, soft_shadow,
};
use super::style::{ARROW_CHIP_BG, PILL_BG, PILL_BG_HOVER, SEARCH_BG, card_shadow, soft_shadow};
use super::time::DayPhase;
pub(crate) fn render_hero(
@@ -41,11 +39,7 @@ fn render_greeting_row(text: String, phase: DayPhase) -> AnyElement {
.gap(px(8.0))
.text_size(px(13.0))
.text_color(rgb(colors::INK_3))
.child(
div()
.text_color(rgb(color))
.child(icon),
)
.child(div().text_color(rgb(color)).child(icon))
.child(text)
.into_any_element()
}
@@ -102,11 +96,7 @@ fn render_search_bar(shell: &ElyShell, cx: &mut Context<ElyShell>) -> AnyElement
.on_click(cx.listener(|shell, _, window, cx| {
shell.focus_address_bar(window, cx);
}))
.child(
div()
.text_color(rgb(colors::INK_3))
.child(IconName::Search),
)
.child(div().text_color(rgb(colors::INK_3)).child(IconName::Search))
.child(
div()
.flex_1()
@@ -170,11 +160,8 @@ fn render_pill_icon<F>(
where
F: Fn(&mut ElyShell, &mut gpui::Window, &mut Context<ElyShell>) + 'static,
{
let leading = div()
.text_color(rgb(colors::INK_3))
.text_size(px(12.0))
.child(icon)
.into_any_element();
let leading =
div().text_color(rgb(colors::INK_3)).text_size(px(12.0)).child(icon).into_any_element();
render_pill(id, leading, label, cx, handler)
}
+26 -63
View File
@@ -16,10 +16,7 @@ use crate::shell::chrome::{SERIF_FAMILY, render_glyph_for};
use super::style::{CARD_BG, card_shadow};
use super::time::relative_time_label;
pub(crate) fn render_recap(
snapshot: &BrowserSnapshot,
cx: &mut Context<ElyShell>,
) -> AnyElement {
pub(crate) fn render_recap(snapshot: &BrowserSnapshot, cx: &mut Context<ElyShell>) -> AnyElement {
if snapshot.history_entries.is_empty() && snapshot.reading_list.is_empty() {
return div().into_any_element();
}
@@ -30,16 +27,8 @@ pub(crate) fn render_recap(
.grid()
.grid_cols(8)
.gap(px(12.0))
.child(
div()
.col_span(5)
.child(render_continue_card(snapshot, now, cx)),
)
.child(
div()
.col_span(3)
.child(render_activity_card(snapshot, now, cx)),
)
.child(div().col_span(5).child(render_continue_card(snapshot, now, cx)))
.child(div().col_span(3).child(render_activity_card(snapshot, now, cx)))
.into_any_element()
}
@@ -48,7 +37,8 @@ fn render_continue_card(
now: SystemTime,
cx: &mut Context<ElyShell>,
) -> AnyElement {
let recent_history: Vec<&HistoryEntry> = snapshot.history_entries.iter().rev().take(3).collect();
let recent_history: Vec<&HistoryEntry> =
snapshot.history_entries.iter().rev().take(3).collect();
let featured = snapshot.reading_list.first();
let reading_total = snapshot.reading_list.len();
@@ -59,18 +49,12 @@ fn render_continue_card(
.p(px(16.0))
.flex()
.gap(px(16.0))
.child(
div()
.flex_1()
.min_w_0()
.child(render_continue_history(recent_history, now, cx)),
)
.child(
div()
.w(px(240.0))
.flex_shrink_0()
.child(render_reading_list_cover(featured, reading_total, cx)),
)
.child(div().flex_1().min_w_0().child(render_continue_history(recent_history, now, cx)))
.child(div().w(px(240.0)).flex_shrink_0().child(render_reading_list_cover(
featured,
reading_total,
cx,
)))
.into_any_element()
}
@@ -175,9 +159,8 @@ fn render_reading_list_cover(
let title = featured
.map(|entry| entry.title().to_string())
.unwrap_or_else(|| "Add an article to your reading list".to_string());
let subtitle = featured
.map(|entry| entry.display_url())
.unwrap_or_else(|| "Reading List".to_string());
let subtitle =
featured.map(|entry| entry.display_url()).unwrap_or_else(|| "Reading List".to_string());
let url = featured.map(|entry| entry.source_url().clone());
let mut cover = div()
@@ -194,26 +177,16 @@ fn render_reading_list_cover(
.cursor_pointer()
.hover(|style| style.opacity(0.96))
.active(|style| style.opacity(0.88))
.child(
div()
.absolute()
.inset_0()
.bg(linear_gradient(
.child(div().absolute().inset_0().bg(linear_gradient(
225.0,
linear_color_stop(hsla(345.0 / 360.0, 1.0, 0.85, 0.55), 0.0),
linear_color_stop(hsla(345.0 / 360.0, 1.0, 0.85, 0.0), 0.6),
)),
)
.child(
div()
.absolute()
.inset_0()
.bg(linear_gradient(
)))
.child(div().absolute().inset_0().bg(linear_gradient(
45.0,
linear_color_stop(hsla(228.0 / 360.0, 0.52, 0.62, 0.55), 0.0),
linear_color_stop(hsla(228.0 / 360.0, 0.52, 0.62, 0.0), 0.7),
)),
);
)));
if let Some(target) = url {
cover = cover.on_click(cx.listener(move |shell, _, window, cx| {
@@ -257,12 +230,7 @@ fn render_reading_list_cover(
.text_color(rgb(0xffffff))
.child(title),
)
.child(
div()
.text_size(px(11.0))
.text_color(rgb(0xe6e3de))
.child(subtitle),
),
.child(div().text_size(px(11.0)).text_color(rgb(0xe6e3de)).child(subtitle)),
)
.into_any_element()
}
@@ -296,9 +264,12 @@ fn render_activity_card(
.flex()
.flex_col()
.gap(px(12.0))
.children(entries.into_iter().enumerate().map(|(index, entry)| {
render_activity_row(index, entry, now, cx)
}))
.children(
entries
.into_iter()
.enumerate()
.map(|(index, entry)| render_activity_row(index, entry, now, cx)),
)
.into_any_element()
})
.child(render_view_all_link(cx))
@@ -345,10 +316,7 @@ fn render_activity_row(
.flex_col()
.gap_1()
.child(
div()
.text_size(px(11.5))
.text_color(rgb(colors::INK_3))
.child("You visited"),
div().text_size(px(11.5)).text_color(rgb(colors::INK_3)).child("You visited"),
)
.child(
div()
@@ -366,12 +334,7 @@ fn render_activity_row(
.child(display_url),
),
)
.child(
div()
.text_size(px(10.5))
.text_color(rgb(colors::INK_4))
.child(when),
)
.child(div().text_size(px(10.5)).text_color(rgb(colors::INK_4)).child(when))
.into_any_element()
}
@@ -11,10 +11,6 @@ pub(crate) fn render_section_chevron_label(label: &'static str) -> AnyElement {
.text_size(px(12.5))
.font_weight(FontWeight(500.0))
.child(label)
.child(
div()
.text_color(rgb(colors::INK_4))
.child(IconName::ChevronDown),
)
.child(div().text_color(rgb(colors::INK_4)).child(IconName::ChevronDown))
.into_any_element()
}
+1 -6
View File
@@ -39,13 +39,8 @@ pub(crate) fn day_phase_from_hour(hour_utc: u32) -> DayPhase {
pub(crate) fn greeting_for_now(now: SystemTime, name: &str) -> String {
let phase = day_phase_for(now).as_str();
if name.is_empty() {
format!("Good {phase}")
} else {
format!("Good {phase}, {name}")
if name.is_empty() { format!("Good {phase}") } else { format!("Good {phase}, {name}") }
}
}
pub(crate) fn relative_time_label(now: SystemTime, then: SystemTime) -> String {
let elapsed = match now.duration_since(then) {
+1 -2
View File
@@ -30,8 +30,7 @@ pub(crate) use sidebar_header::{
render_workspace_disclosure_backdrop,
};
pub(crate) use split_pane::{
pane_host_label, pane_url_is_secure, render_compact_split_canvas,
render_split_pane_header,
pane_host_label, pane_url_is_secure, render_compact_split_canvas, render_split_pane_header,
};
pub(crate) use topbar::render_topbar;
pub(crate) use typography::{SANS_FAMILY, SERIF_FAMILY, register_serif_fonts};
@@ -36,16 +36,8 @@ pub(crate) fn render_plugin_detail_view(
.grid()
.grid_cols(8)
.gap(px(24.0))
.child(
div()
.col_span(3)
.child(render_left_column(plugin, profile_kind, cx)),
)
.child(
div()
.col_span(5)
.child(render_right_column(plugin)),
),
.child(div().col_span(3).child(render_left_column(plugin, profile_kind, cx)))
.child(div().col_span(5).child(render_right_column(plugin))),
)
.into_any_element()
}
@@ -66,14 +58,7 @@ fn render_left_column(
}
fn render_cover(plugin: &InstalledPlugin) -> AnyElement {
let initial = plugin
.manifest()
.name()
.chars()
.next()
.unwrap_or('◇')
.to_string()
.to_uppercase();
let initial = plugin.manifest().name().chars().next().unwrap_or('◇').to_string().to_uppercase();
div()
.h(px(220.0))
@@ -140,20 +125,12 @@ where
.hover(|style| style.opacity(0.92))
.active(|style| style.opacity(0.78))
.on_click(cx.listener(move |shell, _, window, cx| handler(shell, window, cx)))
.child(
div()
.text_color(rgb(0xffffff))
.child(IconName::Check),
)
.child(div().text_color(rgb(0xffffff)).child(IconName::Check))
.child(label)
.into_any_element()
}
fn render_secondary_button<F>(
icon: IconName,
cx: &mut Context<ElyShell>,
handler: F,
) -> AnyElement
fn render_secondary_button<F>(icon: IconName, cx: &mut Context<ElyShell>, handler: F) -> AnyElement
where
F: Fn(&mut ElyShell, &mut gpui::Window, &mut Context<ElyShell>) + 'static,
{
@@ -180,12 +157,7 @@ fn render_permissions_block(manifest: &PluginManifest) -> AnyElement {
.flex_col()
.gap(px(8.0))
.pt(px(4.0))
.child(
div()
.text_size(px(11.0))
.text_color(rgb(colors::INK_3))
.child("PERMISSIONS"),
)
.child(div().text_size(px(11.0)).text_color(rgb(colors::INK_3)).child("PERMISSIONS"))
.child(if manifest.permissions().is_empty() {
div()
.text_size(px(12.0))
@@ -226,10 +198,7 @@ fn render_permission_row(permission: &PluginPermission) -> AnyElement {
.child(if high_risk { "!" } else { "" }),
)
.child(
div()
.flex_1()
.text_color(rgb(colors::INK_2))
.child(permission_scope_label(permission)),
div().flex_1().text_color(rgb(colors::INK_2)).child(permission_scope_label(permission)),
)
.into_any_element()
}
@@ -281,16 +250,11 @@ fn render_right_header(plugin: &InstalledPlugin) -> AnyElement {
.text_color(rgb(colors::INK))
.child(manifest.name().to_string()),
)
.child(
div()
.text_size(px(12.5))
.text_color(rgb(colors::INK_3))
.child(format!(
.child(div().text_size(px(12.5)).text_color(rgb(colors::INK_3)).child(format!(
"by {} · min ELY {}",
manifest.author(),
manifest.min_ely_build()
)),
),
))),
)
.child(render_status_chip(plugin))
.into_any_element()
@@ -341,12 +305,7 @@ fn stat_card(label: &'static str, value: String) -> AnyElement {
.flex()
.flex_col()
.gap(px(2.0))
.child(
div()
.text_size(px(10.5))
.text_color(rgb(colors::INK_4))
.child(label),
)
.child(div().text_size(px(10.5)).text_color(rgb(colors::INK_4)).child(label))
.child(
div()
.text_size(px(13.0))
@@ -436,13 +395,8 @@ fn render_contribution_row(contribution: &PluginContributionPoint) -> AnyElement
fn category_label(plugin: &InstalledPlugin) -> &'static str {
let high_risk = plugin.manifest().high_risk_permissions().next().is_some();
if high_risk {
"ELY · AUDIT NEEDED"
} else {
"ELY · SANDBOXED"
if high_risk { "ELY · AUDIT NEEDED" } else { "ELY · SANDBOXED" }
}
}
const CARD_BG: u32 = 0xffffffd9;
const SECONDARY_BG: u32 = 0xffffffd9;
@@ -38,11 +38,7 @@ const NAV_GROUPS: &[NavGroup] = &[
label: "Spaces",
route: "ely://settings/spaces",
},
NavItem {
icon: IconName::Search,
label: "Search",
route: "ely://settings/search",
},
NavItem { icon: IconName::Search, label: "Search", route: "ely://settings/search" },
NavItem {
icon: IconName::SquareTerminal,
label: "Shortcuts",
@@ -53,11 +49,7 @@ const NAV_GROUPS: &[NavGroup] = &[
NavGroup {
label: "ACCOUNT",
items: &[
NavItem {
icon: IconName::ChartPie,
label: "Sync",
route: "ely://settings/sync",
},
NavItem { icon: IconName::ChartPie, label: "Sync", route: "ely://settings/sync" },
NavItem {
icon: IconName::Eye,
label: "Privacy & Security",
@@ -83,11 +75,7 @@ const NAV_GROUPS: &[NavGroup] = &[
NavGroup {
label: "POWER",
items: &[
NavItem {
icon: IconName::Asterisk,
label: "Plugins",
route: "ely://settings/plugins",
},
NavItem { icon: IconName::Asterisk, label: "Plugins", route: "ely://settings/plugins" },
NavItem {
icon: IconName::LoaderCircle,
label: "Updates",
@@ -102,11 +90,7 @@ const NAV_GROUPS: &[NavGroup] = &[
},
NavGroup {
label: "ABOUT",
items: &[NavItem {
icon: IconName::Info,
label: "About",
route: "ely://about",
}],
items: &[NavItem { icon: IconName::Info, label: "About", route: "ely://about" }],
},
];
@@ -149,9 +133,12 @@ fn render_nav_column(
.gap(px(2.0))
.overflow_y_scrollbar()
.child(render_nav_brand(snapshot))
.children(NAV_GROUPS.iter().enumerate().map(|(group_index, group)| {
render_nav_group(group_index, group, active_route, cx)
}))
.children(
NAV_GROUPS
.iter()
.enumerate()
.map(|(group_index, group)| render_nav_group(group_index, group, active_route, cx)),
)
.into_any_element()
}
@@ -173,10 +160,7 @@ fn render_nav_brand(snapshot: &BrowserSnapshot) -> AnyElement {
div()
.text_size(px(11.5))
.text_color(rgb(colors::INK_4))
.child(format!(
"ELY 0.42 · Profile: {}",
snapshot.active_profile_name
)),
.child(format!("ELY 0.42 · Profile: {}", snapshot.active_profile_name)),
)
.into_any_element()
}
@@ -224,9 +208,7 @@ fn render_nav_item(
let icon = item.icon.clone();
div()
.id(SharedString::from(format!(
"settings-nav-{group_index}-{item_index}"
)))
.id(SharedString::from(format!("settings-nav-{group_index}-{item_index}")))
.flex()
.items_center()
.gap(px(10.0))
@@ -242,11 +224,7 @@ fn render_nav_item(
.on_click(cx.listener(move |shell, _, window, cx| {
shell.open_internal_tab(route, window, cx);
}))
.child(
div()
.text_color(rgb(colors::INK_3))
.child(icon),
)
.child(div().text_color(rgb(colors::INK_3)).child(icon))
.child(div().flex_1().truncate().child(item.label))
.into_any_element()
}
+10 -33
View File
@@ -2,9 +2,9 @@ use ely_browser_core::BrowserSnapshot;
use ely_design_system::{colors, spacing};
use ely_domain::BrowserTab;
use gpui::{
AnyElement, Context, FontWeight, InteractiveElement, IntoElement, ParentElement,
SharedString, StatefulInteractiveElement, Styled, div, hsla, linear_color_stop,
linear_gradient, prelude::FluentBuilder, px, rgb, rgba,
AnyElement, Context, FontWeight, InteractiveElement, IntoElement, ParentElement, SharedString,
StatefulInteractiveElement, Styled, div, hsla, linear_color_stop, linear_gradient,
prelude::FluentBuilder, px, rgb, rgba,
};
use gpui_component::{IconName, StyledExt, scroll::ScrollableElement};
@@ -121,11 +121,7 @@ impl ElyShell {
.on_click(cx.listener(|shell, _, window, cx| {
shell.open_internal_tab("ely://settings", window, cx);
}))
.child(
div()
.text_color(rgb(colors::INK_3))
.child(IconName::Settings),
)
.child(div().text_color(rgb(colors::INK_3)).child(IconName::Settings))
.child("Settings")
.into_any_element()
}
@@ -186,9 +182,7 @@ impl ElyShell {
// it's not a popover. Use a right-chevron so the icon
// promises "this opens a page" instead of the down
// chevron that promises "this opens a menu inline".
div()
.text_color(rgb(colors::INK_4))
.child(IconName::ChevronRight),
div().text_color(rgb(colors::INK_4)).child(IconName::ChevronRight),
)
.into_any_element()
}
@@ -198,13 +192,8 @@ impl ElyShell {
snapshot: &BrowserSnapshot,
cx: &mut Context<Self>,
) -> AnyElement {
let active_tab = snapshot
.tabs
.iter()
.find(|tab| tab.id() == &snapshot.active_tab_id);
let active = active_tab
.map(|tab| tab.url().as_str() == "ely://new-tab")
.unwrap_or(false);
let active_tab = snapshot.tabs.iter().find(|tab| tab.id() == &snapshot.active_tab_id);
let active = active_tab.map(|tab| tab.url().as_str() == "ely://new-tab").unwrap_or(false);
let palette = nav_row_palette(active);
div()
@@ -309,11 +298,7 @@ impl ElyShell {
.on_click(cx.listener(|shell, _, window, cx| {
shell.open_new_tab(window, cx);
}))
.child(
div()
.text_color(rgb(colors::INK_4))
.child(IconName::Plus),
)
.child(div().text_color(rgb(colors::INK_4)).child(IconName::Plus))
.child("New Tab")
.into_any_element()
}
@@ -389,17 +374,9 @@ impl ElyShell {
/// place rather than three transparent-sentinel triples.
fn nav_row_palette(active: bool) -> NavRowPalette {
if active {
NavRowPalette {
bg: ACTIVE_NAV_BG,
hover_bg: ACTIVE_NAV_BG_HOVER,
text: colors::INK,
}
NavRowPalette { bg: ACTIVE_NAV_BG, hover_bg: ACTIVE_NAV_BG_HOVER, text: colors::INK }
} else {
NavRowPalette {
bg: 0x00000000,
hover_bg: HOVER_NAV_BG,
text: colors::INK_2,
}
NavRowPalette { bg: 0x00000000, hover_bg: HOVER_NAV_BG, text: colors::INK_2 }
}
}
@@ -1,8 +1,8 @@
use ely_browser_core::BrowserSnapshot;
use ely_design_system::colors;
use gpui::{
AnyElement, BoxShadow, Context, FontWeight, InteractiveElement, IntoElement,
MouseButton, ParentElement, SharedString, Styled, div, hsla, point, px, rgb, rgba,
AnyElement, BoxShadow, Context, FontWeight, InteractiveElement, IntoElement, MouseButton,
ParentElement, SharedString, Styled, div, hsla, point, px, rgb, rgba,
};
use gpui_component::IconName;
@@ -52,19 +52,11 @@ pub(crate) const RESIZE_HANDLE_HOVER_BG: u32 = 0xffaa7733;
pub(crate) const ROW_CLOSE_SIZE: f32 = 18.0;
pub(crate) fn profile_initial(name: &str) -> String {
name.chars()
.next()
.unwrap_or('P')
.to_uppercase()
.to_string()
name.chars().next().unwrap_or('P').to_uppercase().to_string()
}
pub(crate) fn render_unread_badge(count: u32) -> impl IntoElement {
let label = if count > 99 {
"99+".to_string()
} else {
count.to_string()
};
let label = if count > 99 { "99+".to_string() } else { count.to_string() };
div()
.px(px(6.0))
@@ -85,11 +77,7 @@ pub(crate) fn section_tabs_label(count: usize) -> impl IntoElement {
.flex()
.items_center()
.gap(px(6.0))
.child(
div()
.text_color(rgb(colors::INK_4))
.child(IconName::Frame),
)
.child(div().text_color(rgb(colors::INK_4)).child(IconName::Frame))
.child(
div()
.text_size(px(10.5))
@@ -3,8 +3,8 @@ use ely_design_system::{colors, spacing};
use ely_domain::Space;
use gpui::{
AnyElement, BoxShadow, Context, InteractiveElement, IntoElement, ParentElement, SharedString,
StatefulInteractiveElement, Styled, div, hsla, linear_color_stop, linear_gradient,
prelude::FluentBuilder, point, px, rgb, rgba,
StatefulInteractiveElement, Styled, div, hsla, linear_color_stop, linear_gradient, point,
prelude::FluentBuilder, px, rgb, rgba,
};
use gpui_component::IconName;
@@ -42,10 +42,7 @@ pub(crate) fn render_sidebar_header(
snapshot: &BrowserSnapshot,
cx: &mut Context<ElyShell>,
) -> AnyElement {
let active_space = snapshot
.spaces
.iter()
.find(|space| space.id() == &snapshot.active_space_id);
let active_space = snapshot.spaces.iter().find(|space| space.id() == &snapshot.active_space_id);
let picker_open = shell.workspace_picker_open;
div()
@@ -67,10 +64,7 @@ fn render_title_row() -> AnyElement {
.flex()
.items_center()
.gap(px(4.0))
// macOS draws the traffic lights at window (12, 14) — roughly the
// first 70 px of any sidebar that touches the window's left edge.
// Pad the title past that span so "ELY Browser ⌄" sits inline with
// the dots instead of stranded on a row of its own.
// Reserve the macOS traffic-light group plus a calm title gap.
.pl(px(TRAFFIC_LIGHT_RESERVE))
.child(
div()
@@ -79,20 +73,13 @@ fn render_title_row() -> AnyElement {
.text_color(rgb(colors::INK_2))
.child("ELY Browser"),
)
.child(
div()
.text_color(rgb(colors::INK_3))
.opacity(0.6)
.child(IconName::ChevronDown),
)
.child(div().text_color(rgb(colors::INK_3)).opacity(0.6).child(IconName::ChevronDown))
.into_any_element()
}
/// Width reserved at the start of the sidebar's top row for the macOS
/// traffic lights. Three 12 px dots with 8 px gaps, plus 12 px from the
/// window left edge minus our 16 px shell inset, lands at ~62; we add
/// breathing room and call it 68.
const TRAFFIC_LIGHT_RESERVE: f32 = 68.0;
/// traffic lights plus visual breathing room.
const TRAFFIC_LIGHT_RESERVE: f32 = 90.0;
fn render_workspace_picker(
_snapshot: &BrowserSnapshot,
@@ -146,17 +133,9 @@ fn render_picker_pill(
picker_open: bool,
cx: &mut Context<ElyShell>,
) -> AnyElement {
let space_name = active_space
.map(|space| space.name().to_string())
.unwrap_or_default();
let space_glyph = active_space
.map(|space| space.icon().to_string())
.unwrap_or_default();
let chevron = if picker_open {
IconName::ChevronUp
} else {
IconName::ChevronDown
};
let space_name = active_space.map(|space| space.name().to_string()).unwrap_or_default();
let space_glyph = active_space.map(|space| space.icon().to_string()).unwrap_or_default();
let chevron = if picker_open { IconName::ChevronUp } else { IconName::ChevronDown };
let bg = if picker_open { PICKER_BG_HOVER } else { PICKER_BG };
div()
@@ -188,11 +167,7 @@ fn render_picker_pill(
.text_color(rgb(colors::INK))
.child(space_name),
)
.child(
div()
.text_color(rgb(colors::INK_3))
.child(chevron),
)
.child(div().text_color(rgb(colors::INK_3)).child(chevron))
.into_any_element()
}
@@ -215,11 +190,8 @@ impl WorkspaceDisclosureAnchor {
/// upstream, so changing one of those constants moves the popover
/// with it.
pub(crate) fn solve(sidebar_width_px: f32) -> Self {
let left_px = spacing::SHELL_INSET
+ HEADER_PX
+ PICKER_ROW_PX
+ PICKER_BUTTON_SIZE
+ PICKER_ROW_GAP;
let left_px =
spacing::SHELL_INSET + HEADER_PX + PICKER_ROW_PX + PICKER_BUTTON_SIZE + PICKER_ROW_GAP;
let top_px = spacing::SHELL_INSET
+ HEADER_PT
@@ -236,9 +208,8 @@ impl WorkspaceDisclosureAnchor {
// - 2 * (HEADER_PX + PICKER_ROW_PX) (row insets)
// - 2 * PICKER_BUTTON_SIZE (tile + add)
// - 2 * PICKER_ROW_GAP (two gaps)
let chrome = 2.0 * (HEADER_PX + PICKER_ROW_PX)
+ 2.0 * PICKER_BUTTON_SIZE
+ 2.0 * PICKER_ROW_GAP;
let chrome =
2.0 * (HEADER_PX + PICKER_ROW_PX) + 2.0 * PICKER_BUTTON_SIZE + 2.0 * PICKER_ROW_GAP;
let width_px = (sidebar_width_px - chrome).max(0.0);
Self { top_px, left_px, width_px }
@@ -275,9 +246,7 @@ pub(crate) fn render_workspace_disclosure(
.spaces
.iter()
.enumerate()
.map(|(index, space)| {
render_disclosure_row(index, space, &active_id, cx)
}),
.map(|(index, space)| render_disclosure_row(index, space, &active_id, cx)),
)
.child(render_disclosure_footer(cx));
@@ -288,9 +257,7 @@ pub(crate) fn render_workspace_disclosure(
/// and the disclosure. Press on it closes the picker AND consumes
/// the event so the dismiss-click doesn't ricochet into a button
/// underneath the cursor.
pub(crate) fn render_workspace_disclosure_backdrop(
cx: &mut Context<ElyShell>,
) -> AnyElement {
pub(crate) fn render_workspace_disclosure_backdrop(cx: &mut Context<ElyShell>) -> AnyElement {
div()
.id(SharedString::from("workspace-picker-backdrop"))
.absolute()
@@ -341,13 +308,7 @@ fn render_disclosure_row(
.text_color(rgb(colors::INK))
.child(space.name().to_string()),
)
.when(active, |el| {
el.child(
div()
.text_color(rgb(colors::ACCENT))
.child(IconName::Check),
)
})
.when(active, |el| el.child(div().text_color(rgb(colors::ACCENT)).child(IconName::Check)))
.into_any_element()
}
@@ -372,11 +333,7 @@ fn render_disclosure_footer(cx: &mut Context<ElyShell>) -> AnyElement {
shell.close_workspace_picker(cx);
shell.open_internal_tab("ely://settings/spaces", window, cx);
}))
.child(
div()
.text_color(rgb(colors::INK_4))
.child(IconName::Settings),
)
.child(div().text_color(rgb(colors::INK_4)).child(IconName::Settings))
.child("Manage spaces")
.into_any_element()
}
+4 -21
View File
@@ -34,18 +34,8 @@ pub(crate) fn render_split_pane_header(
.border_b_1()
.border_color(rgb(colors::HAIRLINE))
.bg(rgb(0xf6f4ef))
.child(
div()
.size(px(8.0))
.rounded_full()
.bg(rgb(accent)),
)
.child(
div()
.text_color(rgb(colors::INK_3))
.text_size(px(11.0))
.child(lock_or_globe),
)
.child(div().size(px(8.0)).rounded_full().bg(rgb(accent)))
.child(div().text_color(rgb(colors::INK_3)).text_size(px(11.0)).child(lock_or_globe))
.child(
div()
.text_size(px(11.0))
@@ -102,10 +92,7 @@ fn render_close_glyph(close_tab_id: TabId, cx: &mut Context<ElyShell>) -> AnyEle
}
pub(crate) fn pane_host_label(tab: &BrowserTab) -> String {
tab.url()
.host()
.map(|host| host.to_string())
.unwrap_or_else(|| tab.title().to_string())
tab.url().host().map(|host| host.to_string()).unwrap_or_else(|| tab.title().to_string())
}
pub(crate) fn pane_url_is_secure(tab: &BrowserTab) -> bool {
@@ -114,11 +101,7 @@ pub(crate) fn pane_url_is_secure(tab: &BrowserTab) -> bool {
}
pub(crate) fn split_canvas_status(tab: &BrowserTab) -> String {
if tab.url().as_str() == "ely://new-tab" {
"Ready".to_string()
} else {
tab.display_url()
}
if tab.url().as_str() == "ely://new-tab" { "Ready".to_string() } else { tab.display_url() }
}
pub(crate) fn render_compact_split_canvas(tab: &BrowserTab) -> AnyElement {
@@ -2,12 +2,9 @@ use std::borrow::Cow;
use gpui::App;
const NEWSREADER_REGULAR: &[u8] =
include_bytes!("../../../assets/fonts/Newsreader.ttf");
const NEWSREADER_ITALIC: &[u8] =
include_bytes!("../../../assets/fonts/Newsreader-Italic.ttf");
const GEIST_REGULAR: &[u8] =
include_bytes!("../../../assets/fonts/Geist-Regular.ttf");
const NEWSREADER_REGULAR: &[u8] = include_bytes!("../../../assets/fonts/Newsreader.ttf");
const NEWSREADER_ITALIC: &[u8] = include_bytes!("../../../assets/fonts/Newsreader-Italic.ttf");
const GEIST_REGULAR: &[u8] = include_bytes!("../../../assets/fonts/Geist-Regular.ttf");
/// The bundled Newsreader.ttf is the 16pt optical-size cut. GPUI's text
/// system matches by the font's TrueType name-id 1, which is
+4 -14
View File
@@ -10,26 +10,16 @@ pub(crate) fn render_wallpaper(theme: WallpaperTheme) -> impl IntoElement {
.absolute()
.inset_0()
.bg(rgb(palette.base))
.child(
div()
.absolute()
.inset_0()
.bg(linear_gradient(
.child(div().absolute().inset_0().bg(linear_gradient(
225.0,
linear_color_stop(palette.upper, 0.0),
linear_color_stop(transparent_like(palette.upper), 0.55),
)),
)
.child(
div()
.absolute()
.inset_0()
.bg(linear_gradient(
)))
.child(div().absolute().inset_0().bg(linear_gradient(
45.0,
linear_color_stop(palette.lower, 0.0),
linear_color_stop(transparent_like(palette.lower), 0.62),
)),
)
)))
}
struct WallpaperPalette {
+1 -6
View File
@@ -297,12 +297,7 @@ fn render_canvas_surface(content: impl IntoElement) -> AnyElement {
.flex_1()
.h_full()
.overflow_hidden()
.child(
div()
.size_full()
.overflow_y_scrollbar()
.child(content),
)
.child(div().size_full().overflow_y_scrollbar().child(content))
.into_any_element()
}
@@ -36,11 +36,7 @@ impl ElyShell {
)
}
fn render_hero(
&mut self,
snapshot: &BrowserSnapshot,
cx: &mut Context<Self>,
) -> AnyElement {
fn render_hero(&mut self, snapshot: &BrowserSnapshot, cx: &mut Context<Self>) -> AnyElement {
div()
.grid()
.grid_cols(2)
@@ -73,16 +69,10 @@ impl ElyShell {
.text_color(rgb(colors::INK))
.child("Quiet tools. Everyday magic."),
)
.child(
div()
.max_w(px(520.0))
.text_size(px(13.5))
.text_color(rgb(colors::INK_2))
.child(
.child(div().max_w(px(520.0)).text_size(px(13.5)).text_color(rgb(colors::INK_2)).child(
"ELY plugins are sandboxed, theme-aware, and ship with their own \
controls in your sidebar — no Chrome extension framework required.",
),
)
))
.child(self.render_search_row(cx))
.into_any_element()
}
@@ -103,18 +93,10 @@ impl ElyShell {
.flex()
.items_center()
.gap(px(10.0))
.child(
div()
.text_color(rgb(colors::INK_3))
.child(IconName::Search),
)
.child(
div().flex_1().child(
Input::new(&self.plugin_search_input)
.appearance(false)
.cleanable(true),
),
),
.child(div().text_color(rgb(colors::INK_3)).child(IconName::Search))
.child(div().flex_1().child(
Input::new(&self.plugin_search_input).appearance(false).cleanable(true),
)),
)
.child(
div()
@@ -135,18 +117,13 @@ impl ElyShell {
.on_click(cx.listener(|shell, _, window, cx| {
shell.choose_plugin_package(window, cx);
}))
.child(
div()
.text_color(rgb(0xffffff))
.child(IconName::Plus),
)
.child(div().text_color(rgb(0xffffff)).child(IconName::Plus))
.child("Install"),
)
.into_any_element()
}
}
fn render_summary(snapshot: &BrowserSnapshot) -> AnyElement {
div()
.flex()
@@ -154,21 +131,12 @@ fn render_summary(snapshot: &BrowserSnapshot) -> AnyElement {
.gap(px(6.0))
.child(category_chip("All", true))
.child(category_chip("Installed", false))
.child(category_chip(
sandbox_chip_label(snapshot),
false,
))
.child(
div()
.ml_auto()
.text_size(px(11.5))
.text_color(rgb(colors::INK_3))
.child(format!(
.child(category_chip(sandbox_chip_label(snapshot), false))
.child(div().ml_auto().text_size(px(11.5)).text_color(rgb(colors::INK_3)).child(format!(
"{} signed · {} high-risk",
snapshot.installed_plugins.len(),
high_risk_plugin_count(snapshot)
)),
)
)))
.into_any_element()
}
@@ -188,20 +156,13 @@ fn category_chip(label: &'static str, active: bool) -> AnyElement {
.into_any_element()
}
fn render_grid(
snapshot: &BrowserSnapshot,
needle: &str,
cx: &mut Context<ElyShell>,
) -> AnyElement {
fn render_grid(snapshot: &BrowserSnapshot, needle: &str, cx: &mut Context<ElyShell>) -> AnyElement {
if snapshot.installed_plugins.is_empty() {
return render_empty_state(cx);
}
let matches: Vec<&InstalledPlugin> = snapshot
.installed_plugins
.iter()
.filter(|plugin| matches_plugin(plugin, needle))
.collect();
let matches: Vec<&InstalledPlugin> =
snapshot.installed_plugins.iter().filter(|plugin| matches_plugin(plugin, needle)).collect();
if matches.is_empty() {
return render_no_match_state(needle);
@@ -214,14 +175,9 @@ fn render_grid(
.grid()
.grid_cols(4)
.gap(px(14.0))
.children(
matches
.into_iter()
.enumerate()
.map(|(index, plugin)| {
.children(matches.into_iter().enumerate().map(|(index, plugin)| {
render_plugin_card(index, plugin, &snapshot.active_profile_kind, cx)
}),
)
}))
.into_any_element()
}
@@ -271,22 +227,13 @@ fn render_empty_state(cx: &mut Context<ElyShell>) -> AnyElement {
.text_color(rgb(colors::INK))
.child("No plugins yet."),
)
.child(
div()
.max_w(px(420.0))
.text_size(px(13.0))
.text_color(rgb(colors::INK_3))
.child(
.child(div().max_w(px(420.0)).text_size(px(13.0)).text_color(rgb(colors::INK_3)).child(
"Drop a signed .rplug package on ELY to extend the browser with sandboxed \
tools. Plugins ship with their own sidebar controls.",
),
)
.child(action_button(
"empty-install",
"Install plugin",
cx,
|shell, window, cx| shell.choose_plugin_package(window, cx),
))
.child(action_button("empty-install", "Install plugin", cx, |shell, window, cx| {
shell.choose_plugin_package(window, cx)
}))
.into_any_element()
}
@@ -393,10 +340,7 @@ fn render_plugin_card(
.border_color(rgba(colors::DIVIDER))
.text_size(px(10.5))
.text_color(rgb(colors::INK_4))
.child(format!(
"{} permissions",
plugin.manifest().permissions().len()
))
.child(format!("{} permissions", plugin.manifest().permissions().len()))
.child("·")
.child(format!("{high_risk} high risk"))
.child(
@@ -454,12 +398,8 @@ fn plugin_cover_gradient(name: &str) -> (gpui::Hsla, gpui::Hsla) {
(343.0, 0.78, 0.67, 251.0, 0.85, 0.71),
];
let bucket = name.bytes().fold(0u32, |acc, b| acc.wrapping_add(b as u32))
as usize
% PALETTE.len();
let bucket =
name.bytes().fold(0u32, |acc, b| acc.wrapping_add(b as u32)) as usize % PALETTE.len();
let (h1, s1, l1, h2, s2, l2) = PALETTE[bucket];
(
hsla(h1 / 360.0, s1, l1, 1.0),
hsla(h2 / 360.0, s2, l2, 1.0),
)
(hsla(h1 / 360.0, s1, l1, 1.0), hsla(h2 / 360.0, s2, l2, 1.0))
}
@@ -24,9 +24,11 @@ impl ElyShell {
match plugin {
Some(plugin) => render_canvas_surface(
div().size_full().overflow_y_scrollbar().child(
render_plugin_detail_view(plugin, &snapshot.active_profile_kind, cx),
),
div().size_full().overflow_y_scrollbar().child(render_plugin_detail_view(
plugin,
&snapshot.active_profile_kind,
cx,
)),
),
None => render_canvas_surface(render_missing_plugin_detail(plugin_id.as_ref(), cx)),
}
@@ -24,12 +24,7 @@ pub(super) fn render_editors_pick(
.flex()
.flex_col()
.gap(px(14.0))
.child(
div()
.text_size(px(11.0))
.text_color(rgb(colors::INK_3))
.child("EDITOR'S PICK"),
)
.child(div().text_size(px(11.0)).text_color(rgb(colors::INK_3)).child("EDITOR'S PICK"))
.child(render_featured_body(featured))
.child(render_featured_actions(featured, cx))
.into_any_element()
@@ -37,10 +32,9 @@ pub(super) fn render_editors_pick(
fn render_featured_body(featured: Option<&InstalledPlugin>) -> AnyElement {
let (name, desc) = match featured {
Some(plugin) => (
plugin.manifest().name().to_string(),
plugin.manifest().description().to_string(),
),
Some(plugin) => {
(plugin.manifest().name().to_string(), plugin.manifest().description().to_string())
}
None => (
"Install your first plugin".to_string(),
"Drop a signed .rplug package onto ELY to extend the browser with sandboxed tools."
@@ -81,12 +75,7 @@ fn render_featured_body(featured: Option<&InstalledPlugin>) -> AnyElement {
.text_color(rgb(colors::INK))
.child(name),
)
.child(
div()
.text_size(px(12.5))
.text_color(rgb(colors::INK_3))
.child(desc),
),
.child(div().text_size(px(12.5)).text_color(rgb(colors::INK_3)).child(desc)),
)
.into_any_element()
}
@@ -102,23 +91,15 @@ fn render_featured_actions(
.flex()
.items_center()
.gap(px(8.0))
.child(action_button(
"featured-open",
"Open detail",
cx,
move |shell, window, cx| {
.child(action_button("featured-open", "Open detail", cx, move |shell, window, cx| {
shell.open_internal_tab(&detail_route, window, cx);
},
))
}))
.child(
div()
.ml_auto()
.text_size(px(11.5))
.text_color(rgb(colors::INK_3))
.child(format!(
"{} permissions",
plugin.manifest().permissions().len()
)),
.child(format!("{} permissions", plugin.manifest().permissions().len())),
)
.into_any_element()
} else {
@@ -126,12 +107,9 @@ fn render_featured_actions(
.flex()
.items_center()
.gap(px(8.0))
.child(action_button(
"featured-install",
"Install",
cx,
|shell, window, cx| shell.choose_plugin_package(window, cx),
))
.child(action_button("featured-install", "Install", cx, |shell, window, cx| {
shell.choose_plugin_package(window, cx)
}))
.into_any_element()
}
}
+13 -64
View File
@@ -21,14 +21,7 @@ impl ElyShell {
cx: &mut Context<Self>,
) -> AnyElement {
render_canvas_surface(
div()
.size_full()
.pt(px(40.0))
.px(px(56.0))
.pb(px(32.0))
.flex()
.justify_center()
.child(
div().size_full().pt(px(40.0)).px(px(56.0)).pb(px(32.0)).flex().justify_center().child(
div()
.max_w(px(960.0))
.grid()
@@ -65,11 +58,7 @@ fn render_status_pill(snapshot: &BrowserSnapshot) -> AnyElement {
.bg(rgba(PILL_BG))
.text_size(px(11.0))
.text_color(rgb(colors::INK_3))
.child(
div()
.text_color(rgb(colors::ACCENT))
.child(IconName::Globe),
)
.child(div().text_color(rgb(colors::ACCENT)).child(IconName::Globe))
.child(format!(
"{SYNC_SERVICE_NAME} · {}",
connection_label(snapshot.sync_status.connection())
@@ -99,10 +88,7 @@ fn render_intro_paragraph() -> AnyElement {
.into_any_element()
}
fn render_metrics_card(
snapshot: &BrowserSnapshot,
cx: &mut Context<ElyShell>,
) -> AnyElement {
fn render_metrics_card(snapshot: &BrowserSnapshot, cx: &mut Context<ElyShell>) -> AnyElement {
div()
.max_w(px(380.0))
.p(px(20.0))
@@ -111,12 +97,7 @@ fn render_metrics_card(
.flex()
.flex_col()
.gap(px(16.0))
.child(
div()
.text_size(px(12.5))
.text_color(rgb(colors::INK_3))
.child("Local queue"),
)
.child(div().text_size(px(12.5)).text_color(rgb(colors::INK_3)).child("Local queue"))
.child(
div()
.grid()
@@ -142,12 +123,7 @@ fn render_metric(label: &'static str, value: usize, color: u32) -> AnyElement {
.flex()
.flex_col()
.gap_1()
.child(
div()
.text_size(px(10.5))
.text_color(rgb(colors::INK_4))
.child(label),
)
.child(div().text_size(px(10.5)).text_color(rgb(colors::INK_4)).child(label))
.child(
div()
.text_size(px(20.0))
@@ -185,10 +161,7 @@ fn render_right_column(snapshot: &BrowserSnapshot, cx: &mut Context<ElyShell>) -
.into_any_element()
}
fn render_what_syncs_card(
snapshot: &BrowserSnapshot,
cx: &mut Context<ElyShell>,
) -> AnyElement {
fn render_what_syncs_card(snapshot: &BrowserSnapshot, cx: &mut Context<ElyShell>) -> AnyElement {
div()
.p(px(18.0))
.rounded(px(16.0))
@@ -214,18 +187,11 @@ fn render_what_syncs_card(
div()
.text_size(px(11.0))
.text_color(rgb(colors::INK_3))
.child(format!(
"{} kinds tracked",
snapshot.sync_status.objects().len()
)),
.child(format!("{} kinds tracked", snapshot.sync_status.objects().len())),
),
)
.child(
div()
.flex()
.flex_col()
.gap(px(2.0))
.children(
div().flex().flex_col().gap(px(2.0)).children(
snapshot
.sync_status
.objects()
@@ -264,16 +230,11 @@ fn render_sync_object_row(
.text_color(rgb(colors::INK))
.child(sync_object_kind_label(status.kind())),
)
.child(
div()
.text_size(px(11.0))
.text_color(rgb(colors::INK_4))
.child(format!(
.child(div().text_size(px(11.0)).text_color(rgb(colors::INK_4)).child(format!(
"{} local · {}",
status.local_count(),
sync_object_state_label(status.state())
)),
),
))),
)
.child(render_policy_toggle(index, status, cx))
.into_any_element()
@@ -286,11 +247,7 @@ fn render_state_dot(state: SyncObjectState) -> AnyElement {
SyncObjectState::PrivacyControlled => colors::ACCENT,
};
div()
.size(px(8.0))
.rounded_full()
.bg(rgb(color))
.into_any_element()
div().size(px(8.0)).rounded_full().bg(rgb(color)).into_any_element()
}
fn render_policy_toggle(
@@ -299,17 +256,9 @@ fn render_policy_toggle(
cx: &mut Context<ElyShell>,
) -> AnyElement {
let enabled = status.policy() == SyncObjectPolicy::Enabled;
let next_policy = if enabled {
SyncObjectPolicy::Paused
} else {
SyncObjectPolicy::Enabled
};
let next_policy = if enabled { SyncObjectPolicy::Paused } else { SyncObjectPolicy::Enabled };
let kind = status.kind();
let track_color = if enabled {
colors::ACCENT
} else {
0x281e1426
};
let track_color = if enabled { colors::ACCENT } else { 0x281e1426 };
div()
.id(SharedString::from(format!("sync-policy-{index}")))
+18 -23
View File
@@ -3,8 +3,8 @@ use ely_design_system::{colors, spacing};
use ely_domain::{BrowserTab, DEFAULT_SIDEBAR_WIDTH_PX, HIDDEN_SIDEBAR_WIDTH_PX};
use gpui::{
AnyElement, Context, InteractiveElement, IntoElement, KeyDownEvent, MouseButton,
MouseMoveEvent, MouseUpEvent, ParentElement, Render, SharedString,
StatefulInteractiveElement, Styled, Window, div, prelude::FluentBuilder, px, rgb, rgba,
MouseMoveEvent, MouseUpEvent, ParentElement, Render, SharedString, StatefulInteractiveElement,
Styled, Window, div, prelude::FluentBuilder, px, rgb, rgba,
};
use super::chrome::command_match::visible_command_rows;
@@ -20,7 +20,9 @@ impl Render for ElyShell {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
match &self.state {
ShellState::Ready(core) => match (core.snapshot(), core.active_tab().cloned()) {
(Ok(snapshot), Ok(active_tab)) => self.render_browser(snapshot, active_tab, window, cx),
(Ok(snapshot), Ok(active_tab)) => {
self.render_browser(snapshot, active_tab, window, cx)
}
(Err(error), _) | (_, Err(error)) => render_error(error.to_string()),
},
ShellState::StartupError(message) => render_error(message.clone()),
@@ -89,23 +91,24 @@ impl ElyShell {
sidebar_hidden,
cx,
))
.child(self.render_main_pane(&snapshot, &active_tab, sidebar_collapsed, window, cx)),
.child(self.render_main_pane(
&snapshot,
&active_tab,
sidebar_collapsed,
window,
cx,
)),
)
.when(hover_expanded, |el| {
el.child(self.render_hidden_sidebar_overlay(&snapshot, cx))
})
.when(hover_expanded, |el| el.child(self.render_hidden_sidebar_overlay(&snapshot, cx)))
// Workspace popover only makes sense when the picker pill is
// visible — i.e. the sidebar is expanded. Compact/hidden
// modes don't render the trigger, so showing the disclosure
// would float a stranded card with no anchor.
.when(
self.workspace_picker_open && !sidebar_collapsed && !sidebar_hidden,
|el| {
.when(self.workspace_picker_open && !sidebar_collapsed && !sidebar_hidden, |el| {
let anchor = WorkspaceDisclosureAnchor::solve(sidebar_width);
el.child(render_workspace_disclosure_backdrop(cx))
.child(render_workspace_disclosure(&snapshot, anchor, cx))
},
)
})
.children(render_command_overlay(self, &snapshot, cx))
.into_any_element()
}
@@ -260,11 +263,7 @@ impl ElyShell {
}
}
pub(super) fn begin_sidebar_resize(
&mut self,
cursor_x: f32,
cx: &mut Context<Self>,
) {
pub(super) fn begin_sidebar_resize(&mut self, cursor_x: f32, cx: &mut Context<Self>) {
let ShellState::Ready(core) = &self.state else {
return;
};
@@ -329,8 +328,7 @@ const REVEAL_THRESHOLD_PX: f32 = 24.0;
/// Once revealed, cursor x past this px collapses the hidden sidebar back to
/// the rail. Sits past the right edge of the expanded sidebar plus a small
/// buffer so brief overshoots don't ping-pong the state.
const COLLAPSE_THRESHOLD_PX: f32 =
spacing::SHELL_INSET + DEFAULT_SIDEBAR_WIDTH_PX as f32 + 24.0;
const COLLAPSE_THRESHOLD_PX: f32 = spacing::SHELL_INSET + DEFAULT_SIDEBAR_WIDTH_PX as f32 + 24.0;
fn render_error(message: String) -> AnyElement {
div()
@@ -354,10 +352,7 @@ fn active_sidebar_width(snapshot: &BrowserSnapshot) -> Result<f32, String> {
Ok(f32::from(active_space.sidebar_width_px()))
}
pub(super) fn tab_profile_label(
tab: &BrowserTab,
profiles: &[ely_domain::Profile],
) -> String {
pub(super) fn tab_profile_label(tab: &BrowserTab, profiles: &[ely_domain::Profile]) -> String {
profiles
.iter()
.find(|profile| profile.id() == tab.profile_id())
+3 -15
View File
@@ -61,11 +61,7 @@ impl ElyShell {
}
}
pub(super) fn set_theme_mode(
&mut self,
theme_mode: ThemeMode,
cx: &mut Context<Self>,
) {
pub(super) fn set_theme_mode(&mut self, theme_mode: ThemeMode, cx: &mut Context<Self>) {
if let ShellState::Ready(core) = &mut self.state {
core.set_theme_mode(theme_mode);
cx.notify();
@@ -117,22 +113,14 @@ impl ElyShell {
});
}
pub(super) fn reset_appearance(
&mut self,
window: &mut gpui::Window,
cx: &mut Context<Self>,
) {
pub(super) fn reset_appearance(&mut self, window: &mut gpui::Window, cx: &mut Context<Self>) {
if let ShellState::Ready(core) = &mut self.state {
core.reset_appearance();
cx.notify();
}
let slider = self.translucency_slider.clone();
slider.update(cx, |state, cx| {
state.set_value(
SliderValue::Single(f32::from(DEFAULT_TRANSLUCENCY_PCT)),
window,
cx,
);
state.set_value(SliderValue::Single(f32::from(DEFAULT_TRANSLUCENCY_PCT)), window, cx);
});
}
+5 -7
View File
@@ -11,8 +11,7 @@ use gpui_component::{
};
use super::chrome::{
pane_host_label, pane_url_is_secure, render_compact_split_canvas,
render_split_pane_header,
pane_host_label, pane_url_is_secure, render_compact_split_canvas, render_split_pane_header,
};
use super::{ElyShell, ShellState};
use crate::SplitRight;
@@ -167,16 +166,16 @@ impl ElyShell {
snapshot: &BrowserSnapshot,
cx: &mut Context<Self>,
) -> gpui::Div {
body.flex().flex_col().gap(px(10.0)).children(
panes.chunks(2).enumerate().map(|(row_index, row)| {
body.flex().flex_col().gap(px(10.0)).children(panes.chunks(2).enumerate().map(
|(row_index, row)| {
div().flex().flex_1().min_h(px(180.0)).gap(px(10.0)).children(
row.iter().enumerate().map(|(column_index, tab)| {
let pane_index = row_index * 2 + column_index;
self.render_split_pane(pane_index, tab, snapshot, false, cx)
}),
)
}),
)
},
))
}
fn render_split_pane(
@@ -443,4 +442,3 @@ fn split_pane_shadow() -> Vec<BoxShadow> {
},
]
}