This commit is contained in:
2026-08-15 11:00:55 +07:00
parent ce076bee1d
commit 2d281dfbbb
4 changed files with 119 additions and 43 deletions
@@ -6,7 +6,7 @@
use gpui::prelude::*;
use gpui::{AnyElement, Context, Entity, SharedString, WeakEntity, Window, div, px};
use gpui_component::button::{Button, ButtonVariants};
use gpui_component::input::{Editor, EditorState};
use gpui_component::input::{Editor, EditorState, TabSize};
use gpui_component::list::ListItem;
use gpui_component::spinner::Spinner;
use gpui_component::text::{TextView, TextViewState};
@@ -280,7 +280,16 @@ impl RepoDetailView {
cx: &mut Context<Self>,
) {
let language = code_language(path.as_ref()).unwrap_or("text");
let state = cx.new(|cx| EditorState::new(language, window, cx).default_value(text));
let state = cx.new(|cx| {
EditorState::new(language, window, cx)
.default_value(text)
.tab_size(TabSize {
tab_size: 4,
hard_tabs: false,
})
.line_number(true)
.folding(true)
});
self.code = Some(CodeView { path, state });
}
@@ -294,14 +303,12 @@ impl RepoDetailView {
return preview_spinner();
}
// Disabled: the preview is read-only. Selection, copy and the
// built-in search (Cmd/Ctrl+F) still work; editing is blocked by the
// component's disabled state.
Editor::new(&code.state)
.readonly(true)
.bordered(false)
.rounded_none()
.h_full()
.text_sm()
.into_any_element()
}
}
+105 -36
View File
@@ -11,6 +11,7 @@ use gpui::{
AnyElement, App, ClipboardItem, Context, Entity, EventEmitter, FocusHandle, Focusable, Pixels,
Render, SharedString, Size, Subscription, Task, WeakEntity, Window, div, px, size,
};
use gpui_component::avatar::{Avatar, AvatarGroup};
use gpui_component::button::{Button, ButtonVariants, DropdownButton};
use gpui_component::combobox::{
Caret, Combobox, ComboboxEvent, ComboboxState, ComboboxTriggerContext,
@@ -26,7 +27,7 @@ use gpui_component::{
};
use signed_core::Announcement;
use signed_git::{CommitList, FileCommit};
use signed_state::{GitStore, RepoStore};
use signed_state::{GitStore, ProfileStore, RepoStore};
mod browser;
mod commits;
@@ -941,6 +942,54 @@ impl RepoDetailView {
.clone()
.unwrap_or_else(|| SharedString::from(announcement.id.clone()))
}
/// Horizontal list of everyone who maintains the repository: the owner
/// shown in full, and any additional maintainers as a compact overlapping avatar group.
fn render_maintainers(&self, cx: &mut Context<Self>) -> AnyElement {
let announcement = self.announcement();
let profile_store = ProfileStore::global(cx);
let mut seen = HashSet::new();
let rest: Vec<_> = announcement
.maintainers
.iter()
.copied()
.filter(|key| *key != announcement.owner && seen.insert(*key))
.collect();
let owner = profile_store.read(cx).get(&announcement.owner);
let owner_name = owner.name();
let owner_picture = owner.picture();
h_flex()
.w_full()
.gap_3()
.items_center()
.flex_wrap()
.child(
h_flex()
.gap_1()
.items_center()
.child(
Avatar::new()
.name(owner_name.clone())
.when_some(owner_picture, |this, url| this.src(url))
.small(),
)
.child(div().text_xs().whitespace_nowrap().child(owner_name)),
)
.when(!rest.is_empty(), |this| {
this.child(AvatarGroup::new().small().limit(5).ellipsis().children(
rest.into_iter().map(|key| {
let profile = profile_store.read(cx).get(&key);
Avatar::new()
.name(profile.name())
.when_some(profile.picture(), |this, url| this.src(url))
}),
))
})
.into_any_element()
}
}
impl Panel for RepoDetailView {
@@ -1064,11 +1113,25 @@ impl RepoDetailView {
.child(div().font_semibold().child(name))
.child(
div()
.min_w_0()
.text_xs()
.text_color(cx.theme().muted_foreground)
.line_clamp(3)
.line_clamp(2)
.text_ellipsis()
.child(description),
)
.child(
h_flex()
.mt_2()
.gap_2()
.child(
div()
.text_xs()
.text_color(cx.theme().muted_foreground)
.font_semibold()
.child("Maintainers:"),
)
.child(self.render_maintainers(cx)),
),
)
.child(
@@ -1081,6 +1144,7 @@ impl RepoDetailView {
.button(
Button::new("relay-trigger")
.label(format!("{} relays", relays.len()))
.small()
.ghost(),
)
.dropdown_menu(move |menu, _window, _cx| {
@@ -1107,7 +1171,12 @@ impl RepoDetailView {
)
.child(
DropdownButton::new("web")
.button(Button::new("web-trigger").label("Websites").ghost())
.button(
Button::new("web-trigger")
.label("Websites")
.small()
.ghost(),
)
.dropdown_menu(move |menu, _window, _cx| {
let mut menu = menu;
if web.is_empty() {
@@ -1167,41 +1236,9 @@ impl RepoDetailView {
.flex_1()
.gap_2()
.justify_end()
.child(
div().w(px(120.)).child(
Combobox::new(&self.branch_select)
.placeholder("Branch")
.appearance(false)
.menu_width(px(200.))
.disabled(worktree_empty)
.bg(cx.theme().muted)
.rounded(cx.theme().radius)
.render_trigger(|ctx, _window, cx| {
Self::render_ref_trigger(
ctx,
CustomIconName::GitBranch,
cx,
)
}),
),
)
.child(
div().w(px(120.)).child(
Combobox::new(&self.tag_select)
.placeholder("Tag")
.appearance(false)
.menu_width(px(200.))
.disabled(worktree_empty)
.bg(cx.theme().muted)
.rounded(cx.theme().radius)
.render_trigger(|ctx, _window, cx| {
Self::render_ref_trigger(ctx, CustomIconName::Tag, cx)
}),
),
)
.child(
Button::new("enc")
.secondary()
.ghost()
.when_some(self.head_commit.as_ref(), |this, commit| {
this.child(
div()
@@ -1232,6 +1269,38 @@ impl RepoDetailView {
this.open_commit_diff(&id, window, cx);
}
})),
)
.child(
div().w(px(120.)).child(
Combobox::new(&self.branch_select)
.placeholder("Branch")
.appearance(false)
.menu_width(px(200.))
.disabled(worktree_empty)
.bg(cx.theme().muted)
.rounded(cx.theme().radius)
.render_trigger(|ctx, _window, cx| {
Self::render_ref_trigger(
ctx,
CustomIconName::GitBranch,
cx,
)
}),
),
)
.child(
div().w(px(120.)).child(
Combobox::new(&self.tag_select)
.placeholder("Tag")
.appearance(false)
.menu_width(px(200.))
.disabled(worktree_empty)
.bg(cx.theme().muted)
.rounded(cx.theme().radius)
.render_trigger(|ctx, _window, cx| {
Self::render_ref_trigger(ctx, CustomIconName::Tag, cx)
}),
),
),
),
)
+1 -1
View File
@@ -210,7 +210,7 @@ impl Render for SidebarPanel {
.child(NavItem::new("explore", "Browse", IconName::Globe).on_click(
cx.listener(|this, _ev, window, cx| this.open_explore(window, cx)),
))
.child(NavItem::new("search", "Saerch", IconName::Search).on_click(
.child(NavItem::new("search", "Search", IconName::Search).on_click(
cx.listener(|this, _ev, window, cx| this.open_explore(window, cx)),
))
.child(
+1 -1
View File
@@ -42,7 +42,7 @@ fn main() {
kind: WindowKind::Normal,
app_id: Some("Signed".to_owned()),
titlebar: Some(TitlebarOptions {
title: Some(SharedString::new_static("Signed Platform")),
title: Some(SharedString::new_static("Signed")),
traffic_light_position: Some(point(px(9.0), px(9.0))),
appears_transparent: true,
}),