feature: add a button to open current revision file with default editor

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-06-17 12:20:02 +08:00
parent e102e49f45
commit efa6e46471
No known key found for this signature in database
3 changed files with 48 additions and 7 deletions

View file

@ -133,6 +133,12 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _revisionFileSearchSuggestion, value); private set => SetProperty(ref _revisionFileSearchSuggestion, value);
} }
public bool CanOpenRevisionFileWithDefaultEditor
{
get => _canOpenRevisionFileWithDefaultEditor;
private set => SetProperty(ref _canOpenRevisionFileWithDefaultEditor, value);
}
public CommitDetail(Repository repo) public CommitDetail(Repository repo)
{ {
_repo = repo; _repo = repo;
@ -197,6 +203,7 @@ namespace SourceGit.ViewModels
{ {
ViewRevisionFilePath = string.Empty; ViewRevisionFilePath = string.Empty;
ViewRevisionFileContent = null; ViewRevisionFileContent = null;
CanOpenRevisionFileWithDefaultEditor = false;
return; return;
} }
@ -205,6 +212,7 @@ namespace SourceGit.ViewModels
switch (file.Type) switch (file.Type)
{ {
case Models.ObjectType.Blob: case Models.ObjectType.Blob:
CanOpenRevisionFileWithDefaultEditor = true;
Task.Run(() => Task.Run(() =>
{ {
var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result(); var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result();
@ -252,6 +260,7 @@ namespace SourceGit.ViewModels
}); });
break; break;
case Models.ObjectType.Commit: case Models.ObjectType.Commit:
CanOpenRevisionFileWithDefaultEditor = false;
Task.Run(() => Task.Run(() =>
{ {
var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/'); var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/');
@ -267,11 +276,26 @@ namespace SourceGit.ViewModels
}); });
break; break;
default: default:
CanOpenRevisionFileWithDefaultEditor = false;
ViewRevisionFileContent = null; ViewRevisionFileContent = null;
break; break;
} }
} }
public Task OpenRevisionFileWithDefaultEditor(string file)
{
return Task.Run(() =>
{
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file);
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
var fileExt = Path.GetExtension(fullPath) ?? "";
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file, tmpFile);
Native.OS.OpenWithDefaultEditor(tmpFile);
});
}
public ContextMenu CreateChangeContextMenu(Models.Change change) public ContextMenu CreateChangeContextMenu(Models.Change change)
{ {
var diffWithMerger = new MenuItem(); var diffWithMerger = new MenuItem();
@ -421,13 +445,10 @@ namespace SourceGit.ViewModels
var openWith = new MenuItem(); var openWith = new MenuItem();
openWith.Header = App.Text("OpenWith"); openWith.Header = App.Text("OpenWith");
openWith.Icon = App.CreateMenuIcon("Icons.OpenWith"); openWith.Icon = App.CreateMenuIcon("Icons.OpenWith");
openWith.IsEnabled = file.Type == Models.ObjectType.Blob;
openWith.Click += async (_, ev) => openWith.Click += async (_, ev) =>
{ {
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? ""; await OpenRevisionFileWithDefaultEditor(file.Path);
var fileExt = Path.GetExtension(fullPath) ?? "";
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
await Task.Run(() => Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, tmpFile));
Native.OS.OpenWithDefaultEditor(tmpFile);
ev.Handled = true; ev.Handled = true;
}; };
@ -887,5 +908,6 @@ namespace SourceGit.ViewModels
private List<string> _revisionFiles = null; private List<string> _revisionFiles = null;
private string _revisionFileSearchFilter = string.Empty; private string _revisionFileSearchFilter = string.Empty;
private List<string> _revisionFileSearchSuggestion = null; private List<string> _revisionFileSearchSuggestion = null;
private bool _canOpenRevisionFileWithDefaultEditor = false;
} }
} }

View file

@ -119,7 +119,7 @@
Height="26" Height="26"
BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1"
IsVisible="{Binding ViewRevisionFilePath, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"> IsVisible="{Binding ViewRevisionFilePath, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
<Grid ColumnDefinitions="Auto,*,Auto"> <Grid ColumnDefinitions="Auto,*,Auto,Auto">
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.File}" Margin="8,0,0,0"/> <Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.File}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="1" <TextBlock Grid.Column="1"
Classes="primary" Classes="primary"
@ -140,8 +140,18 @@
Converter="{x:Static c:ObjectConverters.IsTypeOf}" Converter="{x:Static c:ObjectConverters.IsTypeOf}"
ConverterParameter="{x:Type m:RevisionTextFile}"/> ConverterParameter="{x:Type m:RevisionTextFile}"/>
</ToggleButton.IsVisible> </ToggleButton.IsVisible>
<Path Width="13" Height="13" Data="{StaticResource Icons.SyntaxHighlight}" Margin="0,3,0,0"/> <Path Width="13" Height="13" Data="{StaticResource Icons.SyntaxHighlight}" Margin="0,2,0,0"/>
</ToggleButton> </ToggleButton>
<Button Grid.Column="3"
Classes="icon_button"
Width="28"
Background="Transparent"
Click="OnOpenFileWithDefaultEditor"
IsVisible="{Binding CanOpenRevisionFileWithDefaultEditor, Mode=OneWay}"
ToolTip.Tip="{DynamicResource Text.OpenWith}">
<Path Width="12" Height="12" Data="{StaticResource Icons.OpenWith}"/>
</Button>
</Grid> </Grid>
</Border> </Border>

View file

@ -1,5 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
{ {
@ -80,5 +81,13 @@ namespace SourceGit.Views
e.Handled = true; e.Handled = true;
} }
private async void OnOpenFileWithDefaultEditor(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.CommitDetail { CanOpenRevisionFileWithDefaultEditor: true } vm)
await vm.OpenRevisionFileWithDefaultEditor(vm.ViewRevisionFilePath);
e.Handled = true;
}
} }
} }