refactor
This commit is contained in:
@@ -5,8 +5,10 @@ use assets::CustomIconName;
|
||||
use gpui::prelude::*;
|
||||
use gpui::{AnyElement, App, Entity, SharedString, div, px};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::combobox::{Caret, ComboboxTriggerContext};
|
||||
use gpui_component::input::{Textarea, TextareaState};
|
||||
use gpui_component::menu::PopupMenu;
|
||||
use gpui_component::searchable_list::SearchableVec;
|
||||
use gpui_component::tag::Tag;
|
||||
use gpui_component::tree::TreeItem;
|
||||
use gpui_component::{ActiveTheme, Icon, Sizable, StyledExt, h_flex, v_flex};
|
||||
@@ -365,6 +367,44 @@ pub(super) fn pr_roots(store: &RepoStore) -> &[Event] {
|
||||
&store.pull_requests
|
||||
}
|
||||
|
||||
/// The trigger body of the branch/tag selectors.
|
||||
///
|
||||
/// The kind icon, the selection or placeholder, and the caret.
|
||||
/// `Combobox` replaces its default trigger entirely,
|
||||
/// the only way to show an icon inside it.
|
||||
pub(super) fn ref_selector_trigger(
|
||||
ctx: &ComboboxTriggerContext<SearchableVec<SharedString>>,
|
||||
icon: CustomIconName,
|
||||
cx: &App,
|
||||
) -> AnyElement {
|
||||
let muted = cx.theme().muted_foreground;
|
||||
|
||||
h_flex()
|
||||
.w_full()
|
||||
.min_w_0()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
.child(Icon::new(icon).small().flex_shrink_0())
|
||||
.child(
|
||||
div()
|
||||
.flex_1()
|
||||
.min_w_0()
|
||||
.overflow_hidden()
|
||||
.text_ellipsis()
|
||||
.whitespace_nowrap()
|
||||
.when(ctx.selection().is_empty(), |this| this.text_color(muted))
|
||||
.child(
|
||||
ctx.selection()
|
||||
.first()
|
||||
.map(|(_, item)| item.clone())
|
||||
.or_else(|| ctx.placeholder().cloned())
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
)
|
||||
.child(Caret::new(ctx.size()).text_color(muted))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Section heading of a detail sidebar, shared by the issue and PR panels.
|
||||
pub(super) fn sidebar_title(text: &str, cx: &App) -> AnyElement {
|
||||
div()
|
||||
@@ -459,14 +499,7 @@ pub(super) fn sidebar_section(
|
||||
}
|
||||
|
||||
/// The comments on a root event, issue or PR, one card per comment.
|
||||
///
|
||||
/// Comment bodies become shared strings once per comment, not per render.
|
||||
pub(super) fn comments_section(
|
||||
store: &Entity<RepoStore>,
|
||||
root: EventId,
|
||||
contents: &mut HashMap<EventId, SharedString>,
|
||||
cx: &App,
|
||||
) -> AnyElement {
|
||||
pub(super) fn comments_section(store: &Entity<RepoStore>, root: EventId, cx: &App) -> AnyElement {
|
||||
let store = store.read(cx);
|
||||
let comments: Vec<&Event> = store.comments_of(&root).collect();
|
||||
let title = SharedString::from(format!("Discussions {}", comments.len()));
|
||||
@@ -479,10 +512,7 @@ pub(super) fn comments_section(
|
||||
let author = profile.name();
|
||||
let picture = profile.picture();
|
||||
let age = relative_time(comment.created_at);
|
||||
let content = contents
|
||||
.entry(comment.id)
|
||||
.or_insert_with(|| SharedString::from(comment.content.clone()))
|
||||
.clone();
|
||||
let content = SharedString::from(comment.content.as_str());
|
||||
|
||||
v_flex()
|
||||
.gap_1()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use dock::{BasePanel, Panel, PanelEvent};
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
@@ -22,7 +20,6 @@ pub struct IssueDetailView {
|
||||
/// Repo store holding the issues and their statuses.
|
||||
store: Entity<RepoStore>,
|
||||
issue_id: EventId,
|
||||
contents: HashMap<EventId, SharedString>,
|
||||
/// Input state of the comment textarea.
|
||||
comment_input: Entity<TextareaState>,
|
||||
focus_handle: FocusHandle,
|
||||
@@ -43,7 +40,6 @@ impl IssueDetailView {
|
||||
store,
|
||||
issue_id,
|
||||
comment_input,
|
||||
contents: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,17 +87,11 @@ impl Render for IssueDetailView {
|
||||
let (title, author, picture, status, age, issue_id, content) = {
|
||||
let profile_store = ProfileStore::global(cx);
|
||||
let profile = profile_store.read(cx).get(&issue.pubkey);
|
||||
let content = self
|
||||
.contents
|
||||
.entry(issue.id)
|
||||
.or_insert_with(|| {
|
||||
if issue.content.is_empty() {
|
||||
SharedString::from("No description provided.")
|
||||
} else {
|
||||
SharedString::from(&issue.content)
|
||||
}
|
||||
})
|
||||
.clone();
|
||||
let content = if issue.content.is_empty() {
|
||||
SharedString::from("No description provided.")
|
||||
} else {
|
||||
SharedString::from(&issue.content)
|
||||
};
|
||||
|
||||
(
|
||||
activity_subject(issue),
|
||||
@@ -172,12 +162,7 @@ impl Render for IssueDetailView {
|
||||
)
|
||||
.child(div().text_sm().child(content)),
|
||||
)
|
||||
.child(comments_section(
|
||||
&self.store,
|
||||
issue_id,
|
||||
&mut self.contents,
|
||||
cx,
|
||||
))
|
||||
.child(comments_section(&self.store, issue_id, cx))
|
||||
.child(comment_form(
|
||||
&self.store,
|
||||
issue_id,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use assets::CustomIconName;
|
||||
use dock::{BasePanel, DockArea, DockPlacement, Panel, PanelEvent, panel_handle};
|
||||
use dock::{BasePanel, DockArea, Panel, PanelEvent, add_center_panel, panel_handle};
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
AnyElement, App, Context, Entity, EventEmitter, FocusHandle, Focusable, Pixels, Render,
|
||||
@@ -110,7 +110,7 @@ impl IssuesView {
|
||||
let panel = cx.new(|cx| IssueDetailView::new(self.store.clone(), issue_id, window, cx));
|
||||
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Error;
|
||||
use assets::CustomIconName;
|
||||
use dock::{BasePanel, DockArea, DockPlacement, Panel, PanelEvent, panel_handle};
|
||||
use dock::{BasePanel, DockArea, Panel, PanelEvent, add_center_panel, panel_handle};
|
||||
use gix::Repository;
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
@@ -16,9 +16,7 @@ use gpui::{
|
||||
use gpui_base::{Button as BaseButton, Disableable, Popover};
|
||||
use gpui_component::alert::Alert;
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::combobox::{
|
||||
Caret, Combobox, ComboboxEvent, ComboboxState, ComboboxTriggerContext,
|
||||
};
|
||||
use gpui_component::combobox::{Combobox, ComboboxEvent, ComboboxState};
|
||||
use gpui_component::menu::DropdownMenu;
|
||||
use gpui_component::searchable_list::SearchableVec;
|
||||
use gpui_component::tree::TreeState;
|
||||
@@ -26,14 +24,14 @@ use gpui_component::{
|
||||
ActiveTheme, Colorize, Icon, IconName, Sizable, StyledExt, ThemeStyled,
|
||||
VirtualListScrollHandle, h_flex, v_flex,
|
||||
};
|
||||
use nostr::prelude::{EventId, RelayUrl, ToBech32};
|
||||
use nostr::prelude::{RelayUrl, ToBech32};
|
||||
use signed_core::{Announcement, RepoAddr, RepoStatus, filters};
|
||||
use signed_git::{CommitList, FileCommit};
|
||||
use signed_state::{
|
||||
Backend, CheckoutStatus, CheckoutsStore, GitStore, LocalReposStore, ProfileStore,
|
||||
RepoListStore, RepoStore, pr_proposes_checkout,
|
||||
};
|
||||
use signed_ui::{DropdownButton, PixelAvatar, UserAvatar, copy_row};
|
||||
use signed_ui::{CountBadge, DropdownButton, PixelAvatar, UserAvatar, copy_row};
|
||||
|
||||
mod about;
|
||||
mod browser;
|
||||
@@ -55,7 +53,10 @@ use browser::{
|
||||
};
|
||||
use commits::COMMIT_ROW_HEIGHT;
|
||||
use diff::CommitDiffView;
|
||||
use helpers::{ShareTargets, TreeItemSeed, build_tree_items, is_markdown_path, tree_items};
|
||||
use helpers::{
|
||||
ShareTargets, TreeItemSeed, build_tree_items, is_markdown_path, ref_selector_trigger,
|
||||
tree_items,
|
||||
};
|
||||
use issues::{IssuesView, open_new_issue_dialog};
|
||||
use pull_requests::PullRequestsView;
|
||||
use send_patch::open_send_patch_panel;
|
||||
@@ -106,21 +107,6 @@ struct RepoData {
|
||||
head_commit: Option<FileCommit>,
|
||||
}
|
||||
|
||||
/// Derived NIP-34 header data.
|
||||
/// Renders avoid re-encoding bech32 share targets per frame.
|
||||
/// They also avoid rebuilding the clone command strings.
|
||||
struct HeaderCache {
|
||||
/// Announcement event ID and owner NIP-05 this cache was built from.
|
||||
/// Rebuilt when either changes.
|
||||
/// A new announcement version, or the owner's profile arriving with a NIP-05 identifier.
|
||||
key: (EventId, Option<String>),
|
||||
announcement: Rc<Announcement>,
|
||||
share: Rc<ShareTargets>,
|
||||
ngit_command: SharedString,
|
||||
nak_command: SharedString,
|
||||
git_commands: Rc<Vec<SharedString>>,
|
||||
}
|
||||
|
||||
/// Detail view of a repository, header, stats and metadata.
|
||||
/// A file explorer with README preview, cloned from the announcement's `clone` URLs.
|
||||
pub struct RepoDetailView {
|
||||
@@ -193,10 +179,6 @@ pub struct RepoDetailView {
|
||||
/// Bumped on every branch/tag switch.
|
||||
/// In-flight loads with an older generation are discarded when they complete.
|
||||
ref_generation: u64,
|
||||
/// Derived NIP-34 header data, share targets and clone commands.
|
||||
/// Rebuilt only when the announcement or the owner's NIP-05 changes.
|
||||
/// Not on every render.
|
||||
header_cache: Option<HeaderCache>,
|
||||
/// In-flight tasks, finished tasks are pruned on every push.
|
||||
/// The vec stays bounded by the number of concurrent loads.
|
||||
tasks: Vec<Task<Result<(), Error>>>,
|
||||
@@ -346,7 +328,6 @@ impl RepoDetailView {
|
||||
tag_select,
|
||||
switching_ref: false,
|
||||
ref_generation: 0,
|
||||
header_cache: None,
|
||||
focus_handle: cx.focus_handle(),
|
||||
tasks: Vec::new(),
|
||||
_subscriptions: subscriptions,
|
||||
@@ -922,7 +903,7 @@ impl RepoDetailView {
|
||||
cx.new(|cx| CommitDiffView::new(worktree, repo_name, commit_id.into(), window, cx));
|
||||
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1056,7 +1037,7 @@ impl RepoDetailView {
|
||||
let panel = cx.new(|cx| IssuesView::new(self.dock_area.clone(), store, window, cx));
|
||||
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1072,7 +1053,7 @@ impl RepoDetailView {
|
||||
let panel = cx.new(|cx| PullRequestsView::new(self.dock_area.clone(), store, window, cx));
|
||||
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1232,43 +1213,6 @@ impl RepoDetailView {
|
||||
});
|
||||
}
|
||||
|
||||
/// Trigger body for the branch/tag selectors.
|
||||
/// The kind icon, the selection or placeholder, and the caret.
|
||||
/// `Combobox` replaces its default trigger entirely.
|
||||
/// That is the only way to show an icon inside it.
|
||||
fn render_ref_trigger(
|
||||
ctx: &ComboboxTriggerContext<SearchableVec<SharedString>>,
|
||||
icon: CustomIconName,
|
||||
cx: &App,
|
||||
) -> AnyElement {
|
||||
let muted = cx.theme().muted_foreground;
|
||||
|
||||
h_flex()
|
||||
.w_full()
|
||||
.min_w_0()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
.child(Icon::new(icon).small().flex_shrink_0())
|
||||
.child(
|
||||
div()
|
||||
.flex_1()
|
||||
.min_w_0()
|
||||
.overflow_hidden()
|
||||
.text_ellipsis()
|
||||
.whitespace_nowrap()
|
||||
.when(ctx.selection().is_empty(), |this| this.text_color(muted))
|
||||
.child(
|
||||
ctx.selection()
|
||||
.first()
|
||||
.map(|(_, item)| item.clone())
|
||||
.or_else(|| ctx.placeholder().cloned())
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
)
|
||||
.child(Caret::new(ctx.size()).text_color(muted))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Refresh the file explorer, preview pane and commit list after a successful switch.
|
||||
/// The selectors were already updated by [`Self::switch_ref`].
|
||||
/// [`Self::switching_ref`] stays set until this reload finishes.
|
||||
@@ -1422,9 +1366,8 @@ impl RepoDetailView {
|
||||
return div().into_any_element();
|
||||
};
|
||||
|
||||
// The header derives bech32 share targets and clone commands.
|
||||
// Rebuild them only when the announcement or the owner's NIP-05 changes.
|
||||
// Not on every render.
|
||||
// Derived NIP-34 header data, share targets and clone commands.
|
||||
// Rebuilt per frame: two bech32 encodes and a couple of format strings.
|
||||
let nip05 = ProfileStore::global(cx)
|
||||
.read(cx)
|
||||
.get(&source.owner)
|
||||
@@ -1432,32 +1375,12 @@ impl RepoDetailView {
|
||||
.nip05
|
||||
.clone()
|
||||
.filter(|nip05| !nip05.trim().is_empty());
|
||||
let key = (source.event_id, nip05);
|
||||
|
||||
if self
|
||||
.header_cache
|
||||
.as_ref()
|
||||
.is_none_or(|cache| cache.key != key)
|
||||
{
|
||||
let announcement = source.clone();
|
||||
let share = ShareTargets::from_announcement(&announcement);
|
||||
let nostr_url = nostr_clone_url(&announcement, key.1.as_deref());
|
||||
self.header_cache = Some(HeaderCache {
|
||||
ngit_command: SharedString::from(format!("git clone {nostr_url}")),
|
||||
nak_command: SharedString::from(format!("nak git clone {nostr_url}")),
|
||||
git_commands: Rc::new(announcement.clone_urls()),
|
||||
share: Rc::new(share),
|
||||
announcement: Rc::new(announcement),
|
||||
key,
|
||||
});
|
||||
}
|
||||
|
||||
let cache = self.header_cache.as_ref().expect("cache just built");
|
||||
let announcement = cache.announcement.clone();
|
||||
let share = cache.share.clone();
|
||||
let ngit_command = cache.ngit_command.clone();
|
||||
let nak_command = cache.nak_command.clone();
|
||||
let git_commands = cache.git_commands.clone();
|
||||
let announcement = Rc::new(source.clone());
|
||||
let share = Rc::new(ShareTargets::from_announcement(&announcement));
|
||||
let nostr_url = nostr_clone_url(&announcement, nip05.as_deref());
|
||||
let ngit_command = SharedString::from(format!("git clone {nostr_url}"));
|
||||
let nak_command = SharedString::from(format!("nak git clone {nostr_url}"));
|
||||
let git_commands = Rc::new(announcement.clone_urls());
|
||||
|
||||
let name = self.display_name(cx);
|
||||
let description = announcement.description();
|
||||
@@ -2165,19 +2088,7 @@ impl RepoDetailView {
|
||||
.child("Commits"),
|
||||
)
|
||||
.when_some(commits_count, |this, count| {
|
||||
this.child(
|
||||
h_flex()
|
||||
.justify_center()
|
||||
.px_1()
|
||||
.py_0p5()
|
||||
.min_w_4()
|
||||
.text_size(px(8.))
|
||||
.bg(cx.theme().muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.rounded(cx.theme().radius)
|
||||
.line_height(relative(1.))
|
||||
.child(SharedString::from(count.to_string())),
|
||||
)
|
||||
this.child(CountBadge::new(count))
|
||||
})
|
||||
.text_color(cx.theme().button_foreground)
|
||||
.rounded(cx.theme().radius)
|
||||
@@ -2241,7 +2152,7 @@ impl RepoDetailView {
|
||||
.bg(cx.theme().muted)
|
||||
.rounded(cx.theme().radius)
|
||||
.render_trigger(|ctx, _window, cx| {
|
||||
Self::render_ref_trigger(ctx, CustomIconName::GitBranch, cx)
|
||||
ref_selector_trigger(ctx, CustomIconName::GitBranch, cx)
|
||||
}),
|
||||
),
|
||||
)
|
||||
@@ -2255,7 +2166,7 @@ impl RepoDetailView {
|
||||
.bg(cx.theme().muted)
|
||||
.rounded(cx.theme().radius)
|
||||
.render_trigger(|ctx, _window, cx| {
|
||||
Self::render_ref_trigger(ctx, CustomIconName::Tag, cx)
|
||||
ref_selector_trigger(ctx, CustomIconName::Tag, cx)
|
||||
}),
|
||||
),
|
||||
),
|
||||
@@ -2492,13 +2403,7 @@ pub(crate) fn open_repo_panel(
|
||||
|
||||
if let Some(dock_area) = dock_area.upgrade() {
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(
|
||||
panel_handle(detail.clone()),
|
||||
DockPlacement::Center,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
add_center_panel(dock_area, panel_handle(detail.clone()), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
|
||||
use assets::CustomIconName;
|
||||
use dock::{BasePanel, DockArea, DockPlacement, Panel, PanelEvent, panel_handle};
|
||||
use dock::{BasePanel, DockArea, Panel, PanelEvent, add_center_panel, panel_handle};
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
AnyElement, App, Context, Entity, EventEmitter, FocusHandle, Focusable, PathPromptOptions,
|
||||
@@ -11,9 +11,7 @@ use gpui::{
|
||||
};
|
||||
use gpui_base::{Button as BaseButton, StyledExt};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::combobox::{
|
||||
Caret, Combobox, ComboboxEvent, ComboboxState, ComboboxTriggerContext,
|
||||
};
|
||||
use gpui_component::combobox::{Combobox, ComboboxEvent, ComboboxState};
|
||||
use gpui_component::input::{Input, InputState, Textarea, TextareaState};
|
||||
use gpui_component::menu::{DropdownMenu, PopupMenu, PopupMenuItem};
|
||||
use gpui_component::scroll::Scrollbar;
|
||||
@@ -30,10 +28,11 @@ use signed_git::{
|
||||
sanitize_path_component, worktree_commit_range_commits, worktree_commit_range_diff,
|
||||
};
|
||||
use signed_state::{Backend, CheckoutsStore, GitStore, RepoListStore, RepoStore};
|
||||
use signed_ui::placeholder;
|
||||
use signed_ui::{CountBadge, placeholder};
|
||||
|
||||
use super::commits::{COMMIT_ROW_HEIGHT, commit_row};
|
||||
use super::diff::{CommitDiffView, DiffPane};
|
||||
use super::helpers::ref_selector_trigger;
|
||||
|
||||
/// The new pull request panel of a repository.
|
||||
pub struct NewPullRequestView {
|
||||
@@ -1019,7 +1018,7 @@ impl NewPullRequestView {
|
||||
});
|
||||
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1080,7 +1079,7 @@ impl NewPullRequestView {
|
||||
.bg(cx.theme().muted)
|
||||
.rounded(cx.theme().radius)
|
||||
.render_trigger(|ctx, _window, cx| {
|
||||
render_ref_trigger(ctx, CustomIconName::GitBranch, cx)
|
||||
ref_selector_trigger(ctx, CustomIconName::GitBranch, cx)
|
||||
}),
|
||||
),
|
||||
),
|
||||
@@ -1105,7 +1104,7 @@ impl NewPullRequestView {
|
||||
.bg(cx.theme().muted)
|
||||
.rounded(cx.theme().radius)
|
||||
.render_trigger(|ctx, _window, cx| {
|
||||
render_ref_trigger(ctx, CustomIconName::GitBranch, cx)
|
||||
ref_selector_trigger(ctx, CustomIconName::GitBranch, cx)
|
||||
}),
|
||||
),
|
||||
),
|
||||
@@ -1259,7 +1258,7 @@ impl NewPullRequestView {
|
||||
.child(Icon::new(CustomIconName::GitFile).small())
|
||||
.child("Files"),
|
||||
)
|
||||
.child(count_badge(files, cx))
|
||||
.child(CountBadge::new(files))
|
||||
.text_color(cx.theme().button_foreground)
|
||||
.rounded(cx.theme().radius)
|
||||
.hover(|this| this.bg(cx.theme().button_hover))
|
||||
@@ -1287,7 +1286,7 @@ impl NewPullRequestView {
|
||||
.child(Icon::new(CustomIconName::GitCommit).small())
|
||||
.child("Commits"),
|
||||
)
|
||||
.child(count_badge(commits, cx))
|
||||
.child(CountBadge::new(commits))
|
||||
.text_color(cx.theme().button_foreground)
|
||||
.rounded(cx.theme().radius)
|
||||
.hover(|this| this.bg(cx.theme().button_hover))
|
||||
@@ -1390,55 +1389,6 @@ impl NewPullRequestView {
|
||||
}
|
||||
}
|
||||
|
||||
/// The count badge of a tab, styled like the repository panel's.
|
||||
fn count_badge(count: usize, cx: &App) -> impl IntoElement {
|
||||
h_flex()
|
||||
.justify_center()
|
||||
.px_1()
|
||||
.py_0p5()
|
||||
.min_w_4()
|
||||
.text_size(px(8.))
|
||||
.bg(cx.theme().muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.rounded(cx.theme().radius)
|
||||
.line_height(relative(1.))
|
||||
.child(SharedString::from(count.to_string()))
|
||||
}
|
||||
|
||||
/// The trigger of a branch selector.
|
||||
fn render_ref_trigger(
|
||||
ctx: &ComboboxTriggerContext<SearchableVec<SharedString>>,
|
||||
icon: CustomIconName,
|
||||
cx: &App,
|
||||
) -> AnyElement {
|
||||
let muted = cx.theme().muted_foreground;
|
||||
|
||||
h_flex()
|
||||
.w_full()
|
||||
.min_w_0()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
.child(Icon::new(icon).small().flex_shrink_0())
|
||||
.child(
|
||||
div()
|
||||
.flex_1()
|
||||
.min_w_0()
|
||||
.overflow_hidden()
|
||||
.text_ellipsis()
|
||||
.whitespace_nowrap()
|
||||
.when(ctx.selection().is_empty(), |this| this.text_color(muted))
|
||||
.child(
|
||||
ctx.selection()
|
||||
.first()
|
||||
.map(|(_, item)| item.clone())
|
||||
.or_else(|| ctx.placeholder().cloned())
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
)
|
||||
.child(Caret::new(ctx.size()).text_color(muted))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Open the new pull request panel in the center dock.
|
||||
pub(super) fn open_new_pull_panel(
|
||||
dock_area: WeakEntity<DockArea>,
|
||||
@@ -1449,7 +1399,7 @@ pub(super) fn open_new_pull_panel(
|
||||
let panel = cx.new(|cx| NewPullRequestView::new(dock_area.clone(), store, window, cx));
|
||||
|
||||
let _ = dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -17,7 +16,6 @@ use gpui_component::input::{Textarea, TextareaState};
|
||||
use gpui_component::scroll::{ScrollableElement, Scrollbar};
|
||||
use gpui_component::spinner::Spinner;
|
||||
use gpui_component::tab::{Tab, TabBar};
|
||||
use gpui_component::tag::Tag;
|
||||
use gpui_component::{
|
||||
ActiveTheme, Sizable, StyledExt, VirtualListScrollHandle, WindowExt, h_flex, v_flex,
|
||||
v_virtual_list,
|
||||
@@ -26,7 +24,7 @@ use nostr::prelude::{Event, EventId, Kind, Nip34Tag};
|
||||
use signed_core::{activity_subject, pull_request_patch};
|
||||
use signed_git::{FileCommit, patch_commits, patch_diffs};
|
||||
use signed_state::{Backend, GitStore, ProfileStore, RepoStore};
|
||||
use signed_ui::{UserAvatar, placeholder, status_badge};
|
||||
use signed_ui::{CountBadge, UserAvatar, placeholder, status_badge};
|
||||
use utils::{relative_time, relative_time_secs};
|
||||
|
||||
use super::diff::{CommitDiffView, DiffPane};
|
||||
@@ -68,8 +66,6 @@ pub struct PullRequestDetailView {
|
||||
commit_item_sizes: Rc<Vec<Size<Pixels>>>,
|
||||
/// Virtual list state of the commits tab.
|
||||
commit_scroll_handle: VirtualListScrollHandle,
|
||||
/// Comment bodies as shared strings, keyed by comment event ID.
|
||||
contents: HashMap<EventId, SharedString>,
|
||||
/// In-flight tasks, finished tasks are pruned on every push.
|
||||
tasks: Vec<Task<Result<(), anyhow::Error>>>,
|
||||
}
|
||||
@@ -110,7 +106,6 @@ impl PullRequestDetailView {
|
||||
pane,
|
||||
commit_item_sizes: Rc::new(Vec::new()),
|
||||
commit_scroll_handle: VirtualListScrollHandle::new(),
|
||||
contents: HashMap::new(),
|
||||
tasks: Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -315,22 +310,14 @@ impl PullRequestDetailView {
|
||||
Tab::new()
|
||||
.label("Files")
|
||||
.when_some(files_count, |this, count| {
|
||||
this.suffix(
|
||||
Tag::secondary()
|
||||
.xsmall()
|
||||
.child(SharedString::from(count.to_string())),
|
||||
)
|
||||
this.suffix(CountBadge::new(count))
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
Tab::new()
|
||||
.label("Commits")
|
||||
.when_some(commits_count, |this, count| {
|
||||
this.suffix(
|
||||
Tag::secondary()
|
||||
.xsmall()
|
||||
.child(SharedString::from(count.to_string())),
|
||||
)
|
||||
this.suffix(CountBadge::new(count))
|
||||
}),
|
||||
)
|
||||
.into_any_element()
|
||||
@@ -410,12 +397,7 @@ impl PullRequestDetailView {
|
||||
this.child(div().text_sm().child(self.description.clone()))
|
||||
}),
|
||||
)
|
||||
.child(comments_section(
|
||||
&self.store,
|
||||
root_id,
|
||||
&mut self.contents,
|
||||
cx,
|
||||
))
|
||||
.child(comments_section(&self.store, root_id, cx))
|
||||
.child(comment_form(
|
||||
&self.store,
|
||||
root_id,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use assets::CustomIconName;
|
||||
use dock::{BasePanel, DockArea, DockPlacement, Panel, PanelEvent, panel_handle};
|
||||
use dock::{BasePanel, DockArea, Panel, PanelEvent, add_center_panel, panel_handle};
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
AnyElement, App, Context, Entity, EventEmitter, FocusHandle, Focusable, Pixels, Render,
|
||||
@@ -125,7 +125,7 @@ impl PullRequestsView {
|
||||
});
|
||||
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use dock::{BasePanel, DockArea, DockPlacement, Panel, PanelEvent, panel_handle};
|
||||
use dock::{BasePanel, DockArea, Panel, PanelEvent, add_center_panel, panel_handle};
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
AnyElement, App, Context, Entity, EventEmitter, FocusHandle, Focusable, Render, SharedString,
|
||||
@@ -202,7 +202,7 @@ pub(super) fn open_send_patch_panel(
|
||||
let panel = cx.new(|cx| SendPatchView::new(dock_area.clone(), store, window, cx));
|
||||
|
||||
let _ = dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ use std::path::{Path, PathBuf};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use assets::CustomIconName;
|
||||
use dock::{BasePanel, DockArea, DockPlacement, Panel, PanelEvent, TAB_BAR_HEIGHT, panel_handle};
|
||||
use dock::{
|
||||
BasePanel, DockArea, Panel, PanelEvent, TAB_BAR_HEIGHT, add_center_panel, panel_handle,
|
||||
};
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
AnyElement, App, Context, Div, Entity, EventEmitter, FocusHandle, Focusable, ObjectFit, Render,
|
||||
@@ -153,7 +155,7 @@ impl SidebarPanel {
|
||||
self.explore = Some(panel.downgrade());
|
||||
|
||||
let _ = self.dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(panel_handle(panel), DockPlacement::Center, None, window, cx);
|
||||
add_center_panel(dock_area, panel_handle(panel), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -197,13 +199,7 @@ impl SidebarPanel {
|
||||
cx.new(|cx| RepoDetailView::new_local(self.dock_area.clone(), path, window, cx));
|
||||
|
||||
let _ = self.dock_area.update(cx, |dock_area, cx| {
|
||||
dock_area.add_panel_view(
|
||||
panel_handle(detail),
|
||||
DockPlacement::Center,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
add_center_panel(dock_area, panel_handle(detail), window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user