add commit panel
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Error;
|
||||
use assets::CustomIconName;
|
||||
use gpui::prelude::*;
|
||||
use gpui::{
|
||||
AnyElement, App, ClipboardItem, Context, Entity, EventEmitter, FocusHandle, Focusable, Pixels,
|
||||
Render, SharedString, Size, Subscription, Task, Window, div, px, size,
|
||||
Render, SharedString, Size, Subscription, Task, WeakEntity, Window, div, px, size,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants, DropdownButton};
|
||||
use gpui_component::combobox::{Caret, Combobox, ComboboxEvent, ComboboxState, ComboboxTriggerCtx};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::dock::{DockArea, DockPlacement, Panel, PanelEvent};
|
||||
use gpui_component::menu::PopupMenuItem;
|
||||
use gpui_component::searchable_list::SearchableVec;
|
||||
use gpui_component::tab::{Tab, TabBar};
|
||||
@@ -26,6 +27,7 @@ use signed_state::{GitStore, RepoStore};
|
||||
|
||||
mod browser;
|
||||
mod commits;
|
||||
mod diff;
|
||||
mod helpers;
|
||||
|
||||
use browser::{
|
||||
@@ -33,6 +35,7 @@ use browser::{
|
||||
MarkdownView,
|
||||
};
|
||||
use commits::COMMIT_ROW_HEIGHT;
|
||||
use diff::CommitDiffView;
|
||||
use helpers::{build_tree_items, is_markdown_path};
|
||||
|
||||
/// What kind of ref the header selectors switch to.
|
||||
@@ -47,6 +50,10 @@ enum RefKind {
|
||||
/// Detail view of a repository: header, stats, a file explorer with README
|
||||
/// preview (cloned from the announcement's `clone` URLs), and metadata.
|
||||
pub struct RepoDetailView {
|
||||
focus_handle: FocusHandle,
|
||||
/// Dock area the detail view lives in; new panels (commit diffs) are
|
||||
/// added there.
|
||||
dock_area: WeakEntity<DockArea>,
|
||||
/// Snapshot taken at open time, shown until the store's first refresh
|
||||
/// completes (and as a fallback while the store has no announcement).
|
||||
initial: Announcement,
|
||||
@@ -107,7 +114,6 @@ pub struct RepoDetailView {
|
||||
/// Bumped on every branch/tag switch; in-flight loads tagged with an
|
||||
/// older generation are discarded when they complete.
|
||||
ref_generation: u64,
|
||||
focus_handle: FocusHandle,
|
||||
/// In-flight tasks; finished tasks are pruned on every push, so the vec
|
||||
/// stays bounded by the number of concurrent loads.
|
||||
tasks: Vec<Task<Result<(), Error>>>,
|
||||
@@ -117,7 +123,12 @@ pub struct RepoDetailView {
|
||||
}
|
||||
|
||||
impl RepoDetailView {
|
||||
pub fn new(initial: Announcement, window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
pub fn new(
|
||||
dock_area: WeakEntity<DockArea>,
|
||||
initial: Announcement,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let store = cx.new(|cx| RepoStore::new(initial.addr(), cx));
|
||||
let tree_state = cx.new(|cx| TreeState::new(cx));
|
||||
|
||||
@@ -215,6 +226,7 @@ impl RepoDetailView {
|
||||
|
||||
Self {
|
||||
initial,
|
||||
dock_area,
|
||||
announcement: None,
|
||||
relays,
|
||||
web,
|
||||
@@ -568,6 +580,36 @@ impl RepoDetailView {
|
||||
self.track(task);
|
||||
}
|
||||
|
||||
/// Open a new panel showing the diff of `commit` (all files it changed,
|
||||
/// with the line diff of each). Called from the Commits tab rows and the
|
||||
/// latest-commit button in the header.
|
||||
fn open_commit_diff(
|
||||
&mut self,
|
||||
commit: &FileCommit,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let Some(worktree) = self.worktree.clone() else {
|
||||
return;
|
||||
};
|
||||
// Same display name as the repo detail panel's title.
|
||||
let announcement = self.announcement.as_ref().unwrap_or(&self.initial);
|
||||
let repo_name = announcement
|
||||
.name
|
||||
.clone()
|
||||
.unwrap_or_else(|| SharedString::from(announcement.id.clone()));
|
||||
|
||||
let panel =
|
||||
cx.new(|cx| CommitDiffView::new(worktree, repo_name, commit.clone(), window, cx));
|
||||
if let Some(dock_area) = self.dock_area.upgrade() {
|
||||
dock_area.update(cx, |dock_area, cx| {
|
||||
// The diff viewer lives in the bottom dock, leaving the
|
||||
// central explorer open while browsing a commit.
|
||||
dock_area.add_panel(Arc::new(panel), DockPlacement::Bottom, None, window, cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Check out `name` (a branch or tag picked in the header) and refresh
|
||||
/// the explorer once the switch completes.
|
||||
fn switch_ref(
|
||||
@@ -1057,7 +1099,13 @@ impl Render for RepoDetailView {
|
||||
.map_or_else(SharedString::default, |commit| {
|
||||
commit.summary.clone().into()
|
||||
}),
|
||||
),
|
||||
)
|
||||
.on_click(cx.listener(|this, _event, window, cx| {
|
||||
if let Some(commit) = &this.head_commit {
|
||||
let commit = commit.clone();
|
||||
this.open_commit_diff(&commit, window, cx);
|
||||
}
|
||||
})),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user