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