Apply cargo fmt across chrome and internal pages
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
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) {
|
||||
Ok(duration) => duration,
|
||||
|
||||
@@ -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,14 +395,9 @@ 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;
|
||||
const SECONDARY_BG_HOVER: u32 = 0xffffffeb;
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}")))
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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> {
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user