1
1
use crate :: askpass_modal:: AskPassModal ;
2
2
use crate :: commit_modal:: CommitModal ;
3
3
use crate :: git_panel_settings:: StatusStyle ;
4
+ use crate :: project_diff:: Diff ;
4
5
use crate :: remote_output_toast:: { RemoteAction , RemoteOutputToast } ;
5
6
use crate :: repository_selector:: filtered_repository_entries;
6
7
use crate :: { branch_picker, render_remote_button} ;
@@ -231,6 +232,7 @@ pub struct GitPanel {
231
232
fs : Arc < dyn Fs > ,
232
233
hide_scrollbar_task : Option < Task < ( ) > > ,
233
234
new_count : usize ,
235
+ entry_count : usize ,
234
236
new_staged_count : usize ,
235
237
pending : Vec < PendingOperation > ,
236
238
pending_commit : Option < Task < ( ) > > ,
@@ -381,6 +383,7 @@ impl GitPanel {
381
383
context_menu : None ,
382
384
workspace,
383
385
modal_open : false ,
386
+ entry_count : 0 ,
384
387
} ;
385
388
git_panel. schedule_update ( false , window, cx) ;
386
389
git_panel. show_scrollbar = git_panel. should_show_scrollbar ( cx) ;
@@ -1078,7 +1081,7 @@ impl GitPanel {
1078
1081
} ) ;
1079
1082
}
1080
1083
1081
- fn stage_all ( & mut self , _: & StageAll , _window : & mut Window , cx : & mut Context < Self > ) {
1084
+ pub fn stage_all ( & mut self , _: & StageAll , _window : & mut Window , cx : & mut Context < Self > ) {
1082
1085
let entries = self
1083
1086
. entries
1084
1087
. iter ( )
@@ -1089,7 +1092,7 @@ impl GitPanel {
1089
1092
self . change_file_stage ( true , entries, cx) ;
1090
1093
}
1091
1094
1092
- fn unstage_all ( & mut self , _: & UnstageAll , _window : & mut Window , cx : & mut Context < Self > ) {
1095
+ pub fn unstage_all ( & mut self , _: & UnstageAll , _window : & mut Window , cx : & mut Context < Self > ) {
1093
1096
let entries = self
1094
1097
. entries
1095
1098
. iter ( )
@@ -2137,10 +2140,12 @@ impl GitPanel {
2137
2140
self . tracked_count = 0 ;
2138
2141
self . new_staged_count = 0 ;
2139
2142
self . tracked_staged_count = 0 ;
2143
+ self . entry_count = 0 ;
2140
2144
for entry in & self . entries {
2141
2145
let Some ( status_entry) = entry. status_entry ( ) else {
2142
2146
continue ;
2143
2147
} ;
2148
+ self . entry_count += 1 ;
2144
2149
if repo. has_conflict ( & status_entry. repo_path ) {
2145
2150
self . conflicted_count += 1 ;
2146
2151
if self . entry_staging ( status_entry) . has_staged ( ) {
@@ -2402,6 +2407,43 @@ impl GitPanel {
2402
2407
} )
2403
2408
}
2404
2409
2410
+ fn render_panel_header ( & self , window : & mut Window , cx : & mut Context < Self > ) -> impl IntoElement {
2411
+ let text;
2412
+ let action;
2413
+ let tooltip;
2414
+ if self . total_staged_count ( ) == self . entry_count {
2415
+ text = "Unstage All" ;
2416
+ action = git:: UnstageAll . boxed_clone ( ) ;
2417
+ tooltip = "git reset" ;
2418
+ } else {
2419
+ text = "Stage All" ;
2420
+ action = git:: StageAll . boxed_clone ( ) ;
2421
+ tooltip = "git add --all ."
2422
+ }
2423
+
2424
+ self . panel_header_container ( window, cx)
2425
+ . child (
2426
+ Button :: new ( "diff" , "Open diff" )
2427
+ . tooltip ( Tooltip :: for_action_title ( "Open diff" , & Diff ) )
2428
+ . on_click ( |_, _, cx| {
2429
+ cx. defer ( |cx| {
2430
+ cx. dispatch_action ( & Diff ) ;
2431
+ } )
2432
+ } ) ,
2433
+ )
2434
+ . child ( div ( ) . flex_grow ( ) ) // spacer
2435
+ . child (
2436
+ Button :: new ( "stage-unstage-all" , text)
2437
+ . tooltip ( Tooltip :: for_action_title ( tooltip, action. as_ref ( ) ) )
2438
+ . on_click ( move |_, _, cx| {
2439
+ let action = action. boxed_clone ( ) ;
2440
+ cx. defer ( move |cx| {
2441
+ cx. dispatch_action ( action. as_ref ( ) ) ;
2442
+ } )
2443
+ } ) ,
2444
+ )
2445
+ }
2446
+
2405
2447
pub fn render_footer (
2406
2448
& self ,
2407
2449
window : & mut Window ,
@@ -3166,6 +3208,7 @@ impl Render for GitPanel {
3166
3208
. child (
3167
3209
v_flex ( )
3168
3210
. size_full ( )
3211
+ . child ( self . render_panel_header ( window, cx) )
3169
3212
. map ( |this| {
3170
3213
if has_entries {
3171
3214
this. child ( self . render_entries ( has_write_access, window, cx) )
0 commit comments