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
|
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();
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,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 {
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}")))
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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> {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user