Git activity indicator (#28204)
Closes #26182 Release Notes: - Added an activity indicator for long-running git commands. --------- Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
This commit is contained in:
parent
4f9f443452
commit
e3830d2ef5
11 changed files with 625 additions and 487 deletions
|
@ -88,7 +88,7 @@ impl BranchList {
|
|||
) -> Self {
|
||||
let all_branches_request = repository
|
||||
.clone()
|
||||
.map(|repository| repository.read(cx).branches());
|
||||
.map(|repository| repository.update(cx, |repository, _| repository.branches()));
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let mut all_branches = all_branches_request
|
||||
|
@ -202,10 +202,15 @@ impl BranchListDelegate {
|
|||
return;
|
||||
};
|
||||
cx.spawn(async move |_, cx| {
|
||||
cx.update(|cx| repo.read(cx).create_branch(new_branch_name.to_string()))?
|
||||
.await??;
|
||||
cx.update(|cx| repo.read(cx).change_branch(new_branch_name.to_string()))?
|
||||
.await??;
|
||||
repo.update(cx, |repo, _| {
|
||||
repo.create_branch(new_branch_name.to_string())
|
||||
})?
|
||||
.await??;
|
||||
repo.update(cx, |repo, _| {
|
||||
repo.change_branch(new_branch_name.to_string())
|
||||
})?
|
||||
.await??;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.detach_and_prompt_err("Failed to create branch", window, cx, |e, _, _| {
|
||||
|
@ -359,11 +364,13 @@ impl PickerDelegate for BranchListDelegate {
|
|||
.ok_or_else(|| anyhow!("No active repository"))?
|
||||
.clone();
|
||||
|
||||
let cx = cx.to_async();
|
||||
let mut cx = cx.to_async();
|
||||
|
||||
anyhow::Ok(async move {
|
||||
cx.update(|cx| repo.read(cx).change_branch(branch.name.to_string()))?
|
||||
.await?
|
||||
repo.update(&mut cx, |repo, _| {
|
||||
repo.change_branch(branch.name.to_string())
|
||||
})?
|
||||
.await?
|
||||
})
|
||||
})??;
|
||||
|
||||
|
|
|
@ -53,10 +53,8 @@ use project::{
|
|||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{Settings as _, SettingsStore};
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::{collections::HashSet, sync::Arc, time::Duration, usize};
|
||||
use strum::{IntoEnumIterator, VariantNames};
|
||||
use time::OffsetDateTime;
|
||||
|
@ -64,7 +62,7 @@ use ui::{
|
|||
Checkbox, ContextMenu, ElevationIndex, PopoverMenu, Scrollbar, ScrollbarState, Tooltip,
|
||||
prelude::*,
|
||||
};
|
||||
use util::{ResultExt, TryFutureExt, maybe, post_inc};
|
||||
use util::{ResultExt, TryFutureExt, maybe};
|
||||
use workspace::AppState;
|
||||
|
||||
use notifications::status_toast::{StatusToast, ToastIcon};
|
||||
|
@ -232,8 +230,6 @@ struct PendingOperation {
|
|||
op_id: usize,
|
||||
}
|
||||
|
||||
type RemoteOperations = Rc<RefCell<HashSet<u32>>>;
|
||||
|
||||
// computed state related to how to render scrollbars
|
||||
// one per axis
|
||||
// on render we just read this off the panel
|
||||
|
@ -290,8 +286,6 @@ impl ScrollbarProperties {
|
|||
}
|
||||
|
||||
pub struct GitPanel {
|
||||
remote_operation_id: u32,
|
||||
pending_remote_operations: RemoteOperations,
|
||||
pub(crate) active_repository: Option<Entity<Repository>>,
|
||||
pub(crate) commit_editor: Entity<Editor>,
|
||||
conflicted_count: usize,
|
||||
|
@ -327,17 +321,6 @@ pub struct GitPanel {
|
|||
_settings_subscription: Subscription,
|
||||
}
|
||||
|
||||
struct RemoteOperationGuard {
|
||||
id: u32,
|
||||
pending_remote_operations: RemoteOperations,
|
||||
}
|
||||
|
||||
impl Drop for RemoteOperationGuard {
|
||||
fn drop(&mut self) {
|
||||
self.pending_remote_operations.borrow_mut().remove(&self.id);
|
||||
}
|
||||
}
|
||||
|
||||
const MAX_PANEL_EDITOR_LINES: usize = 6;
|
||||
|
||||
pub(crate) fn commit_message_editor(
|
||||
|
@ -416,7 +399,7 @@ impl GitPanel {
|
|||
) => {
|
||||
this.schedule_update(*full_scan, window, cx);
|
||||
}
|
||||
GitStoreEvent::RepositoryUpdated(_, _, _) => {}
|
||||
|
||||
GitStoreEvent::RepositoryAdded(_) | GitStoreEvent::RepositoryRemoved(_) => {
|
||||
this.schedule_update(false, window, cx);
|
||||
}
|
||||
|
@ -427,6 +410,8 @@ impl GitPanel {
|
|||
})
|
||||
.ok();
|
||||
}
|
||||
GitStoreEvent::RepositoryUpdated(_, _, _) => {}
|
||||
GitStoreEvent::JobsUpdated => {}
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
|
@ -458,8 +443,6 @@ impl GitPanel {
|
|||
});
|
||||
|
||||
let mut git_panel = Self {
|
||||
pending_remote_operations: Default::default(),
|
||||
remote_operation_id: 0,
|
||||
active_repository,
|
||||
commit_editor,
|
||||
conflicted_count: 0,
|
||||
|
@ -671,16 +654,6 @@ impl GitPanel {
|
|||
cx.notify();
|
||||
}
|
||||
|
||||
fn start_remote_operation(&mut self) -> RemoteOperationGuard {
|
||||
let id = post_inc(&mut self.remote_operation_id);
|
||||
self.pending_remote_operations.borrow_mut().insert(id);
|
||||
|
||||
RemoteOperationGuard {
|
||||
id,
|
||||
pending_remote_operations: self.pending_remote_operations.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&mut self, cx: &mut Context<Self>) {
|
||||
let width = self.width;
|
||||
self.pending_serialization = cx.background_spawn(
|
||||
|
@ -1743,7 +1716,6 @@ impl GitPanel {
|
|||
return;
|
||||
};
|
||||
telemetry::event!("Git Fetched");
|
||||
let guard = self.start_remote_operation();
|
||||
let askpass = self.askpass_delegate("git fetch", window, cx);
|
||||
let this = cx.weak_entity();
|
||||
window
|
||||
|
@ -1751,7 +1723,6 @@ impl GitPanel {
|
|||
let fetch = repo.update(cx, |repo, cx| repo.fetch(askpass, cx))?;
|
||||
|
||||
let remote_message = fetch.await?;
|
||||
drop(guard);
|
||||
this.update(cx, |this, cx| {
|
||||
let action = RemoteAction::Fetch;
|
||||
match remote_message {
|
||||
|
@ -1883,16 +1854,11 @@ impl GitPanel {
|
|||
this.askpass_delegate(format!("git pull {}", remote.name), window, cx)
|
||||
})?;
|
||||
|
||||
let guard = this
|
||||
.update(cx, |this, _| this.start_remote_operation())
|
||||
.ok();
|
||||
|
||||
let pull = repo.update(cx, |repo, cx| {
|
||||
repo.pull(branch.name.clone(), remote.name.clone(), askpass, cx)
|
||||
})?;
|
||||
|
||||
let remote_message = pull.await?;
|
||||
drop(guard);
|
||||
|
||||
let action = RemoteAction::Pull(remote);
|
||||
this.update(cx, |this, cx| match remote_message {
|
||||
|
@ -1954,10 +1920,6 @@ impl GitPanel {
|
|||
this.askpass_delegate(format!("git push {}", remote.name), window, cx)
|
||||
})?;
|
||||
|
||||
let guard = this
|
||||
.update(cx, |this, _| this.start_remote_operation())
|
||||
.ok();
|
||||
|
||||
let push = repo.update(cx, |repo, cx| {
|
||||
repo.push(
|
||||
branch.name.clone(),
|
||||
|
@ -1969,7 +1931,6 @@ impl GitPanel {
|
|||
})?;
|
||||
|
||||
let remote_output = push.await?;
|
||||
drop(guard);
|
||||
|
||||
let action = RemoteAction::Push(branch.name, remote);
|
||||
this.update(cx, |this, cx| match remote_output {
|
||||
|
@ -2590,20 +2551,6 @@ impl GitPanel {
|
|||
workspace.add_item_to_center(Box::new(editor), window, cx);
|
||||
}
|
||||
|
||||
pub fn render_spinner(&self) -> Option<impl IntoElement> {
|
||||
(!self.pending_remote_operations.borrow().is_empty()).then(|| {
|
||||
Icon::new(IconName::ArrowCircle)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Info)
|
||||
.with_animation(
|
||||
"arrow-circle",
|
||||
Animation::new(Duration::from_secs(2)).repeat(),
|
||||
|icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
|
||||
)
|
||||
.into_any_element()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn can_commit(&self) -> bool {
|
||||
(self.has_staged_changes() || self.has_tracked_changes()) && !self.has_unstaged_conflicts()
|
||||
}
|
||||
|
@ -2832,12 +2779,10 @@ impl GitPanel {
|
|||
if !self.can_push_and_pull(cx) {
|
||||
return None;
|
||||
}
|
||||
let spinner = self.render_spinner();
|
||||
Some(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.flex_shrink_0()
|
||||
.children(spinner)
|
||||
.when_some(branch, |this, branch| {
|
||||
let focus_handle = Some(self.focus_handle(cx));
|
||||
|
||||
|
@ -4129,17 +4074,17 @@ impl RenderOnce for PanelRepoFooter {
|
|||
.truncate(true)
|
||||
.tooltip(Tooltip::for_action_title(
|
||||
"Switch Branch",
|
||||
&zed_actions::git::Branch,
|
||||
&zed_actions::git::Switch,
|
||||
))
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(zed_actions::git::Branch.boxed_clone(), cx);
|
||||
window.dispatch_action(zed_actions::git::Switch.boxed_clone(), cx);
|
||||
});
|
||||
|
||||
let branch_selector = PopoverMenu::new("popover-button")
|
||||
.menu(move |window, cx| Some(branch_picker::popover(repo.clone(), window, cx)))
|
||||
.trigger_with_tooltip(
|
||||
branch_selector_button,
|
||||
Tooltip::for_action_title("Switch Branch", &zed_actions::git::Branch),
|
||||
Tooltip::for_action_title("Switch Branch", &zed_actions::git::Switch),
|
||||
)
|
||||
.anchor(Corner::BottomLeft)
|
||||
.offset(gpui::Point {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue