Add settings hub page
This commit is contained in:
@@ -8,6 +8,7 @@ mod plugin_details;
|
|||||||
mod plugins;
|
mod plugins;
|
||||||
mod profiles;
|
mod profiles;
|
||||||
mod reading_list;
|
mod reading_list;
|
||||||
|
mod settings;
|
||||||
mod site_settings;
|
mod site_settings;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod task_manager;
|
mod task_manager;
|
||||||
@@ -45,6 +46,7 @@ impl ElyShell {
|
|||||||
self.render_site_settings_page(snapshot, url, cx)
|
self.render_site_settings_page(snapshot, url, cx)
|
||||||
}
|
}
|
||||||
"ely://about" => self.render_about_page(snapshot),
|
"ely://about" => self.render_about_page(snapshot),
|
||||||
|
"ely://settings" => self.render_settings_page(snapshot, cx),
|
||||||
"ely://settings/plugins" => self.render_plugins_page(snapshot, cx),
|
"ely://settings/plugins" => self.render_plugins_page(snapshot, cx),
|
||||||
"ely://settings/profiles" => self.render_profiles_page(snapshot, cx),
|
"ely://settings/profiles" => self.render_profiles_page(snapshot, cx),
|
||||||
"ely://settings/sync" => self.render_sync_page(snapshot),
|
"ely://settings/sync" => self.render_sync_page(snapshot),
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
use ely_browser_core::BrowserSnapshot;
|
||||||
|
use ely_design_system::colors;
|
||||||
|
use gpui::{AnyElement, Context, IntoElement, ParentElement, Styled, div, px, rgb};
|
||||||
|
use gpui_component::{
|
||||||
|
IconName, Sizable, StyledExt,
|
||||||
|
button::{Button, ButtonVariants},
|
||||||
|
scroll::ScrollableElement,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{ElyShell, render_canvas_surface};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct SettingsRoute {
|
||||||
|
icon: IconName,
|
||||||
|
title: &'static str,
|
||||||
|
detail: &'static str,
|
||||||
|
route: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
const SETTINGS_ROUTES: &[SettingsRoute] = &[
|
||||||
|
SettingsRoute {
|
||||||
|
icon: IconName::CircleUser,
|
||||||
|
title: "Profiles",
|
||||||
|
detail: "Profile identity, color, and download policy.",
|
||||||
|
route: "ely://settings/profiles",
|
||||||
|
},
|
||||||
|
SettingsRoute {
|
||||||
|
icon: IconName::Globe,
|
||||||
|
title: "Sync",
|
||||||
|
detail: "Local sync state and object scope.",
|
||||||
|
route: "ely://settings/sync",
|
||||||
|
},
|
||||||
|
SettingsRoute {
|
||||||
|
icon: IconName::LayoutDashboard,
|
||||||
|
title: "Plugins",
|
||||||
|
detail: "Installed plugin control and audit trail.",
|
||||||
|
route: "ely://settings/plugins",
|
||||||
|
},
|
||||||
|
SettingsRoute {
|
||||||
|
icon: IconName::Info,
|
||||||
|
title: "About",
|
||||||
|
detail: "Build, runtime, license, and product information.",
|
||||||
|
route: "ely://about",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
impl ElyShell {
|
||||||
|
pub(super) fn render_settings_page(
|
||||||
|
&mut self,
|
||||||
|
snapshot: &BrowserSnapshot,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> AnyElement {
|
||||||
|
render_canvas_surface(
|
||||||
|
div()
|
||||||
|
.size_full()
|
||||||
|
.p_8()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.gap_5()
|
||||||
|
.child(render_settings_header(snapshot))
|
||||||
|
.child(render_settings_summary(snapshot))
|
||||||
|
.child(render_settings_routes(cx)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_settings_header(snapshot: &BrowserSnapshot) -> AnyElement {
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_end()
|
||||||
|
.justify_between()
|
||||||
|
.gap_4()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.min_w_0()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.gap_2()
|
||||||
|
.child(div().text_size(px(26.0)).text_color(rgb(colors::INK)).child("Settings"))
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_sm()
|
||||||
|
.truncate()
|
||||||
|
.text_color(rgb(colors::MUTED))
|
||||||
|
.child(format!("Profile: {}", snapshot.active_profile_name)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.font_semibold()
|
||||||
|
.text_color(rgb(colors::MUTED))
|
||||||
|
.child(format!("{} routes", SETTINGS_ROUTES.len())),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_settings_summary(snapshot: &BrowserSnapshot) -> AnyElement {
|
||||||
|
div()
|
||||||
|
.border_t_1()
|
||||||
|
.border_b_1()
|
||||||
|
.border_color(rgb(colors::HAIRLINE))
|
||||||
|
.py_3()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_between()
|
||||||
|
.gap_4()
|
||||||
|
.children([
|
||||||
|
settings_metric("Profiles", snapshot.profiles.len()),
|
||||||
|
settings_metric("Plugins", snapshot.installed_plugins.len()),
|
||||||
|
settings_metric("Sync objects", snapshot.sync_status.objects().len()),
|
||||||
|
settings_metric("Open tabs", snapshot.tabs.len()),
|
||||||
|
])
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn settings_metric(label: &'static str, value: usize) -> AnyElement {
|
||||||
|
div()
|
||||||
|
.min_w_0()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.gap_1()
|
||||||
|
.child(div().text_xs().text_color(rgb(colors::MUTED)).child(label))
|
||||||
|
.child(
|
||||||
|
div().text_sm().font_semibold().text_color(rgb(colors::INK)).child(value.to_string()),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_settings_routes(cx: &mut Context<ElyShell>) -> AnyElement {
|
||||||
|
div()
|
||||||
|
.flex_1()
|
||||||
|
.min_h_0()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.overflow_y_scrollbar()
|
||||||
|
.children(
|
||||||
|
SETTINGS_ROUTES
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, route)| render_settings_route(index, route, cx)),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_settings_route(
|
||||||
|
index: usize,
|
||||||
|
settings_route: &SettingsRoute,
|
||||||
|
cx: &mut Context<ElyShell>,
|
||||||
|
) -> AnyElement {
|
||||||
|
let route = settings_route.route;
|
||||||
|
|
||||||
|
div()
|
||||||
|
.py_3()
|
||||||
|
.border_b_1()
|
||||||
|
.border_color(rgb(colors::HAIRLINE))
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_between()
|
||||||
|
.gap_4()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.min_w_0()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_3()
|
||||||
|
.child(div().text_color(rgb(colors::MUTED)).child(settings_route.icon.clone()))
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.min_w_0()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.gap_1()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_sm()
|
||||||
|
.font_semibold()
|
||||||
|
.truncate()
|
||||||
|
.text_color(rgb(colors::INK))
|
||||||
|
.child(settings_route.title),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.truncate()
|
||||||
|
.text_color(rgb(colors::MUTED))
|
||||||
|
.child(settings_route.detail),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new(("open-settings-route", index))
|
||||||
|
.ghost()
|
||||||
|
.xsmall()
|
||||||
|
.label("Open")
|
||||||
|
.tooltip(settings_route.title)
|
||||||
|
.on_click(cx.listener(move |shell, _, window, cx| {
|
||||||
|
shell.open_internal_tab(route, window, cx);
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user