update sidebar

This commit is contained in:
2026-08-07 19:22:21 +07:00
parent a734141837
commit 161c066ca8
3 changed files with 235 additions and 71 deletions
+2 -1
View File
@@ -34,7 +34,8 @@ impl RepoListView {
.unwrap_or_else(|| announcement.id.clone());
let owner = ProfileStore::global(cx)
.update(cx, |store, cx| store.get(announcement.owner, cx))
.read(cx)
.get(&announcement.owner)
.name();
let description = announcement.description.clone().unwrap_or_default();
+149 -14
View File
@@ -2,14 +2,15 @@ use std::sync::Arc;
use gpui::prelude::*;
use gpui::{
App, Context, EventEmitter, FocusHandle, Focusable, Render, Subscription, WeakEntity, Window,
div,
App, ClickEvent, Context, ElementId, EventEmitter, FocusHandle, Focusable, Render,
SharedString, StyleRefinement, Subscription, WeakEntity, Window, div,
};
use gpui_component::avatar::Avatar;
use gpui_component::button::{Button, ButtonVariants};
use gpui_component::dock::{DockArea, DockPlacement, Panel, PanelEvent};
use gpui_component::input::InputState;
use gpui_component::{ActiveTheme, v_flex};
use signed_state::{Backend, BackendEvent};
use gpui_component::{ActiveTheme, Icon, IconName, Sizable, StyledExt, h_flex, v_flex};
use signed_state::{Backend, BackendEvent, ProfileStore};
use super::RepoListView;
@@ -128,15 +129,8 @@ impl Focusable for SidebarPanel {
impl Render for SidebarPanel {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if self.logged_in {
v_flex().child(
Button::new("explore")
.label("Explore")
.w_full()
.on_click(cx.listener(|this, _, window, cx| this.open_explore(window, cx))),
)
} else {
v_flex()
if !self.logged_in {
return v_flex()
.p_4()
.size_full()
.items_center()
@@ -165,7 +159,148 @@ impl Render for SidebarPanel {
.on_click(
cx.listener(|this, _ev, window, cx| this.open_import(window, cx)),
),
)
);
}
let backend = Backend::global(cx);
let profile_store = ProfileStore::global(cx);
let profile = backend
.read(cx)
.current_user()
.map(|public_key| profile_store.read(cx).get(&public_key));
v_flex()
.size_full()
.justify_between()
.bg(cx.theme().sidebar)
.text_color(cx.theme().sidebar_foreground)
.child(
div()
.flex_1()
.when_some(profile.as_ref(), |this, profile| {
let name = profile.name();
let picture = profile.picture();
this.child(
h_flex()
.h_12()
.px_3()
.gap_2()
.child(
Avatar::new()
.name(name.clone())
.when_some(picture, |this, url| this.src(url))
.small()
.border_0(),
)
.child(div().text_sm().child(name)),
)
})
.child(
v_flex()
.px_2()
.gap_1()
.items_start()
.justify_start()
.child(NavItem::new("inbox", "Inbox", IconName::Inbox).on_click(
cx.listener(|this, _ev, window, cx| this.open_explore(window, cx)),
))
.child(NavItem::new("explore", "Browse", IconName::Globe).on_click(
cx.listener(|this, _ev, window, cx| this.open_explore(window, cx)),
))
.child(
v_flex().w_full().child(
h_flex()
.h_10()
.w_full()
.justify_between()
.items_center()
.child(
h_flex()
.px_2()
.gap_2()
.text_color(cx.theme().muted_foreground)
.child(Icon::new(IconName::Folder).small())
.child(
div()
.text_xs()
.font_semibold()
.child("All Repositories"),
),
)
.child(
Button::new("add").icon(IconName::Plus).small().ghost(),
),
),
),
),
)
.child(
v_flex()
.p_2()
.flex_shrink_0()
.gap_1()
.items_start()
.justify_start()
.child(NavItem::new("guide", "Guide", IconName::Info).on_click(
cx.listener(|this, _ev, window, cx| this.open_explore(window, cx)),
))
.child(
NavItem::new("settings", "Settings", IconName::Settings).on_click(
cx.listener(|this, _ev, window, cx| this.open_explore(window, cx)),
),
),
)
}
}
/// A single navigation entry in the sidebar: an icon and label with a hover
/// highlight and an optional click handler.
#[allow(clippy::type_complexity)]
#[derive(IntoElement)]
struct NavItem {
id: ElementId,
style: StyleRefinement,
icon: IconName,
label: SharedString,
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
}
impl NavItem {
fn new<I, L>(id: I, label: L, icon: IconName) -> Self
where
I: Into<ElementId>,
L: Into<SharedString>,
{
Self {
id: id.into(),
icon,
label: label.into(),
style: StyleRefinement::default(),
on_click: None,
}
}
fn on_click(mut self, listener: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
self.on_click = Some(Box::new(listener));
self
}
}
impl RenderOnce for NavItem {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.id(self.id)
.refine_style(&self.style)
.px_2()
.py_1()
.w_full()
.gap_2()
.rounded(cx.theme().radius)
.child(Icon::new(self.icon).small())
.child(div().text_sm().child(self.label))
.hover(|this| this.bg(cx.theme().list_hover))
.when_some(self.on_click, |this, listener| this.on_click(listener))
}
}