fix: Load icon successfully

This commit is contained in:
walterlv 2024-04-08 16:05:37 +08:00
parent f66c6c14a2
commit 0426e24c6e
5 changed files with 106 additions and 49 deletions

View file

@ -5,14 +5,14 @@ using System.IO;
namespace SourceGit.Models namespace SourceGit.Models
{ {
public class ExternalTerminal public record ExternalTerminal
{ {
public string Name { get; set; } = string.Empty; public string Name { get; init; } = string.Empty;
public string Icon { get; set; } = string.Empty; public string Icon { get; init; } = string.Empty;
public string Executable { get; set; } = string.Empty; public string Executable { get; init; } = string.Empty;
public string OpenCmdArgs { get; set; } = string.Empty; public string OpenCmdArgs { get; init; } = string.Empty;
public void Open(string repo) public virtual void Open(string repo)
{ {
Process.Start(new ProcessStartInfo() Process.Start(new ProcessStartInfo()
{ {
@ -34,31 +34,33 @@ namespace SourceGit.Models
public void WindowsGitBash(Func<string> platform_finder) public void WindowsGitBash(Func<string> platform_finder)
{ {
TryAdd("Git Bash", "git-bash.png", "bash", "\"{0}\"", platform_finder); TryAdd("Git Bash", "git-bash.png", "bash", "", platform_finder);
} }
public void Gnome(Func<string> platform_finder) public void Gnome(Func<string> platform_finder)
{ {
TryAdd("gnome-terminal", "gnome.png", "/usr/bin/gnome-terminal", "--working-directory=\"{0}\"", platform_finder); TryAdd("gnome-terminal", "gnome.png", "gnome", "--working-directory=\"{0}\"", platform_finder);
} }
public void Konsole(Func<string> platform_finder) public void Konsole(Func<string> platform_finder)
{ {
TryAdd("gnome-terminal", "konsole.png", "/usr/bin/konsole", "--workdir \"{0}\"", platform_finder); TryAdd("konsole", "konsole.png", "konsole", "--workdir \"{0}\"", platform_finder);
} }
public void osaScript(Func<string> platform_finder) public void AppleScript(ExternalTerminal terminal)
{ {
TryAdd("AppleScript", "osascript.png", "/usr/bin/osascript", var path = terminal.Executable;
"""
on run argv if (string.IsNullOrEmpty(path) || !File.Exists(path))
tell application "Terminal" {
do script "cd '{0}'" return;
activate }
end tell
end run Terminals.Add(terminal with
""", {
platform_finder); Name = "AppleScript",
Icon = "osascript.png",
});
} }
public void PowerShell(Func<string> platform_finder) public void PowerShell(Func<string> platform_finder)
@ -73,7 +75,7 @@ namespace SourceGit.Models
public void Xfce4(Func<string> platform_finder) public void Xfce4(Func<string> platform_finder)
{ {
TryAdd("gnome-terminal", "xfce4.png", "/usr/bin/xfce4-terminal", "--working-directory=\"{0}\"", platform_finder); TryAdd("xfce4", "xfce4.png", "xfce4", "--working-directory=\"{0}\"", platform_finder);
} }
private void TryAdd(string name, string icon, string cmd, string args, Func<string> finder) private void TryAdd(string name, string icon, string cmd, string args, Func<string> finder)

View file

@ -31,7 +31,7 @@ namespace SourceGit.Native
public List<Models.ExternalTerminal> FindExternalTerminals() public List<Models.ExternalTerminal> FindExternalTerminals()
{ {
var finder = new Models.ExternalTerminalFinder(); var finder = new Models.ExternalTerminalFinder();
finder.osaScript(() => "/usr/bin/osascript"); finder.AppleScript(new AppleScriptTerminal());
return finder.Terminals; return finder.Terminals;
} }
@ -64,25 +64,39 @@ namespace SourceGit.Native
public void OpenTerminal(string workdir) public void OpenTerminal(string workdir)
{ {
var dir = string.IsNullOrEmpty(workdir) ? "~" : workdir; new AppleScriptTerminal().Open(workdir);
var builder = new StringBuilder();
builder.AppendLine("on run argv");
builder.AppendLine(" tell application \"Terminal\"");
builder.AppendLine($" do script \"cd '{dir}'\"");
builder.AppendLine(" activate");
builder.AppendLine(" end tell");
builder.AppendLine("end run");
var tmp = Path.GetTempFileName();
File.WriteAllText(tmp, builder.ToString());
var proc = Process.Start("/usr/bin/osascript", $"\"{tmp}\"");
proc.Exited += (o, e) => File.Delete(tmp);
} }
public void OpenWithDefaultEditor(string file) public void OpenWithDefaultEditor(string file)
{ {
Process.Start("open", file); Process.Start("open", file);
} }
private sealed record AppleScriptTerminal : Models.ExternalTerminal
{
public AppleScriptTerminal()
{
Executable = "/usr/bin/osascript";
OpenCmdArgs = "";
}
public override void Open(string repo)
{
var dir = string.IsNullOrEmpty(repo) ? "~" : repo;
var tmp = Path.GetTempFileName();
File.WriteAllText(tmp,
$"""
on run argv
tell application "Terminal"
do script "cd '{dir}'"
activate
end tell
end run
""");
var proc = Process.Start("/usr/bin/osascript", $"\"{tmp}\"");
proc.Exited += (o, e) => File.Delete(tmp);
}
}
} }
} }

View file

@ -346,8 +346,10 @@ namespace SourceGit.ViewModels
foreach (var terminal in terminals) foreach (var terminal in terminals)
{ {
var dupTerminal = terminal; var dupTerminal = terminal;
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalTerminalIcons/{dupTerminal.Icon}", UriKind.RelativeOrAbsolute)); var item = new ExternalMenuItem(
var item = new ExternalMenuItem(App.Text("Repository.OpenIn", dupTerminal.Name), new Bitmap(icon), () => dupTerminal.Open(_fullpath)); App.Text("Repository.OpenIn", dupTerminal.Name),
$"ExternalTerminalIcons/{dupTerminal.Icon}",
() => dupTerminal.Open(_fullpath));
items.Add(item); items.Add(item);
} }
@ -370,8 +372,10 @@ namespace SourceGit.ViewModels
foreach (var editor in editors) foreach (var editor in editors)
{ {
var dupEditor = editor; var dupEditor = editor;
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{dupEditor.Icon}", UriKind.RelativeOrAbsolute)); var item = new ExternalMenuItem(
var item = new ExternalMenuItem(App.Text("Repository.OpenIn", dupEditor.Name), new Bitmap(icon), () => dupEditor.Open(_fullpath)); App.Text("Repository.OpenIn", dupEditor.Name),
$"ExternalToolIcons/{dupEditor.Icon}",
() => dupEditor.Open(_fullpath));
items.Add(item); items.Add(item);
} }
@ -1424,14 +1428,14 @@ namespace SourceGit.ViewModels
public ExternalMenuItem(string header) public ExternalMenuItem(string header)
{ {
Header = header; Header = header;
Icon = null; IconKey = null;
Command = null; Command = null;
} }
public ExternalMenuItem(string header, Bitmap icon, Action click) public ExternalMenuItem(string header, string iconKey, Action click)
{ {
Header = header; Header = header;
Icon = icon; IconKey = iconKey;
Command = new RelayCommand(click); Command = new RelayCommand(click);
} }
@ -1443,7 +1447,7 @@ namespace SourceGit.ViewModels
/// <summary> /// <summary>
/// The resource key of the icon. /// The resource key of the icon.
/// </summary> /// </summary>
public Bitmap? Icon { get; init; } public string? IconKey { get; init; }
/// <summary> /// <summary>
/// The command when the user click the menu item. /// The command when the user click the menu item.
@ -1453,6 +1457,6 @@ namespace SourceGit.ViewModels
/// <summary> /// <summary>
/// <see langword="true"/> if the menu item is enabled; otherwise, <see langword="false"/>. /// <see langword="true"/> if the menu item is enabled; otherwise, <see langword="false"/>.
/// </summary> /// </summary>
public bool IsEnabled { get; init; } public bool IsEnabled { get; init; } = true;
} }
} }

View file

@ -11,12 +11,23 @@
x:DataType="vm:Repository"> x:DataType="vm:Repository">
<UserControl.Resources> <UserControl.Resources>
<MenuFlyout x:Key="TerminalShellsMenuFlyout" Placement="Bottom"> <v:ExternalIconKeyToImageConverter x:Key="IconKeyToImageConverter" />
</MenuFlyout> <MenuFlyout x:Key="TerminalShellsMenuFlyout" Placement="BottomEdgeAlignedLeft"
<MenuFlyout x:Key="ExternalToolsMenuFlyout" Placement="Bottom"> ItemsSource="{Binding ExternalTerminals, Mode=OneTime}" />
</MenuFlyout> <MenuFlyout x:Key="ExternalToolsMenuFlyout" Placement="BottomEdgeAlignedLeft"
ItemsSource="{Binding ExternalEditors, Mode=OneTime}" />
</UserControl.Resources> </UserControl.Resources>
<UserControl.DataTemplates>
<DataTemplate x:DataType="vm:ExternalMenuItem">
<MenuItem Header="{Binding Header, Mode=OneTime}"
Icon="{Binding IconKey, Mode=OneTime, Converter={StaticResource IconKeyToImageConverter}}"
Command="{Binding Command, Mode=OneTime}"
IsEnabled="{Binding IsEnabled, Mode=OneTime}">
</MenuItem>
</DataTemplate>
</UserControl.DataTemplates>
<Grid RowDefinitions="36,*" Background="{DynamicResource Brush.Window}"> <Grid RowDefinitions="36,*" Background="{DynamicResource Brush.Window}">
<!-- Toolbar --> <!-- Toolbar -->
<Border Grid.Row="0" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" Background="{DynamicResource Brush.ToolBar}"> <Border Grid.Row="0" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1" Background="{DynamicResource Brush.ToolBar}">

View file

@ -1,11 +1,15 @@
using System; using System;
using System.Globalization;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Data.Converters;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
namespace SourceGit.Views namespace SourceGit.Views
{ {
@ -301,4 +305,26 @@ namespace SourceGit.Views
} }
} }
} }
public sealed class ExternalIconKeyToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string iconKey && !string.IsNullOrWhiteSpace(iconKey))
{
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/{iconKey}", UriKind.RelativeOrAbsolute));
return new Image
{
Width = 16, Height = 16, Source = new Bitmap(icon),
};
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
} }