feature: supports visit remote url in browser

This commit is contained in:
leo 2024-06-17 20:31:54 +08:00
parent 3afb134037
commit ad2fc68c6b
No known key found for this signature in database
GPG key ID: B528468E49CD0E58
6 changed files with 58 additions and 9 deletions

View file

@ -1,4 +1,5 @@
using System.Text.RegularExpressions; using System;
using System.Text.RegularExpressions;
namespace SourceGit.Models namespace SourceGit.Models
{ {
@ -11,6 +12,9 @@ namespace SourceGit.Models
[GeneratedRegex(@"^ssh://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/[\w\-/]+/[\w\-\.]+(\.git)?$")] [GeneratedRegex(@"^ssh://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/[\w\-/]+/[\w\-\.]+(\.git)?$")]
private static partial Regex REG_SSH2(); private static partial Regex REG_SSH2();
[GeneratedRegex(@"^git@([\w\.\-]+):([\w\-/]+/[\w\-\.]+)\.git$")]
private static partial Regex REG_TO_VISIT_URL_CAPTURE();
private static readonly Regex[] URL_FORMATS = [ private static readonly Regex[] URL_FORMATS = [
REG_HTTPS(), REG_HTTPS(),
REG_SSH1(), REG_SSH1(),
@ -43,5 +47,29 @@ namespace SourceGit.Models
} }
return false; return false;
} }
public bool TryGetVisitURL(out string url)
{
url = null;
if (URL.StartsWith("http", StringComparison.Ordinal))
{
if (URL.EndsWith(".git"))
url = URL.Substring(0, URL.Length - 4);
else
url = URL;
return true;
}
var match = REG_TO_VISIT_URL_CAPTURE().Match(URL);
if (match.Success)
{
url = $"https://{match.Groups[1].Value}/{match.Groups[2].Value}";
return true;
}
return false;
}
} }
} }

View file

@ -345,6 +345,8 @@
<x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">Install Path</x:String> <x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">Install Path</x:String>
<x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">Input path for merge tool</x:String> <x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">Input path for merge tool</x:String>
<x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">Merger</x:String> <x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">Merger</x:String>
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Prune Remote</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Target :</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch :</x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branch :</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">Into :</x:String> <x:String x:Key="Text.Pull.Into" xml:space="preserve">Into :</x:String>
@ -383,8 +385,8 @@
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">Delete ...</x:String> <x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">Delete ...</x:String>
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">Edit ...</x:String> <x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">Edit ...</x:String>
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">Fetch ...</x:String> <x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">Fetch ...</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Prune</x:String> <x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">Open In Browser</x:String>
<x:String x:Key="Text.RemoteCM.Prune.Target" xml:space="preserve">Target :</x:String> <x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Prune ...</x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">Rename Branch</x:String> <x:String x:Key="Text.RenameBranch" xml:space="preserve">Rename Branch</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">New Name :</x:String> <x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">New Name :</x:String>
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Unique name for this branch</x:String> <x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Unique name for this branch</x:String>

View file

@ -348,6 +348,8 @@
<x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">安装路径</x:String> <x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">安装路径</x:String>
<x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">填写工具可执行文件所在位置</x:String> <x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">填写工具可执行文件所在位置</x:String>
<x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">工具</x:String> <x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">工具</x:String>
<x:String x:Key="Text.PruneRemote" xml:space="preserve">清理远程已删除分支</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">目标 </x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String> <x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String>
@ -386,8 +388,8 @@
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">删除 ...</x:String> <x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">删除 ...</x:String>
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">编辑 ...</x:String> <x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">编辑 ...</x:String>
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">拉取(fetch)更新 ...</x:String> <x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">拉取(fetch)更新 ...</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">清理远程已删除分支</x:String> <x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">在浏览器中打开</x:String>
<x:String x:Key="Text.RemoteCM.Prune.Target" xml:space="preserve">目标 </x:String> <x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">清理远程已删除分支 ...</x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">分支重命名</x:String> <x:String x:Key="Text.RenameBranch" xml:space="preserve">分支重命名</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">新的名称 </x:String> <x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">新的名称 </x:String>
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能与现有分支名相同</x:String> <x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能与现有分支名相同</x:String>

View file

@ -348,6 +348,8 @@
<x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">安裝路徑</x:String> <x:String x:Key="Text.Preference.Merger.Path" xml:space="preserve">安裝路徑</x:String>
<x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">填寫工具可執行檔案所在位置</x:String> <x:String x:Key="Text.Preference.Merger.Path.Placeholder" xml:space="preserve">填寫工具可執行檔案所在位置</x:String>
<x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">工具</x:String> <x:String x:Key="Text.Preference.Merger.Type" xml:space="preserve">工具</x:String>
<x:String x:Key="Text.PruneRemote" xml:space="preserve">清理遠端已刪除分支</x:String>
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">目標 </x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String> <x:String x:Key="Text.Pull" xml:space="preserve">拉回(pull)</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String> <x:String x:Key="Text.Pull.Branch" xml:space="preserve">拉取分支 </x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String> <x:String x:Key="Text.Pull.Into" xml:space="preserve">本地分支 </x:String>
@ -386,8 +388,8 @@
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">刪除 ...</x:String> <x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">刪除 ...</x:String>
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">編輯 ...</x:String> <x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">編輯 ...</x:String>
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">拉取(fetch)更新 ...</x:String> <x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">拉取(fetch)更新 ...</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">清理遠端已刪除分支</x:String> <x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">在瀏覽器中訪問網址</x:String>
<x:String x:Key="Text.RemoteCM.Prune.Target" xml:space="preserve">目標 </x:String> <x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">清理遠端已刪除分支 ...</x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">分支重新命名</x:String> <x:String x:Key="Text.RenameBranch" xml:space="preserve">分支重新命名</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">新的名稱 </x:String> <x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">新的名稱 </x:String>
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能與現有分支名相同</x:String> <x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">新的分支名不能與現有分支名相同</x:String>

View file

@ -1214,6 +1214,21 @@ namespace SourceGit.ViewModels
{ {
var menu = new ContextMenu(); var menu = new ContextMenu();
if (remote.TryGetVisitURL(out string visitURL))
{
var visit = new MenuItem();
visit.Header = App.Text("RemoteCM.OpenInBrowser");
visit.Icon = App.CreateMenuIcon("Icons.OpenWith");
visit.Click += (o, e) =>
{
Native.OS.OpenBrowser(visitURL);
e.Handled = true;
};
menu.Items.Add(visit);
menu.Items.Add(new MenuItem() { Header = "-" });
}
var fetch = new MenuItem(); var fetch = new MenuItem();
fetch.Header = App.Text("RemoteCM.Fetch"); fetch.Header = App.Text("RemoteCM.Fetch");
fetch.Icon = App.CreateMenuIcon("Icons.Fetch"); fetch.Icon = App.CreateMenuIcon("Icons.Fetch");

View file

@ -9,9 +9,9 @@
<StackPanel Orientation="Vertical" Margin="8,0"> <StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18" <TextBlock FontSize="18"
Classes="bold" Classes="bold"
Text="{DynamicResource Text.RemoteCM.Prune}"/> Text="{DynamicResource Text.PruneRemote}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0">
<TextBlock Text="{DynamicResource Text.RemoteCM.Prune.Target}"/> <TextBlock Text="{DynamicResource Text.PruneRemote.Target}"/>
<Path Width="14" Height="14" Margin="8,6,8,0" Data="{StaticResource Icons.Remote}"/> <Path Width="14" Height="14" Margin="8,6,8,0" Data="{StaticResource Icons.Remote}"/>
<TextBlock Text="{Binding Remote.Name}"/> <TextBlock Text="{Binding Remote.Name}"/>
</StackPanel> </StackPanel>