11using System ;
22using System . IO ;
3+ using System . Text ;
34
45using Avalonia . Controls ;
56using Avalonia . Input ;
7+ using Avalonia . Platform . Storage ;
68
79namespace SourceGit . Views
810{
@@ -15,61 +17,127 @@ public BranchCompare()
1517
1618 private void OnChangeContextRequested ( object sender , ContextRequestedEventArgs e )
1719 {
18- if ( DataContext is ViewModels . BranchCompare { SelectedChanges : { Count : 1 } selected } vm &&
20+ if ( DataContext is ViewModels . BranchCompare { SelectedChanges : { Count : > 0 } selected } vm &&
1921 sender is ChangeCollectionView view )
2022 {
21- var repo = vm . RepositoryPath ;
22- var change = selected [ 0 ] ;
2323 var menu = new ContextMenu ( ) ;
24+ var repo = vm . RepositoryPath ;
2425
25- var openWithMerger = new MenuItem ( ) ;
26- openWithMerger . Header = App . Text ( "OpenInExternalMergeTool" ) ;
27- openWithMerger . Icon = App . CreateMenuIcon ( "Icons.OpenWith" ) ;
28- openWithMerger . Tag = OperatingSystem . IsMacOS ( ) ? "⌘+⇧+D" : "Ctrl+Shift+D" ;
29- openWithMerger . Click += ( _ , ev ) =>
26+ var patch = new MenuItem ( ) ;
27+ patch . Header = App . Text ( "FileCM.SaveAsPatch" ) ;
28+ patch . Icon = App . CreateMenuIcon ( "Icons.Diff" ) ;
29+ patch . Click += async ( _ , e ) =>
3030 {
31- new Commands . DiffTool ( repo , new Models . DiffOption ( vm . Base . Head , vm . To . Head , change ) ) . Open ( ) ;
32- ev . Handled = true ;
31+ var storageProvider = this . StorageProvider ;
32+ if ( storageProvider == null )
33+ return ;
34+
35+ var options = new FilePickerSaveOptions ( ) ;
36+ options . Title = App . Text ( "FileCM.SaveAsPatch" ) ;
37+ options . DefaultExtension = ".patch" ;
38+ options . FileTypeChoices = [ new FilePickerFileType ( "Patch File" ) { Patterns = [ "*.patch" ] } ] ;
39+
40+ var storageFile = await storageProvider . SaveFilePickerAsync ( options ) ;
41+ if ( storageFile != null )
42+ {
43+ var saveTo = storageFile . Path . LocalPath ;
44+ await vm . SaveChangesAsPatchAsync ( selected , saveTo ) ;
45+ }
46+
47+ e . Handled = true ;
3348 } ;
34- menu . Items . Add ( openWithMerger ) ;
3549
36- if ( change . Index != Models . ChangeState . Deleted )
50+ if ( selected . Count == 1 )
3751 {
38- var full = Path . GetFullPath ( Path . Combine ( repo , change . Path ) ) ;
39- var explore = new MenuItem ( ) ;
40- explore . Header = App . Text ( "RevealFile " ) ;
41- explore . Icon = App . CreateMenuIcon ( "Icons.Explore " ) ;
42- explore . IsEnabled = File . Exists ( full ) ;
43- explore . Click += ( _ , ev ) =>
52+ var change = selected [ 0 ] ;
53+ var openWithMerger = new MenuItem ( ) ;
54+ openWithMerger . Header = App . Text ( "OpenInExternalMergeTool " ) ;
55+ openWithMerger . Icon = App . CreateMenuIcon ( "Icons.OpenWith " ) ;
56+ openWithMerger . Tag = OperatingSystem . IsMacOS ( ) ? "⌘+⇧+D" : "Ctrl+Shift+D" ;
57+ openWithMerger . Click += ( _ , ev ) =>
4458 {
45- Native . OS . OpenInFileManager ( full , true ) ;
59+ new Commands . DiffTool ( repo , new Models . DiffOption ( vm . Base . Head , vm . To . Head , change ) ) . Open ( ) ;
4660 ev . Handled = true ;
4761 } ;
48- menu . Items . Add ( explore ) ;
49- }
62+ menu . Items . Add ( openWithMerger ) ;
5063
51- var copyPath = new MenuItem ( ) ;
52- copyPath . Header = App . Text ( "CopyPath" ) ;
53- copyPath . Icon = App . CreateMenuIcon ( "Icons.Copy" ) ;
54- copyPath . Tag = OperatingSystem . IsMacOS ( ) ? "⌘+C" : "Ctrl+C" ;
55- copyPath . Click += async ( _ , ev ) =>
56- {
57- await App . CopyTextAsync ( change . Path ) ;
58- ev . Handled = true ;
59- } ;
60- menu . Items . Add ( new MenuItem ( ) { Header = "-" } ) ;
61- menu . Items . Add ( copyPath ) ;
62-
63- var copyFullPath = new MenuItem ( ) ;
64- copyFullPath . Header = App . Text ( "CopyFullPath" ) ;
65- copyFullPath . Icon = App . CreateMenuIcon ( "Icons.Copy" ) ;
66- copyFullPath . Tag = OperatingSystem . IsMacOS ( ) ? "⌘+⇧+C" : "Ctrl+Shift+C" ;
67- copyFullPath . Click += async ( _ , ev ) =>
64+ if ( change . Index != Models . ChangeState . Deleted )
65+ {
66+ var full = Path . GetFullPath ( Path . Combine ( repo , change . Path ) ) ;
67+ var explore = new MenuItem ( ) ;
68+ explore . Header = App . Text ( "RevealFile" ) ;
69+ explore . Icon = App . CreateMenuIcon ( "Icons.Explore" ) ;
70+ explore . IsEnabled = File . Exists ( full ) ;
71+ explore . Click += ( _ , ev ) =>
72+ {
73+ Native . OS . OpenInFileManager ( full , true ) ;
74+ ev . Handled = true ;
75+ } ;
76+ menu . Items . Add ( explore ) ;
77+ }
78+
79+ var copyPath = new MenuItem ( ) ;
80+ copyPath . Header = App . Text ( "CopyPath" ) ;
81+ copyPath . Icon = App . CreateMenuIcon ( "Icons.Copy" ) ;
82+ copyPath . Tag = OperatingSystem . IsMacOS ( ) ? "⌘+C" : "Ctrl+C" ;
83+ copyPath . Click += async ( _ , ev ) =>
84+ {
85+ await App . CopyTextAsync ( change . Path ) ;
86+ ev . Handled = true ;
87+ } ;
88+
89+ var copyFullPath = new MenuItem ( ) ;
90+ copyFullPath . Header = App . Text ( "CopyFullPath" ) ;
91+ copyFullPath . Icon = App . CreateMenuIcon ( "Icons.Copy" ) ;
92+ copyFullPath . Tag = OperatingSystem . IsMacOS ( ) ? "⌘+⇧+C" : "Ctrl+Shift+C" ;
93+ copyFullPath . Click += async ( _ , ev ) =>
94+ {
95+ await App . CopyTextAsync ( Native . OS . GetAbsPath ( repo , change . Path ) ) ;
96+ ev . Handled = true ;
97+ } ;
98+
99+ menu . Items . Add ( new MenuItem ( ) { Header = "-" } ) ;
100+ menu . Items . Add ( patch ) ;
101+ menu . Items . Add ( new MenuItem ( ) { Header = "-" } ) ;
102+ menu . Items . Add ( copyPath ) ;
103+ menu . Items . Add ( copyFullPath ) ;
104+ }
105+ else
68106 {
69- await App . CopyTextAsync ( Native . OS . GetAbsPath ( repo , change . Path ) ) ;
70- ev . Handled = true ;
71- } ;
72- menu . Items . Add ( copyFullPath ) ;
107+ var copyPath = new MenuItem ( ) ;
108+ copyPath . Header = App . Text ( "CopyPath" ) ;
109+ copyPath . Icon = App . CreateMenuIcon ( "Icons.Copy" ) ;
110+ copyPath . Tag = OperatingSystem . IsMacOS ( ) ? "⌘+C" : "Ctrl+C" ;
111+ copyPath . Click += async ( _ , ev ) =>
112+ {
113+ var builder = new StringBuilder ( ) ;
114+ foreach ( var c in selected )
115+ builder . AppendLine ( c . Path ) ;
116+
117+ await App . CopyTextAsync ( builder . ToString ( ) ) ;
118+ ev . Handled = true ;
119+ } ;
120+
121+ var copyFullPath = new MenuItem ( ) ;
122+ copyFullPath . Header = App . Text ( "CopyFullPath" ) ;
123+ copyFullPath . Icon = App . CreateMenuIcon ( "Icons.Copy" ) ;
124+ copyFullPath . Tag = OperatingSystem . IsMacOS ( ) ? "⌘+⇧+C" : "Ctrl+Shift+C" ;
125+ copyFullPath . Click += async ( _ , ev ) =>
126+ {
127+ var builder = new StringBuilder ( ) ;
128+ foreach ( var c in selected )
129+ builder . AppendLine ( Native . OS . GetAbsPath ( repo , c . Path ) ) ;
130+
131+ await App . CopyTextAsync ( builder . ToString ( ) ) ;
132+ ev . Handled = true ;
133+ } ;
134+
135+ menu . Items . Add ( patch ) ;
136+ menu . Items . Add ( new MenuItem ( ) { Header = "-" } ) ;
137+ menu . Items . Add ( copyPath ) ;
138+ menu . Items . Add ( copyFullPath ) ;
139+ }
140+
73141 menu . Open ( view ) ;
74142 }
75143
@@ -89,17 +157,24 @@ private async void OnChangeCollectionViewKeyDown(object sender, KeyEventArgs e)
89157 if ( DataContext is not ViewModels . BranchCompare vm )
90158 return ;
91159
92- if ( sender is not ChangeCollectionView { SelectedChanges : { Count : 1 } selectedChanges } )
160+ if ( sender is not ChangeCollectionView { SelectedChanges : { Count : > 0 } selectedChanges } )
93161 return ;
94162
95- var change = selectedChanges [ 0 ] ;
96163 if ( e . KeyModifiers . HasFlag ( OperatingSystem . IsMacOS ( ) ? KeyModifiers . Meta : KeyModifiers . Control ) && e . Key == Key . C )
97164 {
98- if ( e . KeyModifiers . HasFlag ( KeyModifiers . Shift ) )
99- await App . CopyTextAsync ( vm . GetAbsPath ( change . Path ) ) ;
165+ var builder = new StringBuilder ( ) ;
166+ var copyAbsPath = e . KeyModifiers . HasFlag ( KeyModifiers . Shift ) ;
167+ if ( selectedChanges . Count == 1 )
168+ {
169+ builder . Append ( copyAbsPath ? vm . GetAbsPath ( selectedChanges [ 0 ] . Path ) : selectedChanges [ 0 ] . Path ) ;
170+ }
100171 else
101- await App . CopyTextAsync ( change . Path ) ;
172+ {
173+ foreach ( var c in selectedChanges )
174+ builder . AppendLine ( copyAbsPath ? vm . GetAbsPath ( c . Path ) : c . Path ) ;
175+ }
102176
177+ await App . CopyTextAsync ( builder . ToString ( ) ) ;
103178 e . Handled = true ;
104179 }
105180 }
0 commit comments