mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-06-15 15:44:59 +00:00
Merge branch 'release/v2025.21'
This commit is contained in:
commit
932baeec53
95 changed files with 1359 additions and 693 deletions
|
@ -56,7 +56,7 @@ You can find the current translation status in [TRANSLATION.md](https://github.c
|
||||||
|
|
||||||
**To use this tool, you need to install Git(>=2.25.1) first.**
|
**To use this tool, you need to install Git(>=2.25.1) first.**
|
||||||
|
|
||||||
You can download the latest stable from [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) or download workflow artifacts from [Github Actions](https://github.com/sourcegit-scm/sourcegit/actions) to try this app based on latest commits.
|
You can download the latest stable from [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) or download workflow artifacts from [GitHub Actions](https://github.com/sourcegit-scm/sourcegit/actions) to try this app based on latest commits.
|
||||||
|
|
||||||
This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationData}/SourceGit"`, which is platform-dependent, to store user settings, downloaded avatars and crash logs.
|
This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationData}/SourceGit"`, which is platform-dependent, to store user settings, downloaded avatars and crash logs.
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ For **macOS** users:
|
||||||
brew tap ybeapps/homebrew-sourcegit
|
brew tap ybeapps/homebrew-sourcegit
|
||||||
brew install --cask --no-quarantine sourcegit
|
brew install --cask --no-quarantine sourcegit
|
||||||
```
|
```
|
||||||
* If you want to install `SourceGit.app` from Github Release manually, you need run following command to make sure it works:
|
* If you want to install `SourceGit.app` from GitHub Release manually, you need run following command to make sure it works:
|
||||||
```shell
|
```shell
|
||||||
sudo xattr -cr /Applications/SourceGit.app
|
sudo xattr -cr /Applications/SourceGit.app
|
||||||
```
|
```
|
||||||
|
|
|
@ -6,11 +6,12 @@ This document shows the translation status of each locale file in the repository
|
||||||
|
|
||||||
### 
|
### 
|
||||||
|
|
||||||
### 
|
### 
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing keys in de_DE.axaml</summary>
|
<summary>Missing keys in de_DE.axaml</summary>
|
||||||
|
|
||||||
|
- Text.Avatar.Load
|
||||||
- Text.BranchCM.ResetToSelectedCommit
|
- Text.BranchCM.ResetToSelectedCommit
|
||||||
- Text.CommitDetail.Changes.Count
|
- Text.CommitDetail.Changes.Count
|
||||||
- Text.CreateBranch.OverwriteExisting
|
- Text.CreateBranch.OverwriteExisting
|
||||||
|
@ -42,13 +43,21 @@ This document shows the translation status of each locale file in the repository
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 
|
### 
|
||||||
|
|
||||||
### 
|
<details>
|
||||||
|
<summary>Missing keys in es_ES.axaml</summary>
|
||||||
|
|
||||||
|
- Text.Avatar.Load
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### 
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing keys in fr_FR.axaml</summary>
|
<summary>Missing keys in fr_FR.axaml</summary>
|
||||||
|
|
||||||
|
- Text.Avatar.Load
|
||||||
- Text.Bisect
|
- Text.Bisect
|
||||||
- Text.Bisect.Abort
|
- Text.Bisect.Abort
|
||||||
- Text.Bisect.Bad
|
- Text.Bisect.Bad
|
||||||
|
@ -113,11 +122,12 @@ This document shows the translation status of each locale file in the repository
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 
|
### 
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing keys in it_IT.axaml</summary>
|
<summary>Missing keys in it_IT.axaml</summary>
|
||||||
|
|
||||||
|
- Text.Avatar.Load
|
||||||
- Text.BranchCM.ResetToSelectedCommit
|
- Text.BranchCM.ResetToSelectedCommit
|
||||||
- Text.CommitDetail.Changes.Count
|
- Text.CommitDetail.Changes.Count
|
||||||
- Text.CreateBranch.OverwriteExisting
|
- Text.CreateBranch.OverwriteExisting
|
||||||
|
@ -144,6 +154,7 @@ This document shows the translation status of each locale file in the repository
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing keys in ja_JP.axaml</summary>
|
<summary>Missing keys in ja_JP.axaml</summary>
|
||||||
|
|
||||||
|
- Text.Avatar.Load
|
||||||
- Text.Bisect
|
- Text.Bisect
|
||||||
- Text.Bisect.Abort
|
- Text.Bisect.Abort
|
||||||
- Text.Bisect.Bad
|
- Text.Bisect.Bad
|
||||||
|
@ -185,7 +196,6 @@ This document shows the translation status of each locale file in the repository
|
||||||
- Text.Repository.FilterCommits
|
- Text.Repository.FilterCommits
|
||||||
- Text.Repository.Search.ByContent
|
- Text.Repository.Search.ByContent
|
||||||
- Text.Repository.ShowSubmodulesAsTree
|
- Text.Repository.ShowSubmodulesAsTree
|
||||||
- Text.Repository.Tags.OrderByNameDes
|
|
||||||
- Text.Repository.ViewLogs
|
- Text.Repository.ViewLogs
|
||||||
- Text.Repository.Visit
|
- Text.Repository.Visit
|
||||||
- Text.ResetWithoutCheckout
|
- Text.ResetWithoutCheckout
|
||||||
|
@ -222,6 +232,7 @@ This document shows the translation status of each locale file in the repository
|
||||||
- Text.ApplyStash.DropAfterApply
|
- Text.ApplyStash.DropAfterApply
|
||||||
- Text.ApplyStash.RestoreIndex
|
- Text.ApplyStash.RestoreIndex
|
||||||
- Text.ApplyStash.Stash
|
- Text.ApplyStash.Stash
|
||||||
|
- Text.Avatar.Load
|
||||||
- Text.Bisect
|
- Text.Bisect
|
||||||
- Text.Bisect.Abort
|
- Text.Bisect.Abort
|
||||||
- Text.Bisect.Bad
|
- Text.Bisect.Bad
|
||||||
|
@ -308,8 +319,7 @@ This document shows the translation status of each locale file in the repository
|
||||||
- Text.Repository.ShowSubmodulesAsTree
|
- Text.Repository.ShowSubmodulesAsTree
|
||||||
- Text.Repository.Skip
|
- Text.Repository.Skip
|
||||||
- Text.Repository.Tags.OrderByCreatorDate
|
- Text.Repository.Tags.OrderByCreatorDate
|
||||||
- Text.Repository.Tags.OrderByNameAsc
|
- Text.Repository.Tags.OrderByName
|
||||||
- Text.Repository.Tags.OrderByNameDes
|
|
||||||
- Text.Repository.Tags.Sort
|
- Text.Repository.Tags.Sort
|
||||||
- Text.Repository.UseRelativeTimeInHistories
|
- Text.Repository.UseRelativeTimeInHistories
|
||||||
- Text.Repository.ViewLogs
|
- Text.Repository.ViewLogs
|
||||||
|
@ -347,22 +357,14 @@ This document shows the translation status of each locale file in the repository
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 
|
### 
|
||||||
|
|
||||||
<details>
|
### 
|
||||||
<summary>Missing keys in ru_RU.axaml</summary>
|
|
||||||
|
|
||||||
- Text.BranchCM.CompareWithCurrent
|
|
||||||
- Text.Repository.ClearStashes
|
|
||||||
- Text.WorkingCopy.ResetAuthor
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
### 
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing keys in ta_IN.axaml</summary>
|
<summary>Missing keys in ta_IN.axaml</summary>
|
||||||
|
|
||||||
|
- Text.Avatar.Load
|
||||||
- Text.Bisect
|
- Text.Bisect
|
||||||
- Text.Bisect.Abort
|
- Text.Bisect.Abort
|
||||||
- Text.Bisect.Bad
|
- Text.Bisect.Bad
|
||||||
|
@ -428,11 +430,12 @@ This document shows the translation status of each locale file in the repository
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 
|
### 
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Missing keys in uk_UA.axaml</summary>
|
<summary>Missing keys in uk_UA.axaml</summary>
|
||||||
|
|
||||||
|
- Text.Avatar.Load
|
||||||
- Text.Bisect
|
- Text.Bisect
|
||||||
- Text.Bisect.Abort
|
- Text.Bisect.Abort
|
||||||
- Text.Bisect.Bad
|
- Text.Bisect.Bad
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2025.20
|
2025.21
|
|
@ -12,4 +12,4 @@
|
||||||
dotnet publish -c Release -r $RUNTIME_IDENTIFIER -o $DESTINATION_FOLDER src/SourceGit.csproj
|
dotnet publish -c Release -r $RUNTIME_IDENTIFIER -o $DESTINATION_FOLDER src/SourceGit.csproj
|
||||||
```
|
```
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> Please replace the `$RUNTIME_IDENTIFIER` with one of `win-x64`,`win-arm64`,`linux-x64`,`linux-arm64`,`osx-x64`,`osx-arm64`, and replece the `$DESTINATION_FOLDER` with the real path that will store the output executable files.
|
> Please replace the `$RUNTIME_IDENTIFIER` with one of `win-x64`,`win-arm64`,`linux-x64`,`linux-arm64`,`osx-x64`,`osx-arm64`, and replace the `$DESTINATION_FOLDER` with the real path that will store the output executable files.
|
||||||
|
|
|
@ -338,7 +338,7 @@ namespace SourceGit
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ViewModels.Launcher GetLauncer()
|
public static ViewModels.Launcher GetLauncher()
|
||||||
{
|
{
|
||||||
return Current is App app ? app._launcher : null;
|
return Current is App app ? app._launcher : null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<!-- This manifest is used on Windows only.
|
<!-- This manifest is used on Windows only.
|
||||||
Don't remove it as it might cause problems with window transparency and embeded controls.
|
Don't remove it as it might cause problems with window transparency and embedded controls.
|
||||||
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
|
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
|
||||||
<assemblyIdentity version="1.0.0.0" name="SourceGit.Desktop"/>
|
<assemblyIdentity version="1.0.0.0" name="SourceGit.Desktop"/>
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
private readonly Models.BlameData _result = new Models.BlameData();
|
private readonly Models.BlameData _result = new Models.BlameData();
|
||||||
private readonly StringBuilder _content = new StringBuilder();
|
private readonly StringBuilder _content = new StringBuilder();
|
||||||
private readonly string _dateFormat = Models.DateTimeFormat.Actived.DateOnly;
|
private readonly string _dateFormat = Models.DateTimeFormat.Active.DateOnly;
|
||||||
private string _lastSHA = string.Empty;
|
private string _lastSHA = string.Empty;
|
||||||
private bool _needUnifyCommitSHA = false;
|
private bool _needUnifyCommitSHA = false;
|
||||||
private int _minSHALen = 64;
|
private int _minSHALen = 64;
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
if (!File.Exists(toolPath))
|
if (!File.Exists(toolPath))
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(() => App.RaiseException(repo, $"Can NOT found external merge tool in '{toolPath}'!"));
|
Dispatcher.UIThread.Post(() => App.RaiseException(repo, $"Can NOT find external merge tool in '{toolPath}'!"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
if (!File.Exists(toolPath))
|
if (!File.Exists(toolPath))
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, $"Can NOT found external diff tool in '{toolPath}'!"));
|
Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, $"Can NOT find external diff tool in '{toolPath}'!"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,5 +35,39 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Stream FromLFS(string repo, string oid, long size)
|
||||||
|
{
|
||||||
|
var starter = new ProcessStartInfo();
|
||||||
|
starter.WorkingDirectory = repo;
|
||||||
|
starter.FileName = Native.OS.GitExecutable;
|
||||||
|
starter.Arguments = $"lfs smudge";
|
||||||
|
starter.UseShellExecute = false;
|
||||||
|
starter.CreateNoWindow = true;
|
||||||
|
starter.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
|
starter.RedirectStandardInput = true;
|
||||||
|
starter.RedirectStandardOutput = true;
|
||||||
|
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var proc = new Process() { StartInfo = starter };
|
||||||
|
proc.Start();
|
||||||
|
proc.StandardInput.WriteLine("version https://git-lfs.github.com/spec/v1");
|
||||||
|
proc.StandardInput.WriteLine($"oid sha256:{oid}");
|
||||||
|
proc.StandardInput.WriteLine($"size {size}");
|
||||||
|
proc.StandardOutput.BaseStream.CopyTo(stream);
|
||||||
|
proc.WaitForExit();
|
||||||
|
proc.Close();
|
||||||
|
|
||||||
|
stream.Position = 0;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
App.RaiseException(repo, $"Failed to query file content: {e}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,8 @@ namespace SourceGit.Commands
|
||||||
var isLFSFiltered = new IsLFSFiltered(repo, revision, file).Result();
|
var isLFSFiltered = new IsLFSFiltered(repo, revision, file).Result();
|
||||||
if (isLFSFiltered)
|
if (isLFSFiltered)
|
||||||
{
|
{
|
||||||
var tmpFile = saveTo + ".tmp";
|
var pointerStream = QueryFileContent.Run(repo, revision, file);
|
||||||
if (ExecCmd(repo, $"show {revision}:\"{file}\"", tmpFile))
|
ExecCmd(repo, $"lfs smudge", saveTo, pointerStream);
|
||||||
{
|
|
||||||
ExecCmd(repo, $"lfs smudge", saveTo, tmpFile);
|
|
||||||
}
|
|
||||||
File.Delete(tmpFile);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -26,7 +22,7 @@ namespace SourceGit.Commands
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ExecCmd(string repo, string args, string outputFile, string inputFile = null)
|
private static bool ExecCmd(string repo, string args, string outputFile, Stream input = null)
|
||||||
{
|
{
|
||||||
var starter = new ProcessStartInfo();
|
var starter = new ProcessStartInfo();
|
||||||
starter.WorkingDirectory = repo;
|
starter.WorkingDirectory = repo;
|
||||||
|
@ -45,21 +41,8 @@ namespace SourceGit.Commands
|
||||||
{
|
{
|
||||||
var proc = new Process() { StartInfo = starter };
|
var proc = new Process() { StartInfo = starter };
|
||||||
proc.Start();
|
proc.Start();
|
||||||
|
if (input != null)
|
||||||
if (inputFile != null)
|
proc.StandardInput.Write(new StreamReader(input).ReadToEnd());
|
||||||
{
|
|
||||||
using (StreamReader sr = new StreamReader(inputFile))
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
var line = sr.ReadLine();
|
|
||||||
if (line == null)
|
|
||||||
break;
|
|
||||||
proc.StandardInput.WriteLine(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc.StandardOutput.BaseStream.CopyTo(sw);
|
proc.StandardOutput.BaseStream.CopyTo(sw);
|
||||||
proc.WaitForExit();
|
proc.WaitForExit();
|
||||||
var rs = proc.ExitCode == 0;
|
var rs = proc.ExitCode == 0;
|
||||||
|
|
27
src/Converters/ObjectConverters.cs
Normal file
27
src/Converters/ObjectConverters.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using Avalonia.Data.Converters;
|
||||||
|
|
||||||
|
namespace SourceGit.Converters
|
||||||
|
{
|
||||||
|
public static class ObjectConverters
|
||||||
|
{
|
||||||
|
public class IsTypeOfConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value == null || parameter == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return value.GetType().IsAssignableTo((Type)parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly IsTypeOfConverter IsTypeOf = new IsTypeOfConverter();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ namespace SourceGit.Models
|
||||||
{
|
{
|
||||||
public interface IAvatarHost
|
public interface IAvatarHost
|
||||||
{
|
{
|
||||||
void OnAvatarResourceChanged(string email);
|
void OnAvatarResourceChanged(string email, Bitmap image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class AvatarManager
|
public partial class AvatarManager
|
||||||
|
@ -119,7 +119,7 @@ namespace SourceGit.Models
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
_resources[email] = img;
|
_resources[email] = img;
|
||||||
NotifyResourceChanged(email);
|
NotifyResourceChanged(email, img);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ namespace SourceGit.Models
|
||||||
if (File.Exists(localFile))
|
if (File.Exists(localFile))
|
||||||
File.Delete(localFile);
|
File.Delete(localFile);
|
||||||
|
|
||||||
NotifyResourceChanged(email);
|
NotifyResourceChanged(email, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -186,6 +186,37 @@ namespace SourceGit.Models
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetFromLocal(string email, string file)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Bitmap image = null;
|
||||||
|
|
||||||
|
using (var stream = File.OpenRead(file))
|
||||||
|
{
|
||||||
|
image = Bitmap.DecodeToWidth(stream, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_resources.ContainsKey(email))
|
||||||
|
_resources[email] = image;
|
||||||
|
else
|
||||||
|
_resources.Add(email, image);
|
||||||
|
|
||||||
|
_requesting.Remove(email);
|
||||||
|
|
||||||
|
var store = Path.Combine(_storePath, GetEmailHash(email));
|
||||||
|
File.Copy(file, store, true);
|
||||||
|
NotifyResourceChanged(email, image);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void LoadDefaultAvatar(string key, string img)
|
private void LoadDefaultAvatar(string key, string img)
|
||||||
{
|
{
|
||||||
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/{img}", UriKind.RelativeOrAbsolute));
|
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/{img}", UriKind.RelativeOrAbsolute));
|
||||||
|
@ -203,12 +234,10 @@ namespace SourceGit.Models
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NotifyResourceChanged(string email)
|
private void NotifyResourceChanged(string email, Bitmap image)
|
||||||
{
|
{
|
||||||
foreach (var avatar in _avatars)
|
foreach (var avatar in _avatars)
|
||||||
{
|
avatar.OnAvatarResourceChanged(email, image);
|
||||||
avatar.OnAvatarResourceChanged(email);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,14 +33,14 @@ namespace SourceGit.Models
|
||||||
public User Committer { get; set; } = User.Invalid;
|
public User Committer { get; set; } = User.Invalid;
|
||||||
public ulong CommitterTime { get; set; } = 0;
|
public ulong CommitterTime { get; set; } = 0;
|
||||||
public string Subject { get; set; } = string.Empty;
|
public string Subject { get; set; } = string.Empty;
|
||||||
public List<string> Parents { get; set; } = new List<string>();
|
public List<string> Parents { get; set; } = new();
|
||||||
public List<Decorator> Decorators { get; set; } = new List<Decorator>();
|
public List<Decorator> Decorators { get; set; } = new();
|
||||||
public bool HasDecorators => Decorators.Count > 0;
|
public bool HasDecorators => Decorators.Count > 0;
|
||||||
|
|
||||||
public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
|
public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
|
||||||
public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
|
public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
|
||||||
public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly);
|
public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
|
||||||
public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly);
|
public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
|
||||||
|
|
||||||
public bool IsMerged { get; set; } = false;
|
public bool IsMerged { get; set; } = false;
|
||||||
public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime;
|
public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime;
|
||||||
|
@ -49,7 +49,7 @@ namespace SourceGit.Models
|
||||||
public int Color { get; set; } = 0;
|
public int Color { get; set; } = 0;
|
||||||
public double Opacity => IsMerged ? 1 : OpacityForNotMerged;
|
public double Opacity => IsMerged ? 1 : OpacityForNotMerged;
|
||||||
public FontWeight FontWeight => IsCurrentHead ? FontWeight.Bold : FontWeight.Regular;
|
public FontWeight FontWeight => IsCurrentHead ? FontWeight.Bold : FontWeight.Regular;
|
||||||
public Thickness Margin { get; set; } = new Thickness(0);
|
public Thickness Margin { get; set; } = new(0);
|
||||||
public IBrush Brush => CommitGraph.Pens[Color].Brush;
|
public IBrush Brush => CommitGraph.Pens[Color].Brush;
|
||||||
|
|
||||||
public void ParseDecorators(string data)
|
public void ParseDecorators(string data)
|
||||||
|
@ -121,6 +121,6 @@ namespace SourceGit.Models
|
||||||
public class CommitFullMessage
|
public class CommitFullMessage
|
||||||
{
|
{
|
||||||
public string Message { get; set; } = string.Empty;
|
public string Message { get; set; } = string.Empty;
|
||||||
public List<InlineElement> Inlines { get; set; } = [];
|
public InlineElementCollector Inlines { get; set; } = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace SourceGit.Models
|
||||||
set;
|
set;
|
||||||
} = 0;
|
} = 0;
|
||||||
|
|
||||||
public static DateTimeFormat Actived
|
public static DateTimeFormat Active
|
||||||
{
|
{
|
||||||
get => Supported[ActiveIndex];
|
get => Supported[ActiveIndex];
|
||||||
}
|
}
|
||||||
|
|
9
src/Models/ImageDecoder.cs
Normal file
9
src/Models/ImageDecoder.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace SourceGit.Models
|
||||||
|
{
|
||||||
|
public enum ImageDecoder
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Builtin,
|
||||||
|
Pfim
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,7 @@
|
||||||
{
|
{
|
||||||
public enum InlineElementType
|
public enum InlineElementType
|
||||||
{
|
{
|
||||||
None = 0,
|
Keyword = 0,
|
||||||
Keyword,
|
|
||||||
Link,
|
Link,
|
||||||
CommitSHA,
|
CommitSHA,
|
||||||
Code,
|
Code,
|
||||||
|
@ -11,10 +10,10 @@
|
||||||
|
|
||||||
public class InlineElement
|
public class InlineElement
|
||||||
{
|
{
|
||||||
public InlineElementType Type { get; set; } = InlineElementType.None;
|
public InlineElementType Type { get; }
|
||||||
public int Start { get; set; } = 0;
|
public int Start { get; }
|
||||||
public int Length { get; set; } = 0;
|
public int Length { get; }
|
||||||
public string Link { get; set; } = "";
|
public string Link { get; }
|
||||||
|
|
||||||
public InlineElement(InlineElementType type, int start, int length, string link)
|
public InlineElement(InlineElementType type, int start, int length, string link)
|
||||||
{
|
{
|
||||||
|
@ -24,7 +23,7 @@
|
||||||
Link = link;
|
Link = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Intersect(int start, int length)
|
public bool IsIntersecting(int start, int length)
|
||||||
{
|
{
|
||||||
if (start == Start)
|
if (start == Start)
|
||||||
return true;
|
return true;
|
||||||
|
|
38
src/Models/InlineElementCollector.cs
Normal file
38
src/Models/InlineElementCollector.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SourceGit.Models
|
||||||
|
{
|
||||||
|
public class InlineElementCollector
|
||||||
|
{
|
||||||
|
public int Count => _implementation.Count;
|
||||||
|
public InlineElement this[int index] => _implementation[index];
|
||||||
|
|
||||||
|
public InlineElement Intersect(int start, int length)
|
||||||
|
{
|
||||||
|
foreach (var elem in _implementation)
|
||||||
|
{
|
||||||
|
if (elem.IsIntersecting(start, length))
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(InlineElement element)
|
||||||
|
{
|
||||||
|
_implementation.Add(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Sort()
|
||||||
|
{
|
||||||
|
_implementation.Sort((l, r) => l.Start.CompareTo(r.Start));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_implementation.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<InlineElement> _implementation = [];
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ namespace SourceGit.Models
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_singletoneLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
|
_singletonLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
|
||||||
_isFirstInstance = true;
|
_isFirstInstance = true;
|
||||||
_server = new NamedPipeServerStream(
|
_server = new NamedPipeServerStream(
|
||||||
"SourceGitIPCChannel" + Environment.UserName,
|
"SourceGitIPCChannel" + Environment.UserName,
|
||||||
|
@ -67,7 +67,7 @@ namespace SourceGit.Models
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_cancellationTokenSource?.Cancel();
|
_cancellationTokenSource?.Cancel();
|
||||||
_singletoneLock?.Dispose();
|
_singletonLock?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void StartServer()
|
private async void StartServer()
|
||||||
|
@ -96,7 +96,7 @@ namespace SourceGit.Models
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileStream _singletoneLock = null;
|
private FileStream _singletonLock = null;
|
||||||
private bool _isFirstInstance = false;
|
private bool _isFirstInstance = false;
|
||||||
private NamedPipeServerStream _server = null;
|
private NamedPipeServerStream _server = null;
|
||||||
private CancellationTokenSource _cancellationTokenSource = null;
|
private CancellationTokenSource _cancellationTokenSource = null;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Text.RegularExpressions;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ namespace SourceGit.Models
|
||||||
set => SetProperty(ref _urlTemplate, value);
|
set => SetProperty(ref _urlTemplate, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Matches(List<InlineElement> outs, string message)
|
public void Matches(InlineElementCollector outs, string message)
|
||||||
{
|
{
|
||||||
if (_regex == null || string.IsNullOrEmpty(_urlTemplate))
|
if (_regex == null || string.IsNullOrEmpty(_urlTemplate))
|
||||||
return;
|
return;
|
||||||
|
@ -60,17 +59,7 @@ namespace SourceGit.Models
|
||||||
|
|
||||||
var start = match.Index;
|
var start = match.Index;
|
||||||
var len = match.Length;
|
var len = match.Length;
|
||||||
var intersect = false;
|
if (outs.Intersect(start, len) != null)
|
||||||
foreach (var exist in outs)
|
|
||||||
{
|
|
||||||
if (exist.Intersect(start, len))
|
|
||||||
{
|
|
||||||
intersect = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intersect)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var link = _urlTemplate;
|
var link = _urlTemplate;
|
||||||
|
|
|
@ -1,8 +1,22 @@
|
||||||
namespace SourceGit.Models
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace SourceGit.Models
|
||||||
{
|
{
|
||||||
public class LFSObject
|
public partial class LFSObject
|
||||||
{
|
{
|
||||||
|
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
|
||||||
|
private static partial Regex REG_FORMAT();
|
||||||
|
|
||||||
public string Oid { get; set; } = string.Empty;
|
public string Oid { get; set; } = string.Empty;
|
||||||
public long Size { get; set; } = 0;
|
public long Size { get; set; } = 0;
|
||||||
|
|
||||||
|
public static LFSObject Parse(string content)
|
||||||
|
{
|
||||||
|
var match = REG_FORMAT().Match(content);
|
||||||
|
if (match.Success)
|
||||||
|
return new() { Oid = match.Groups[1].Value, Size = long.Parse(match.Groups[2].Value) };
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace SourceGit.Models
|
||||||
set;
|
set;
|
||||||
} = false;
|
} = false;
|
||||||
|
|
||||||
public bool OnlyHighlighCurrentBranchInHistories
|
public bool OnlyHighlightCurrentBranchInHistories
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
@ -188,7 +188,7 @@ namespace SourceGit.Models
|
||||||
set;
|
set;
|
||||||
} = false;
|
} = false;
|
||||||
|
|
||||||
public string PreferedOpenAIService
|
public string PreferredOpenAIService
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
@ -453,5 +453,19 @@ namespace SourceGit.Models
|
||||||
if (act != null)
|
if (act != null)
|
||||||
CustomActions.Remove(act);
|
CustomActions.Remove(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void MoveCustomActionUp(CustomAction act)
|
||||||
|
{
|
||||||
|
var idx = CustomActions.IndexOf(act);
|
||||||
|
if (idx > 0)
|
||||||
|
CustomActions.Move(idx - 1, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveCustomActionDown(CustomAction act)
|
||||||
|
{
|
||||||
|
var idx = CustomActions.IndexOf(act);
|
||||||
|
if (idx < CustomActions.Count - 1)
|
||||||
|
CustomActions.Move(idx + 1, idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using Avalonia.Media.Imaging;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
|
||||||
namespace SourceGit.Models
|
namespace SourceGit.Models
|
||||||
{
|
{
|
||||||
|
@ -9,10 +11,17 @@ namespace SourceGit.Models
|
||||||
|
|
||||||
public class RevisionImageFile
|
public class RevisionImageFile
|
||||||
{
|
{
|
||||||
public Bitmap Image { get; set; } = null;
|
public Bitmap Image { get; }
|
||||||
public long FileSize { get; set; } = 0;
|
public long FileSize { get; }
|
||||||
public string ImageType { get; set; } = string.Empty;
|
public string ImageType { get; }
|
||||||
public string ImageSize => Image != null ? $"{Image.PixelSize.Width} x {Image.PixelSize.Height}" : "0 x 0";
|
public string ImageSize => Image != null ? $"{Image.PixelSize.Width} x {Image.PixelSize.Height}" : "0 x 0";
|
||||||
|
|
||||||
|
public RevisionImageFile(string file, Bitmap img, long size)
|
||||||
|
{
|
||||||
|
Image = img;
|
||||||
|
FileSize = size;
|
||||||
|
ImageType = Path.GetExtension(file)!.Substring(1).ToUpper(CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RevisionTextFile
|
public class RevisionTextFile
|
||||||
|
|
|
@ -11,6 +11,6 @@ namespace SourceGit.Models
|
||||||
public ulong Time { get; set; } = 0;
|
public ulong Time { get; set; } = 0;
|
||||||
public string Message { get; set; } = "";
|
public string Message { get; set; } = "";
|
||||||
|
|
||||||
public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
|
public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ namespace SourceGit.Models
|
||||||
public enum TagSortMode
|
public enum TagSortMode
|
||||||
{
|
{
|
||||||
CreatorDate = 0,
|
CreatorDate = 0,
|
||||||
NameInAscending,
|
Name,
|
||||||
NameInDescending,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Tag : ObservableObject
|
public class Tag : ObservableObject
|
||||||
|
|
|
@ -157,7 +157,7 @@ namespace SourceGit.Models
|
||||||
if (string.IsNullOrEmpty(e.Name))
|
if (string.IsNullOrEmpty(e.Name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var name = e.Name.Replace("\\", "/");
|
var name = e.Name.Replace('\\', '/').TrimEnd('/');
|
||||||
if (name.Contains("fsmonitor--daemon/", StringComparison.Ordinal) ||
|
if (name.Contains("fsmonitor--daemon/", StringComparison.Ordinal) ||
|
||||||
name.EndsWith(".lock", StringComparison.Ordinal) ||
|
name.EndsWith(".lock", StringComparison.Ordinal) ||
|
||||||
name.StartsWith("lfs/", StringComparison.Ordinal))
|
name.StartsWith("lfs/", StringComparison.Ordinal))
|
||||||
|
@ -205,7 +205,7 @@ namespace SourceGit.Models
|
||||||
if (string.IsNullOrEmpty(e.Name))
|
if (string.IsNullOrEmpty(e.Name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var name = e.Name.Replace("\\", "/");
|
var name = e.Name.Replace('\\', '/').TrimEnd('/');
|
||||||
if (name.Equals(".git", StringComparison.Ordinal) ||
|
if (name.Equals(".git", StringComparison.Ordinal) ||
|
||||||
name.StartsWith(".git/", StringComparison.Ordinal) ||
|
name.StartsWith(".git/", StringComparison.Ordinal) ||
|
||||||
name.EndsWith("/.git", StringComparison.Ordinal))
|
name.EndsWith("/.git", StringComparison.Ordinal))
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace SourceGit.Models
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (IsDetached)
|
if (IsDetached)
|
||||||
return $"deteched HEAD at {Head.AsSpan(10)}";
|
return $"detached HEAD at {Head.AsSpan(10)}";
|
||||||
|
|
||||||
if (Branch.StartsWith("refs/heads/", StringComparison.Ordinal))
|
if (Branch.StartsWith("refs/heads/", StringComparison.Ordinal))
|
||||||
return Branch.Substring(11);
|
return Branch.Substring(11);
|
||||||
|
|
|
@ -120,8 +120,8 @@ namespace SourceGit.Native
|
||||||
private string FindExecutable(string filename)
|
private string FindExecutable(string filename)
|
||||||
{
|
{
|
||||||
var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
|
var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
|
||||||
var pathes = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
|
var paths = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||||
foreach (var path in pathes)
|
foreach (var path in paths)
|
||||||
{
|
{
|
||||||
var test = Path.Combine(path, filename);
|
var test = Path.Combine(path, filename);
|
||||||
if (File.Exists(test))
|
if (File.Exists(test))
|
||||||
|
|
|
@ -80,17 +80,17 @@ namespace SourceGit.Native
|
||||||
var p = IntPtrToPixelPoint(lParam);
|
var p = IntPtrToPixelPoint(lParam);
|
||||||
GetWindowRect(hWnd, out var rcWindow);
|
GetWindowRect(hWnd, out var rcWindow);
|
||||||
|
|
||||||
var borderThinkness = (int)(4 * window.RenderScaling);
|
var borderThickness = (int)(4 * window.RenderScaling);
|
||||||
int y = 1;
|
int y = 1;
|
||||||
int x = 1;
|
int x = 1;
|
||||||
if (p.X >= rcWindow.left && p.X < rcWindow.left + borderThinkness)
|
if (p.X >= rcWindow.left && p.X < rcWindow.left + borderThickness)
|
||||||
x = 0;
|
x = 0;
|
||||||
else if (p.X < rcWindow.right && p.X >= rcWindow.right - borderThinkness)
|
else if (p.X < rcWindow.right && p.X >= rcWindow.right - borderThickness)
|
||||||
x = 2;
|
x = 2;
|
||||||
|
|
||||||
if (p.Y >= rcWindow.top && p.Y < rcWindow.top + borderThinkness)
|
if (p.Y >= rcWindow.top && p.Y < rcWindow.top + borderThickness)
|
||||||
y = 0;
|
y = 0;
|
||||||
else if (p.Y < rcWindow.bottom && p.Y >= rcWindow.bottom - borderThinkness)
|
else if (p.Y < rcWindow.bottom && p.Y >= rcWindow.bottom - borderThickness)
|
||||||
y = 2;
|
y = 2;
|
||||||
|
|
||||||
var zone = y * 3 + x;
|
var zone = y * 3 + x;
|
||||||
|
@ -351,10 +351,10 @@ namespace SourceGit.Native
|
||||||
Microsoft.Win32.RegistryView.Registry64);
|
Microsoft.Win32.RegistryView.Registry64);
|
||||||
|
|
||||||
// VSCodium (system)
|
// VSCodium (system)
|
||||||
var systemVScodium = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{88DA3577-054F-4CA1-8122-7D820494CFFB}_is1");
|
var systemVSCodium = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{88DA3577-054F-4CA1-8122-7D820494CFFB}_is1");
|
||||||
if (systemVScodium != null)
|
if (systemVSCodium != null)
|
||||||
{
|
{
|
||||||
return systemVScodium.GetValue("DisplayIcon") as string;
|
return systemVSCodium.GetValue("DisplayIcon") as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey(
|
var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey(
|
||||||
|
|
|
@ -89,7 +89,8 @@
|
||||||
<StreamGeometry x:Key="Icons.Move">M299 811 299 725 384 725 384 811 299 811M469 811 469 725 555 725 555 811 469 811M640 811 640 725 725 725 725 811 640 811M299 640 299 555 384 555 384 640 299 640M469 640 469 555 555 555 555 640 469 640M640 640 640 555 725 555 725 640 640 640M299 469 299 384 384 384 384 469 299 469M469 469 469 384 555 384 555 469 469 469M640 469 640 384 725 384 725 469 640 469M299 299 299 213 384 213 384 299 299 299M469 299 469 213 555 213 555 299 469 299M640 299 640 213 725 213 725 299 640 299Z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Move">M299 811 299 725 384 725 384 811 299 811M469 811 469 725 555 725 555 811 469 811M640 811 640 725 725 725 725 811 640 811M299 640 299 555 384 555 384 640 299 640M469 640 469 555 555 555 555 640 469 640M640 640 640 555 725 555 725 640 640 640M299 469 299 384 384 384 384 469 299 469M469 469 469 384 555 384 555 469 469 469M640 469 640 384 725 384 725 469 640 469M299 299 299 213 384 213 384 299 299 299M469 299 469 213 555 213 555 299 469 299M640 299 640 213 725 213 725 299 640 299Z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.MoveToAnotherGroup">M64 363l0 204 265 0L329 460c0-11 6-18 14-20C349 437 355 437 362 441c93 60 226 149 226 149 33 22 34 60 0 82 0 0-133 89-226 149-14 9-32-3-32-18l-1-110L64 693l0 117c0 41 34 75 75 75l746 0c41 0 75-34 75-74L960 364c0-0 0-1 0-1L64 363zM64 214l0 75 650 0-33-80c-16-38-62-69-103-69l-440 0C97 139 64 173 64 214z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.MoveToAnotherGroup">M64 363l0 204 265 0L329 460c0-11 6-18 14-20C349 437 355 437 362 441c93 60 226 149 226 149 33 22 34 60 0 82 0 0-133 89-226 149-14 9-32-3-32-18l-1-110L64 693l0 117c0 41 34 75 75 75l746 0c41 0 75-34 75-74L960 364c0-0 0-1 0-1L64 363zM64 214l0 75 650 0-33-80c-16-38-62-69-103-69l-440 0C97 139 64 173 64 214z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.OpenWith">M683 409v204L1024 308 683 0v191c-413 0-427 526-427 526c117-229 203-307 427-307zm85 492H102V327h153s38-63 114-122H51c-28 0-51 27-51 61v697c0 34 23 61 51 61h768c28 0 51-27 51-61V614l-102 100v187z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.OpenWith">M683 409v204L1024 308 683 0v191c-413 0-427 526-427 526c117-229 203-307 427-307zm85 492H102V327h153s38-63 114-122H51c-28 0-51 27-51 61v697c0 34 23 61 51 61h768c28 0 51-27 51-61V614l-102 100v187z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Order">M841 627A43 43 0 00811 555h-299v85h196l-183 183A43 43 0 00555 896h299v-85h-196l183-183zM299 170H213v512H85l171 171 171-171H299zM725 128h-85c-18 0-34 11-40 28l-117 313h91L606 384h154l32 85h91l-117-313A43 43 0 00725 128zm-88 171 32-85h26l32 85h-90z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.OrderByName">M841 627A43 43 0 00811 555h-299v85h196l-183 183A43 43 0 00555 896h299v-85h-196l183-183zM299 170H213v512H85l171 171 171-171H299zM725 128h-85c-18 0-34 11-40 28l-117 313h91L606 384h154l32 85h91l-117-313A43 43 0 00725 128zm-88 171 32-85h26l32 85h-90z</StreamGeometry>
|
||||||
|
<StreamGeometry x:Key="Icons.OrderByTime">M512 0a512 512 0 01512 512 57 57 0 01-114 0 398 398 0 10-398 398 57 57 0 010 114A512 512 0 01512 0zm367 600 121 120a57 57 0 01-80 81l-40-40V967a57 57 0 01-50 57l-7 0a57 57 0 01-57-57v-205l-40 40a57 57 0 01-75 5l-5-5a57 57 0 01-0-80l120-121a80 80 0 01113-0zM512 272a57 57 0 0157 57V499h114a57 57 0 0156 50L740 556a57 57 0 01-57 57H512a57 57 0 01-57-57v-228a57 57 0 0150-57L512 272z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Password">M640 96c-158 0-288 130-288 288 0 17 3 31 5 46L105 681 96 691V928h224v-96h96v-96h96v-95c38 18 82 31 128 31 158 0 288-130 288-288s-130-288-288-288zm0 64c123 0 224 101 224 224s-101 224-224 224a235 235 0 01-109-28l-8-4H448v96h-96v96H256v96H160v-146l253-254 12-11-3-17C419 417 416 400 416 384c0-123 101-224 224-224zm64 96a64 64 0 100 128 64 64 0 100-128z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Password">M640 96c-158 0-288 130-288 288 0 17 3 31 5 46L105 681 96 691V928h224v-96h96v-96h96v-95c38 18 82 31 128 31 158 0 288-130 288-288s-130-288-288-288zm0 64c123 0 224 101 224 224s-101 224-224 224a235 235 0 01-109-28l-8-4H448v96h-96v96H256v96H160v-146l253-254 12-11-3-17C419 417 416 400 416 384c0-123 101-224 224-224zm64 96a64 64 0 100 128 64 64 0 100-128z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Paste">M544 85c49 0 90 37 95 85h75a96 96 0 0196 89L811 267a32 32 0 01-28 32L779 299a32 32 0 01-32-28L747 267a32 32 0 00-28-32L715 235h-91a96 96 0 01-80 42H395c-33 0-62-17-80-42L224 235a32 32 0 00-32 28L192 267v576c0 16 12 30 28 32l4 0h128a32 32 0 0132 28l0 4a32 32 0 01-32 32h-128a96 96 0 01-96-89L128 843V267a96 96 0 0189-96L224 171h75a96 96 0 0195-85h150zm256 256a96 96 0 0196 89l0 7v405a96 96 0 01-89 96L800 939h-277a96 96 0 01-96-89L427 843v-405a96 96 0 0189-96L523 341h277zm-256-192H395a32 32 0 000 64h150a32 32 0 100-64z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Paste">M544 85c49 0 90 37 95 85h75a96 96 0 0196 89L811 267a32 32 0 01-28 32L779 299a32 32 0 01-32-28L747 267a32 32 0 00-28-32L715 235h-91a96 96 0 01-80 42H395c-33 0-62-17-80-42L224 235a32 32 0 00-32 28L192 267v576c0 16 12 30 28 32l4 0h128a32 32 0 0132 28l0 4a32 32 0 01-32 32h-128a96 96 0 01-96-89L128 843V267a96 96 0 0189-96L224 171h75a96 96 0 0195-85h150zm256 256a96 96 0 0196 89l0 7v405a96 96 0 01-89 96L800 939h-277a96 96 0 01-96-89L427 843v-405a96 96 0 0189-96L523 341h277zm-256-192H395a32 32 0 000 64h150a32 32 0 100-64z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE DATEIEN</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE DATEIEN</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ENTFERNEN</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ENTFERNEN</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Aktualisieren</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINÄRE DATEI NICHT UNTERSTÜTZT!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINÄRE DATEI NICHT UNTERSTÜTZT!!!</x:String>
|
||||||
<x:String x:Key="Text.Bisect">Bisect</x:String>
|
<x:String x:Key="Text.Bisect">Bisect</x:String>
|
||||||
<x:String x:Key="Text.Bisect.Abort">Abbrechen</x:String>
|
<x:String x:Key="Text.Bisect.Abort">Abbrechen</x:String>
|
||||||
|
@ -550,7 +551,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Lokale Änderungen stashen & wieder anwenden</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Lokale Änderungen stashen & wieder anwenden</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Auf:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Auf:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Aktualisieren</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Remote hinzufügen</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Remote hinzufügen</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Remote bearbeiten</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Remote bearbeiten</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String>
|
||||||
|
@ -624,8 +624,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEUER TAG</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEUER TAG</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Nach Erstellungsdatum</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Nach Erstellungsdatum</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Nach Namen (Aufsteigend)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Nach Namen</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Nach Namen (Absteigend)</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sortiere</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sortiere</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Verwende relative Zeitangaben in Verlauf</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Verwende relative Zeitangaben in Verlauf</x:String>
|
||||||
|
@ -767,7 +766,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGEN</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGEN</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ALLES STAGEN</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ALLES STAGEN</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE ANZEIGEN</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE ANZEIGEN</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">ARBEITSPLATZ: </x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">ARBEITSPLATZ: </x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Arbeitsplätze konfigurieren...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Arbeitsplätze konfigurieren...</x:String>
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILES ASSUME UNCHANGED</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILES ASSUME UNCHANGED</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO FILES ASSUMED AS UNCHANGED</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO FILES ASSUMED AS UNCHANGED</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVE</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVE</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">Load Image...</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Refresh</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINARY FILE NOT SUPPORTED!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINARY FILE NOT SUPPORTED!!!</x:String>
|
||||||
<x:String x:Key="Text.Bisect">Bisect</x:String>
|
<x:String x:Key="Text.Bisect">Bisect</x:String>
|
||||||
<x:String x:Key="Text.Bisect.Abort">Abort</x:String>
|
<x:String x:Key="Text.Bisect.Abort">Abort</x:String>
|
||||||
|
@ -561,7 +563,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash & reapply local changes</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash & reapply local changes</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Refresh</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Add Remote</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Add Remote</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Edit Remote</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Edit Remote</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String>
|
||||||
|
@ -637,8 +638,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">New Tag</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">New Tag</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">By Creator Date</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">By Creator Date</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">By Name (Ascending)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">By Name</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">By Name (Descending)</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sort</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sort</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Use relative time in histories</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Use relative time in histories</x:String>
|
||||||
|
@ -791,7 +791,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE ALL</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE ALL</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VIEW ASSUME UNCHANGED</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VIEW ASSUME UNCHANGED</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE: </x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE: </x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configure Workspaces...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configure Workspaces...</x:String>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO HAY ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NO HAY ARCHIVOS ASUMIDOS COMO SIN CAMBIOS</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Refrescar</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">¡ARCHIVO BINARIO NO SOPORTADO!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">¡ARCHIVO BINARIO NO SOPORTADO!</x:String>
|
||||||
<x:String x:Key="Text.Bisect">Bisect</x:String>
|
<x:String x:Key="Text.Bisect">Bisect</x:String>
|
||||||
<x:String x:Key="Text.Bisect.Abort">Abortar</x:String>
|
<x:String x:Key="Text.Bisect.Abort">Abortar</x:String>
|
||||||
|
@ -565,7 +566,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash & reaplicar cambios locales</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash & reaplicar cambios locales</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">En:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">En:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Refrescar</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Añadir Remoto</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Añadir Remoto</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nombre:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nombre:</x:String>
|
||||||
|
@ -641,8 +641,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">ETIQUETAS</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">ETIQUETAS</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUEVA ETIQUETA</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUEVA ETIQUETA</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Por Fecha de Creación</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Por Fecha de Creación</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Por Nombre (Ascendiente)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Por Nombre</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Por Nombre (Descendiente)</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Ordenar</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Ordenar</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Abrir en Terminal</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Abrir en Terminal</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usar tiempo relativo en las historias</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usar tiempo relativo en las historias</x:String>
|
||||||
|
@ -795,7 +794,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODO</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODO</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VER ASSUME UNCHANGED</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VER ASSUME UNCHANGED</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Plantilla: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Plantilla: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">ESPACIO DE TRABAJO: </x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">ESPACIO DE TRABAJO: </x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Espacios de Trabajo...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Espacios de Trabajo...</x:String>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">PAS DE FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">PAS DE FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">SUPPRIMER</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">SUPPRIMER</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Rafraîchir</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FICHIER BINAIRE NON SUPPORTÉ !!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FICHIER BINAIRE NON SUPPORTÉ !!!</x:String>
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">Blâme</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">Blâme</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!</x:String>
|
||||||
|
@ -532,7 +533,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash & réappliquer changements locaux</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash & réappliquer changements locaux</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Sur :</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Sur :</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase :</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase :</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Rafraîchir</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Ajouter dépôt distant</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Ajouter dépôt distant</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Modifier dépôt distant</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Modifier dépôt distant</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nom :</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nom :</x:String>
|
||||||
|
@ -602,8 +602,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NOUVEAU TAG</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NOUVEAU TAG</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Par date de créateur</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Par date de créateur</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Par nom (Croissant)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Par nom</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Par nom (Décroissant)</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Trier</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Trier</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Ouvrir dans un terminal</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Ouvrir dans un terminal</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Utiliser le temps relatif dans les historiques</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Utiliser le temps relatif dans les historiques</x:String>
|
||||||
|
@ -734,7 +733,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">NON INDEXÉ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">NON INDEXÉ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">INDEXER</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">INDEXER</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">INDEXER TOUT</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">INDEXER TOUT</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VOIR LES FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VOIR LES FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Modèle: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Modèle: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">ESPACE DE TRAVAIL : </x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">ESPACE DE TRAVAIL : </x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configurer les espaces de travail...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configurer les espaces de travail...</x:String>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILE ASSUNTI COME INVARIATI</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FILE ASSUNTI COME INVARIATI</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NESSUN FILE ASSUNTO COME INVARIATO</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NESSUN FILE ASSUNTO COME INVARIATO</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">RIMUOVI</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">RIMUOVI</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Aggiorna</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FILE BINARIO NON SUPPORTATO!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FILE BINARIO NON SUPPORTATO!!!</x:String>
|
||||||
<x:String x:Key="Text.Bisect" xml:space="preserve">Biseca</x:String>
|
<x:String x:Key="Text.Bisect" xml:space="preserve">Biseca</x:String>
|
||||||
<x:String x:Key="Text.Bisect.Abort" xml:space="preserve">Annulla</x:String>
|
<x:String x:Key="Text.Bisect.Abort" xml:space="preserve">Annulla</x:String>
|
||||||
|
@ -553,7 +554,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stasha e Riapplica modifiche locali</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stasha e Riapplica modifiche locali</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Su:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Su:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Riallinea:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Riallinea:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Aggiorna</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Aggiungi Remoto</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Aggiungi Remoto</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Modifica Remoto</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Modifica Remoto</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nome:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nome:</x:String>
|
||||||
|
@ -628,8 +628,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAG</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAG</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUOVO TAG</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NUOVO TAG</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Per data di creazione</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">Per data di creazione</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">Per nome (ascendente)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Per nome</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">Per nome (discendente)</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Ordina</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Ordina</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Apri nel Terminale</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Apri nel Terminale</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usa tempo relativo nello storico</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Usa tempo relativo nello storico</x:String>
|
||||||
|
@ -777,7 +776,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">NON IN STAGE</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">NON IN STAGE</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">FAI LO STAGE</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">FAI LO STAGE</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">FAI LO STAGE DI TUTTO</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">FAI LO STAGE DI TUTTO</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VISUALIZZA COME NON MODIFICATO</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VISUALIZZA COME NON MODIFICATO</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE:</x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE:</x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Workspaces...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Workspaces...</x:String>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">変更されていないとみなされるファイル</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">変更されていないとみなされるファイル</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">変更されていないとみなされるファイルはありません</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">変更されていないとみなされるファイルはありません</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">削除</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">削除</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">更新</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">バイナリファイルはサポートされていません!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">バイナリファイルはサポートされていません!!!</x:String>
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAMEではこのファイルはサポートされていません!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAMEではこのファイルはサポートされていません!!!</x:String>
|
||||||
|
@ -531,7 +532,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">ローカルの変更をスタッシュして再適用</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">ローカルの変更をスタッシュして再適用</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">リベース:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">リベース:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">更新</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">リモートを追加</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">リモートを追加</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">リモートを編集</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">リモートを編集</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">名前:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">名前:</x:String>
|
||||||
|
@ -600,7 +600,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">タグ</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">タグ</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新しいタグを作成</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新しいタグを作成</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">作成者日時</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">作成者日時</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">名前 (昇順)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">名前</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">ソート</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">ソート</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">ターミナルで開く</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">ターミナルで開く</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">履歴に相対時間を使用</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">履歴に相対時間を使用</x:String>
|
||||||
|
@ -731,7 +731,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未ステージのファイル</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未ステージのファイル</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">ステージへ移動</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">ステージへ移動</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">すべてステージへ移動</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">すべてステージへ移動</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">変更されていないとみなしたものを表示</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">変更されていないとみなしたものを表示</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">テンプレート: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">テンプレート: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">ワークスペース: </x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">ワークスペース: </x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">ワークスペースを設定...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">ワークスペースを設定...</x:String>
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARQUIVOS CONSIDERADOS SEM ALTERAÇÕES</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ARQUIVOS CONSIDERADOS SEM ALTERAÇÕES</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NENHUM ARQUIVO CONSIDERADO SEM ALTERAÇÕES</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">NENHUM ARQUIVO CONSIDERADO SEM ALTERAÇÕES</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVER</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Atualizar</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">ARQUIVO BINÁRIO NÃO SUPORTADO!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">ARQUIVO BINÁRIO NÃO SUPORTADO!!!</x:String>
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!</x:String>
|
||||||
|
@ -488,7 +489,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Guardar & reaplicar alterações locais</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Guardar & reaplicar alterações locais</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Em:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">Em:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Atualizar</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Adicionar Remoto</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Adicionar Remoto</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Editar Remoto</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nome:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Nome:</x:String>
|
||||||
|
@ -667,7 +667,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODOS</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE TODOS</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VER SUPOR NÃO ALTERADO</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">VER SUPOR NÃO ALTERADO</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">Workspaces: </x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">Workspaces: </x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configurar workspaces...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configurar workspaces...</x:String>
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">СПИСОК ПУСТ</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">СПИСОК ПУСТ</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">УДАЛИТЬ</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">УДАЛИТЬ</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">Загрузить картинку...</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Обновить</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">ДВОИЧНЫЙ ФАЙЛ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">ДВОИЧНЫЙ ФАЙЛ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String>
|
||||||
<x:String x:Key="Text.Bisect">Раздвоить</x:String>
|
<x:String x:Key="Text.Bisect">Раздвоить</x:String>
|
||||||
<x:String x:Key="Text.Bisect.Abort">О</x:String>
|
<x:String x:Key="Text.Bisect.Abort">О</x:String>
|
||||||
|
@ -50,6 +52,7 @@
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">Расследование</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">Расследование</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!!</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Переключиться на ${0}$...</x:String>
|
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Переключиться на ${0}$...</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCM.CompareWithCurrent" xml:space="preserve">Сравнить с ${0}$</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим каталогом</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим каталогом</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Копировать имя ветки</x:String>
|
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Копировать имя ветки</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Изменить действие</x:String>
|
<x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Изменить действие</x:String>
|
||||||
|
@ -564,7 +567,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Отложить и применить повторно локальные изменения</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Отложить и применить повторно локальные изменения</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">На:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">На:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Переместить:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Переместить:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Обновить</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Добавить внешний репозиторий</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Добавить внешний репозиторий</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Редактировать внешний репозиторий</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Редактировать внешний репозиторий</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Имя:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Имя:</x:String>
|
||||||
|
@ -592,6 +594,7 @@
|
||||||
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String>
|
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String>
|
||||||
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду (git gc) для данного репозитория.</x:String>
|
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду (git gc) для данного репозитория.</x:String>
|
||||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String>
|
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.ClearStashes" xml:space="preserve">Очистить</x:String>
|
||||||
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Настройка репозитория</x:String>
|
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Настройка репозитория</x:String>
|
||||||
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">ПРОДОЛЖИТЬ</x:String>
|
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">ПРОДОЛЖИТЬ</x:String>
|
||||||
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Изменить действия</x:String>
|
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Изменить действия</x:String>
|
||||||
|
@ -639,8 +642,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">МЕТКИ</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">МЕТКИ</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">НОВАЯ МЕТКА</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">НОВАЯ МЕТКА</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">По дате создания</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">По дате создания</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">По имени (по возрастанию)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">По имени</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">По имени (по убыванию)</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортировать</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортировать</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Открыть в терминале</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Открыть в терминале</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Использовать относительное время в историях</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Использовать относительное время в историях</x:String>
|
||||||
|
@ -784,6 +786,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String>
|
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">НЕТ ПОСЛЕДНИХ ВХОДНЫХ СООБЩЕНИЙ</x:String>
|
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">НЕТ ПОСЛЕДНИХ ВХОДНЫХ СООБЩЕНИЙ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">НЕТ ШАБЛОНОВ РЕВИЗИИ</x:String>
|
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">НЕТ ШАБЛОНОВ РЕВИЗИИ</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">Сбросить автора</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Щёлкните правой кнопкой мыши выбранный файл(ы) и разрешите конфликты.</x:String>
|
<x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Щёлкните правой кнопкой мыши выбранный файл(ы) и разрешите конфликты.</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">Завершение работы</x:String>
|
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">Завершение работы</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">СФОРМИРОВАННЫЕ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">СФОРМИРОВАННЫЕ</x:String>
|
||||||
|
@ -792,7 +795,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">НЕСФОРМИРОВАННЫЕ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">НЕСФОРМИРОВАННЫЕ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">СФОРМИРОВАТЬ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">СФОРМИРОВАТЬ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">СФОРМИРОВАТЬ ВСЁ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">СФОРМИРОВАТЬ ВСЁ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">ОТКРЫТЬ СПИСОК НЕОТСЛЕЖИВАЕМЫХ ФАЙЛОВ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">ОТКРЫТЬ СПИСОК НЕОТСЛЕЖИВАЕМЫХ ФАЙЛОВ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Шаблон: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Шаблон: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">РАБОЧЕЕ ПРОСТРАНСТВО: </x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">РАБОЧЕЕ ПРОСТРАНСТВО: </x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Настройка рабочего пространства...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Настройка рабочего пространства...</x:String>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">கோப்புகள் மாற்றப்படவில்லை எனக் கருதப்படுகிறது</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">கோப்புகள் மாற்றப்படவில்லை எனக் கருதப்படுகிறது</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">எந்த கோப்புகளும் மாற்றப்படவில்லை எனக் கருதப்படுகிறது</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">எந்த கோப்புகளும் மாற்றப்படவில்லை எனக் கருதப்படுகிறது</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">நீக்கு</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">நீக்கு</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">புதுப்பி</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">இருமம் கோப்பு ஆதரிக்கப்படவில்லை!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">இருமம் கோப்பு ஆதரிக்கப்படவில்லை!!!</x:String>
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">குற்றச்சாட்டு</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">குற்றச்சாட்டு</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!!</x:String>
|
||||||
|
@ -531,7 +532,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">உள்ளக மாற்றங்களை பதுக்கிவை & மீண்டும் இடு</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">உள்ளக மாற்றங்களை பதுக்கிவை & மீண்டும் இடு</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">மேல்:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">மேல்:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">மறுதளம்:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">மறுதளம்:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">புதுப்பி</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">தொலையைச் சேர்</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">தொலையைச் சேர்</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">தொலையைத் திருத்து</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">தொலையைத் திருத்து</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">பெயர்:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">பெயர்:</x:String>
|
||||||
|
@ -601,8 +601,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">குறிசொற்கள்</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">குறிசொற்கள்</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">புதிய குறிசொல்</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">புதிய குறிசொல்</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">படைப்பாளர் தேதியின்படி</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">படைப்பாளர் தேதியின்படி</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">பெயர் (ஏறுவரிசை) மூலம்</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">பெயர் மூலம்</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">பெயர் (இறகுவரிசை) மூலம்</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">வரிசைப்படுத்து</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">வரிசைப்படுத்து</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">முனையத்தில் திற</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">முனையத்தில் திற</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">வரலாறுகளில் உறவு நேரத்தைப் பயன்படுத்து</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">வரலாறுகளில் உறவு நேரத்தைப் பயன்படுத்து</x:String>
|
||||||
|
@ -733,7 +732,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">நிலைநீக்கு</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">நிலைநீக்கு</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">நிலைபடுத்து</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">நிலைபடுத்து</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">அனைத்தும் நிலைபடுத்து</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">அனைத்தும் நிலைபடுத்து</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">மாறாதது எனநினைப்பதை பார்</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">மாறாதது எனநினைப்பதை பார்</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">வளர்புரு: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">வளர்புரு: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">பணியிடம்:</x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">பணியிடம்:</x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">பணியிடங்களை உள்ளமை...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">பணியிடங்களை உள்ளமை...</x:String>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">НЕМАЄ ФАЙЛІВ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">НЕМАЄ ФАЙЛІВ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ВИДАЛИТИ</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ВИДАЛИТИ</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">Оновити</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">БІНАРНИЙ ФАЙЛ НЕ ПІДТРИМУЄТЬСЯ!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">БІНАРНИЙ ФАЙЛ НЕ ПІДТРИМУЄТЬСЯ!!!</x:String>
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">Автор рядка</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">Автор рядка</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!!</x:String>
|
||||||
|
@ -536,7 +537,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Сховати та застосувати локальні зміни</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Сховати та застосувати локальні зміни</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">На:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">На:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Перебазувати:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Перебазувати:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Оновити</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Додати віддалене сховище</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Додати віддалене сховище</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Редагувати віддалене сховище</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Редагувати віддалене сховище</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Назва:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Назва:</x:String>
|
||||||
|
@ -606,8 +606,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">ТЕГИ</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">ТЕГИ</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">НОВИЙ ТЕГ</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">НОВИЙ ТЕГ</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">За датою створення</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">За датою створення</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">За назвою (за зростанням)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">За назвою</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">За назвою (за спаданням)</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортувати</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортувати</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Відкрити в терміналі</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Відкрити в терміналі</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Використовувати відносний час в історії</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Використовувати відносний час в історії</x:String>
|
||||||
|
@ -743,7 +742,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">НЕПРОІНДЕКСОВАНІ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">НЕПРОІНДЕКСОВАНІ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">ІНДЕКСУВАТИ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">ІНДЕКСУВАТИ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ІНДЕКСУВАТИ ВСЕ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ІНДЕКСУВАТИ ВСЕ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">ПЕРЕГЛЯНУТИ ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">ПЕРЕГЛЯНУТИ ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Шаблон: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Шаблон: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">РОБОЧИЙ ПРОСТІР: </x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">РОБОЧИЙ ПРОСТІР: </x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Налаштувати робочі простори...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Налаштувати робочі простори...</x:String>
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">不跟踪更改的文件</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">不跟踪更改的文件</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">没有不跟踪更改的文件</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">没有不跟踪更改的文件</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">移除</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">移除</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">加载本地图片</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">重新加载</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二进制文件不支持该操作!!!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二进制文件不支持该操作!!!</x:String>
|
||||||
<x:String x:Key="Text.Bisect">二分定位(bisect)</x:String>
|
<x:String x:Key="Text.Bisect">二分定位(bisect)</x:String>
|
||||||
<x:String x:Key="Text.Bisect.Abort">终止</x:String>
|
<x:String x:Key="Text.Bisect.Abort">终止</x:String>
|
||||||
|
@ -565,7 +567,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自动贮藏并恢复本地变更</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自动贮藏并恢复本地变更</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">目标提交 :</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">目标提交 :</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">分支 :</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">分支 :</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">重新加载</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">添加远程仓库</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">添加远程仓库</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">编辑远程仓库</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">编辑远程仓库</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">远程名 :</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">远程名 :</x:String>
|
||||||
|
@ -641,8 +642,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">标签列表</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">标签列表</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新建标签</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新建标签</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">按创建时间</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">按创建时间</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">按名称(升序)</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">按名称</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">按名称(降序)</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">排序</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">排序</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在终端中打开</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在终端中打开</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相对时间</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相对时间</x:String>
|
||||||
|
@ -795,7 +795,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未暂存</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未暂存</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">暂存选中</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">暂存选中</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">暂存所有</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">暂存所有</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">查看忽略变更文件</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">查看忽略变更文件</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">模板:${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">模板:${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">工作区:</x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">工作区:</x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">配置工作区...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">配置工作区...</x:String>
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">不追蹤變更的檔案</x:String>
|
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">不追蹤變更的檔案</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">沒有不追蹤變更的檔案</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">沒有不追蹤變更的檔案</x:String>
|
||||||
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">移除</x:String>
|
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">移除</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Load" xml:space="preserve">載入本機圖片...</x:String>
|
||||||
|
<x:String x:Key="Text.Avatar.Refetch" xml:space="preserve">重新載入</x:String>
|
||||||
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二進位檔案不支援該操作!</x:String>
|
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">二進位檔案不支援該操作!</x:String>
|
||||||
<x:String x:Key="Text.Bisect">二分搜尋 (bisect)</x:String>
|
<x:String x:Key="Text.Bisect">二分搜尋 (bisect)</x:String>
|
||||||
<x:String x:Key="Text.Bisect.Abort">中止</x:String>
|
<x:String x:Key="Text.Bisect.Abort">中止</x:String>
|
||||||
|
@ -565,7 +567,6 @@
|
||||||
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自動擱置變更並復原本機變更</x:String>
|
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自動擱置變更並復原本機變更</x:String>
|
||||||
<x:String x:Key="Text.Rebase.On" xml:space="preserve">目標提交:</x:String>
|
<x:String x:Key="Text.Rebase.On" xml:space="preserve">目標提交:</x:String>
|
||||||
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">分支:</x:String>
|
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">分支:</x:String>
|
||||||
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">重新載入</x:String>
|
|
||||||
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">新增遠端存放庫</x:String>
|
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">新增遠端存放庫</x:String>
|
||||||
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">編輯遠端存放庫</x:String>
|
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">編輯遠端存放庫</x:String>
|
||||||
<x:String x:Key="Text.Remote.Name" xml:space="preserve">遠端名稱:</x:String>
|
<x:String x:Key="Text.Remote.Name" xml:space="preserve">遠端名稱:</x:String>
|
||||||
|
@ -641,8 +642,7 @@
|
||||||
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">標籤列表</x:String>
|
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">標籤列表</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新增標籤</x:String>
|
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">新增標籤</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">依建立時間</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">依建立時間</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">依名稱升序</x:String>
|
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">依名稱</x:String>
|
||||||
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">依名稱降序</x:String>
|
|
||||||
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">排序</x:String>
|
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">排序</x:String>
|
||||||
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在終端機中開啟</x:String>
|
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在終端機中開啟</x:String>
|
||||||
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相對時間</x:String>
|
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相對時間</x:String>
|
||||||
|
@ -795,7 +795,7 @@
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未暫存</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">未暫存</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">暫存選取的檔案</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">暫存選取的檔案</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">暫存所有檔案</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">暫存所有檔案</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">檢視不追蹤變更的檔案</x:String>
|
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchanged" xml:space="preserve">檢視不追蹤變更的檔案</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">範本: ${0}$</x:String>
|
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">範本: ${0}$</x:String>
|
||||||
<x:String x:Key="Text.Workspace" xml:space="preserve">工作區:</x:String>
|
<x:String x:Key="Text.Workspace" xml:space="preserve">工作區:</x:String>
|
||||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">設定工作區...</x:String>
|
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">設定工作區...</x:String>
|
||||||
|
|
|
@ -843,6 +843,10 @@
|
||||||
<DataTemplate DataType="x:String">
|
<DataTemplate DataType="x:String">
|
||||||
<v:NameHighlightedTextBlock Text="{Binding}" VerticalAlignment="Center"/>
|
<v:NameHighlightedTextBlock Text="{Binding}" VerticalAlignment="Center"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
|
<DataTemplate DataType="vm:FilterModeInGraph">
|
||||||
|
<v:FilterModeInGraph/>
|
||||||
|
</DataTemplate>
|
||||||
</ContentPresenter.DataTemplates>
|
</ContentPresenter.DataTemplates>
|
||||||
</ContentPresenter>
|
</ContentPresenter>
|
||||||
|
|
||||||
|
@ -949,6 +953,20 @@
|
||||||
</Style>
|
</Style>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="MenuItem.filter_mode_switcher">
|
||||||
|
<Setter Property="Height" Value="48"/>
|
||||||
|
<Setter Property="StaysOpenOnClick" Value="True"/>
|
||||||
|
|
||||||
|
<Style Selector="^:selected">
|
||||||
|
<Style Selector="^ /template/ Border#PART_LayoutRoot">
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
|
||||||
|
<Setter Property="Foreground" Value="Transparent" />
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
|
|
||||||
<Style Selector="ComboBox">
|
<Style Selector="ComboBox">
|
||||||
<Style.Resources>
|
<Style.Resources>
|
||||||
<Thickness x:Key="ComboBoxDropdownBorderPadding">4,0</Thickness>
|
<Thickness x:Key="ComboBoxDropdownBorderPadding">4,0</Thickness>
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" />
|
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" />
|
||||||
<PackageReference Include="OpenAI" Version="2.2.0-beta.4" />
|
<PackageReference Include="OpenAI" Version="2.2.0-beta.4" />
|
||||||
|
<PackageReference Include="Pfim" Version="0.11.3" />
|
||||||
<PackageReference Include="TextMateSharp" Version="1.0.66" />
|
<PackageReference Include="TextMateSharp" Version="1.0.66" />
|
||||||
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.66" />
|
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.66" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(file))
|
if (!string.IsNullOrEmpty(file))
|
||||||
{
|
{
|
||||||
var log = _repo.CreateLog("Remove Assue Unchanged File");
|
var log = _repo.CreateLog("Remove Assume Unchanged File");
|
||||||
new Commands.AssumeUnchanged(_repo.FullPath, file, false).Use(log).Exec();
|
new Commands.AssumeUnchanged(_repo.FullPath, file, false).Use(log).Exec();
|
||||||
log.Complete();
|
log.Complete();
|
||||||
Files.Remove(file);
|
Files.Remove(file);
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public void NavigateToCommit(string commitSHA)
|
public void NavigateToCommit(string commitSHA)
|
||||||
{
|
{
|
||||||
var launcher = App.GetLauncer();
|
var launcher = App.GetLauncher();
|
||||||
if (launcher == null)
|
if (launcher == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public void NavigateTo(string commitSHA)
|
public void NavigateTo(string commitSHA)
|
||||||
{
|
{
|
||||||
var launcher = App.GetLauncer();
|
var launcher = App.GetLauncher();
|
||||||
if (launcher == null)
|
if (launcher == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ namespace SourceGit.ViewModels
|
||||||
CallUIThread(() =>
|
CallUIThread(() =>
|
||||||
{
|
{
|
||||||
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true);
|
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true);
|
||||||
var launcher = App.GetLauncer();
|
var launcher = App.GetLauncher();
|
||||||
var page = null as LauncherPage;
|
var page = null as LauncherPage;
|
||||||
foreach (var one in launcher.Pages)
|
foreach (var one in launcher.Pages)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Avalonia.Platform.Storage;
|
using Avalonia.Platform.Storage;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
|
@ -56,7 +54,7 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
private set;
|
private set;
|
||||||
} = [];
|
}
|
||||||
|
|
||||||
public List<string> Children
|
public List<string> Children
|
||||||
{
|
{
|
||||||
|
@ -103,16 +101,20 @@ namespace SourceGit.ViewModels
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (SetProperty(ref _searchChangeFilter, value))
|
if (SetProperty(ref _searchChangeFilter, value))
|
||||||
{
|
|
||||||
RefreshVisibleChanges();
|
RefreshVisibleChanges();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string ViewRevisionFilePath
|
||||||
|
{
|
||||||
|
get => _viewRevisionFilePath;
|
||||||
|
private set => SetProperty(ref _viewRevisionFilePath, value);
|
||||||
|
}
|
||||||
|
|
||||||
public object ViewRevisionFileContent
|
public object ViewRevisionFileContent
|
||||||
{
|
{
|
||||||
get => _viewRevisionFileContent;
|
get => _viewRevisionFileContent;
|
||||||
set => SetProperty(ref _viewRevisionFileContent, value);
|
private set => SetProperty(ref _viewRevisionFileContent, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string RevisionFileSearchFilter
|
public string RevisionFileSearchFilter
|
||||||
|
@ -193,10 +195,13 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
if (file == null)
|
if (file == null)
|
||||||
{
|
{
|
||||||
|
ViewRevisionFilePath = string.Empty;
|
||||||
ViewRevisionFileContent = null;
|
ViewRevisionFileContent = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewRevisionFilePath = file.Path;
|
||||||
|
|
||||||
switch (file.Type)
|
switch (file.Type)
|
||||||
{
|
{
|
||||||
case Models.ObjectType.Blob:
|
case Models.ObjectType.Blob:
|
||||||
|
@ -205,14 +210,11 @@ namespace SourceGit.ViewModels
|
||||||
var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result();
|
var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result();
|
||||||
if (isBinary)
|
if (isBinary)
|
||||||
{
|
{
|
||||||
var ext = Path.GetExtension(file.Path);
|
var imgDecoder = ImageSource.GetDecoder(file.Path);
|
||||||
if (IMG_EXTS.Contains(ext))
|
if (imgDecoder != Models.ImageDecoder.None)
|
||||||
{
|
{
|
||||||
var stream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path);
|
var source = ImageSource.FromRevision(_repo.FullPath, _commit.SHA, file.Path, imgDecoder);
|
||||||
var fileSize = stream.Length;
|
var image = new Models.RevisionImageFile(file.Path, source.Bitmap, source.Size);
|
||||||
var bitmap = fileSize > 0 ? new Bitmap(stream) : null;
|
|
||||||
var imageType = ext!.Substring(1).ToUpper(CultureInfo.CurrentCulture);
|
|
||||||
var image = new Models.RevisionImageFile() { Image = bitmap, FileSize = fileSize, ImageType = imageType };
|
|
||||||
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = image);
|
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = image);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -227,13 +229,20 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path);
|
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path);
|
||||||
var content = new StreamReader(contentStream).ReadToEnd();
|
var content = new StreamReader(contentStream).ReadToEnd();
|
||||||
var matchLFS = REG_LFS_FORMAT().Match(content);
|
var lfs = Models.LFSObject.Parse(content);
|
||||||
if (matchLFS.Success)
|
if (lfs != null)
|
||||||
{
|
{
|
||||||
var obj = new Models.RevisionLFSObject() { Object = new Models.LFSObject() };
|
var imgDecoder = ImageSource.GetDecoder(file.Path);
|
||||||
obj.Object.Oid = matchLFS.Groups[1].Value;
|
if (imgDecoder != Models.ImageDecoder.None)
|
||||||
obj.Object.Size = long.Parse(matchLFS.Groups[2].Value);
|
{
|
||||||
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = obj);
|
var combined = new RevisionLFSImage(_repo.FullPath, file.Path, lfs, imgDecoder);
|
||||||
|
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = combined);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rlfs = new Models.RevisionLFSObject() { Object = lfs };
|
||||||
|
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = rlfs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -245,30 +254,16 @@ namespace SourceGit.ViewModels
|
||||||
case Models.ObjectType.Commit:
|
case Models.ObjectType.Commit:
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
var submoduleRoot = Path.Combine(_repo.FullPath, file.Path);
|
var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/');
|
||||||
var commit = new Commands.QuerySingleCommit(submoduleRoot, file.SHA).Result();
|
var commit = new Commands.QuerySingleCommit(submoduleRoot, file.SHA).Result();
|
||||||
if (commit != null)
|
var message = commit != null ? new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result() : null;
|
||||||
|
var module = new Models.RevisionSubmodule()
|
||||||
{
|
{
|
||||||
var body = new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result();
|
Commit = commit ?? new Models.Commit() { SHA = _commit.SHA },
|
||||||
var submodule = new Models.RevisionSubmodule()
|
FullMessage = new Models.CommitFullMessage { Message = message }
|
||||||
{
|
};
|
||||||
Commit = commit,
|
|
||||||
FullMessage = new Models.CommitFullMessage { Message = body }
|
|
||||||
};
|
|
||||||
|
|
||||||
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = submodule);
|
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = module);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Dispatcher.UIThread.Invoke(() =>
|
|
||||||
{
|
|
||||||
ViewRevisionFileContent = new Models.RevisionSubmodule()
|
|
||||||
{
|
|
||||||
Commit = new Models.Commit() { SHA = file.SHA },
|
|
||||||
FullMessage = null,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -426,12 +421,12 @@ 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.Click += (_, ev) =>
|
openWith.Click += async (_, ev) =>
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
|
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
|
||||||
var fileExt = Path.GetExtension(fullPath) ?? "";
|
var fileExt = Path.GetExtension(fullPath) ?? "";
|
||||||
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
|
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
|
||||||
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, tmpFile);
|
await Task.Run(() => Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, tmpFile));
|
||||||
Native.OS.OpenWithDefaultEditor(tmpFile);
|
Native.OS.OpenWithDefaultEditor(tmpFile);
|
||||||
ev.Handled = true;
|
ev.Handled = true;
|
||||||
};
|
};
|
||||||
|
@ -453,9 +448,9 @@ namespace SourceGit.ViewModels
|
||||||
if (selected.Count == 1)
|
if (selected.Count == 1)
|
||||||
{
|
{
|
||||||
var folder = selected[0];
|
var folder = selected[0];
|
||||||
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
|
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder.Path.ToString();
|
||||||
var saveTo = Path.Combine(folderPath, Path.GetFileName(file.Path));
|
var saveTo = Path.Combine(folderPath, Path.GetFileName(file.Path)!);
|
||||||
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo);
|
await Task.Run(() => Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -625,9 +620,9 @@ namespace SourceGit.ViewModels
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Models.InlineElement> ParseInlinesInMessage(string message)
|
private Models.InlineElementCollector ParseInlinesInMessage(string message)
|
||||||
{
|
{
|
||||||
var inlines = new List<Models.InlineElement>();
|
var inlines = new Models.InlineElementCollector();
|
||||||
if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules)
|
if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules)
|
||||||
{
|
{
|
||||||
foreach (var rule in rules)
|
foreach (var rule in rules)
|
||||||
|
@ -643,17 +638,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
var start = match.Index;
|
var start = match.Index;
|
||||||
var len = match.Length;
|
var len = match.Length;
|
||||||
var intersect = false;
|
if (inlines.Intersect(start, len) != null)
|
||||||
foreach (var link in inlines)
|
|
||||||
{
|
|
||||||
if (link.Intersect(start, len))
|
|
||||||
{
|
|
||||||
intersect = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intersect)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var url = message.Substring(start, len);
|
var url = message.Substring(start, len);
|
||||||
|
@ -670,17 +655,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
var start = match.Index;
|
var start = match.Index;
|
||||||
var len = match.Length;
|
var len = match.Length;
|
||||||
var intersect = false;
|
if (inlines.Intersect(start, len) != null)
|
||||||
foreach (var link in inlines)
|
|
||||||
{
|
|
||||||
if (link.Intersect(start, len))
|
|
||||||
{
|
|
||||||
intersect = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intersect)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var sha = match.Groups[1].Value;
|
var sha = match.Groups[1].Value;
|
||||||
|
@ -689,9 +664,7 @@ namespace SourceGit.ViewModels
|
||||||
inlines.Add(new Models.InlineElement(Models.InlineElementType.CommitSHA, start, len, sha));
|
inlines.Add(new Models.InlineElement(Models.InlineElementType.CommitSHA, start, len, sha));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inlines.Count > 0)
|
inlines.Sort();
|
||||||
inlines.Sort((l, r) => l.Start - r.Start);
|
|
||||||
|
|
||||||
return inlines;
|
return inlines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,14 +870,6 @@ namespace SourceGit.ViewModels
|
||||||
[GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")]
|
[GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")]
|
||||||
private static partial Regex REG_SHA_FORMAT();
|
private static partial Regex REG_SHA_FORMAT();
|
||||||
|
|
||||||
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
|
|
||||||
private static partial Regex REG_LFS_FORMAT();
|
|
||||||
|
|
||||||
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
|
|
||||||
{
|
|
||||||
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
|
|
||||||
};
|
|
||||||
|
|
||||||
private Repository _repo = null;
|
private Repository _repo = null;
|
||||||
private Models.Commit _commit = null;
|
private Models.Commit _commit = null;
|
||||||
private Models.CommitFullMessage _fullMessage = null;
|
private Models.CommitFullMessage _fullMessage = null;
|
||||||
|
@ -915,6 +880,7 @@ namespace SourceGit.ViewModels
|
||||||
private List<Models.Change> _selectedChanges = null;
|
private List<Models.Change> _selectedChanges = null;
|
||||||
private string _searchChangeFilter = string.Empty;
|
private string _searchChangeFilter = string.Empty;
|
||||||
private DiffContext _diffContext = null;
|
private DiffContext _diffContext = null;
|
||||||
|
private string _viewRevisionFilePath = string.Empty;
|
||||||
private object _viewRevisionFileContent = null;
|
private object _viewRevisionFileContent = null;
|
||||||
private CancellationTokenSource _cancellationSource = null;
|
private CancellationTokenSource _cancellationSource = null;
|
||||||
private bool _requestingRevisionFiles = false;
|
private bool _requestingRevisionFiles = false;
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
@ -14,7 +12,7 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
public string Title
|
public string Title
|
||||||
{
|
{
|
||||||
get => _title;
|
get;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IgnoreWhitespace
|
public bool IgnoreWhitespace
|
||||||
|
@ -70,9 +68,9 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
|
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
|
||||||
_title = _option.Path;
|
Title = _option.Path;
|
||||||
else
|
else
|
||||||
_title = $"{_option.OrgPath} → {_option.Path}";
|
Title = $"{_option.OrgPath} → {_option.Path}";
|
||||||
|
|
||||||
LoadDiffContent();
|
LoadDiffContent();
|
||||||
}
|
}
|
||||||
|
@ -113,13 +111,10 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
// NOTE: Here we override the UnifiedLines value (if UseFullTextDiff is on).
|
|
||||||
// There is no way to tell a git-diff to use "ALL lines of context",
|
|
||||||
// so instead we set a very high number for the "lines of context" parameter.
|
|
||||||
var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
|
var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
|
||||||
var ignoreWS = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
|
var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
|
||||||
var latest = new Commands.Diff(_repo, _option, numLines, ignoreWS).Result();
|
var latest = new Commands.Diff(_repo, _option, numLines, ignoreWhitespace).Result();
|
||||||
var info = new Info(_option, numLines, ignoreWS, latest);
|
var info = new Info(_option, numLines, ignoreWhitespace, latest);
|
||||||
if (_info != null && info.IsSame(_info))
|
if (_info != null && info.IsSame(_info))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -133,7 +128,7 @@ namespace SourceGit.ViewModels
|
||||||
if (count <= 3)
|
if (count <= 3)
|
||||||
{
|
{
|
||||||
var submoduleDiff = new Models.SubmoduleDiff();
|
var submoduleDiff = new Models.SubmoduleDiff();
|
||||||
var submoduleRoot = $"{_repo}/{_option.Path}".Replace("\\", "/");
|
var submoduleRoot = $"{_repo}/{_option.Path}".Replace('\\', '/').TrimEnd('/');
|
||||||
isSubmodule = true;
|
isSubmodule = true;
|
||||||
for (int i = 1; i < count; i++)
|
for (int i = 1; i < count; i++)
|
||||||
{
|
{
|
||||||
|
@ -164,28 +159,39 @@ namespace SourceGit.ViewModels
|
||||||
else if (latest.IsBinary)
|
else if (latest.IsBinary)
|
||||||
{
|
{
|
||||||
var oldPath = string.IsNullOrEmpty(_option.OrgPath) ? _option.Path : _option.OrgPath;
|
var oldPath = string.IsNullOrEmpty(_option.OrgPath) ? _option.Path : _option.OrgPath;
|
||||||
var ext = Path.GetExtension(_option.Path);
|
var imgDecoder = ImageSource.GetDecoder(_option.Path);
|
||||||
|
|
||||||
if (IMG_EXTS.Contains(ext))
|
if (imgDecoder != Models.ImageDecoder.None)
|
||||||
{
|
{
|
||||||
var imgDiff = new Models.ImageDiff();
|
var imgDiff = new Models.ImageDiff();
|
||||||
|
|
||||||
if (_option.Revisions.Count == 2)
|
if (_option.Revisions.Count == 2)
|
||||||
{
|
{
|
||||||
(imgDiff.Old, imgDiff.OldFileSize) = BitmapFromRevisionFile(_repo, _option.Revisions[0], oldPath);
|
var oldImage = ImageSource.FromRevision(_repo, _option.Revisions[0], oldPath, imgDecoder);
|
||||||
(imgDiff.New, imgDiff.NewFileSize) = BitmapFromRevisionFile(_repo, _option.Revisions[1], _option.Path);
|
var newImage = ImageSource.FromRevision(_repo, _option.Revisions[1], _option.Path, imgDecoder);
|
||||||
|
imgDiff.Old = oldImage.Bitmap;
|
||||||
|
imgDiff.OldFileSize = oldImage.Size;
|
||||||
|
imgDiff.New = newImage.Bitmap;
|
||||||
|
imgDiff.NewFileSize = newImage.Size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!oldPath.Equals("/dev/null", StringComparison.Ordinal))
|
if (!oldPath.Equals("/dev/null", StringComparison.Ordinal))
|
||||||
(imgDiff.Old, imgDiff.OldFileSize) = BitmapFromRevisionFile(_repo, "HEAD", oldPath);
|
{
|
||||||
|
var oldImage = ImageSource.FromRevision(_repo, "HEAD", oldPath, imgDecoder);
|
||||||
|
imgDiff.Old = oldImage.Bitmap;
|
||||||
|
imgDiff.OldFileSize = oldImage.Size;
|
||||||
|
}
|
||||||
|
|
||||||
var fullPath = Path.Combine(_repo, _option.Path);
|
var fullPath = Path.Combine(_repo, _option.Path);
|
||||||
if (File.Exists(fullPath))
|
if (File.Exists(fullPath))
|
||||||
{
|
{
|
||||||
imgDiff.New = new Bitmap(fullPath);
|
var newImage = ImageSource.FromFile(fullPath, imgDecoder);
|
||||||
imgDiff.NewFileSize = new FileInfo(fullPath).Length;
|
imgDiff.New = newImage.Bitmap;
|
||||||
|
imgDiff.NewFileSize = newImage.Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rs = imgDiff;
|
rs = imgDiff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -207,7 +213,11 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
else if (latest.IsLFS)
|
else if (latest.IsLFS)
|
||||||
{
|
{
|
||||||
rs = latest.LFSDiff;
|
var imgDecoder = ImageSource.GetDecoder(_option.Path);
|
||||||
|
if (imgDecoder != Models.ImageDecoder.None)
|
||||||
|
rs = new LFSImageDiff(_repo, latest.LFSDiff, imgDecoder);
|
||||||
|
else
|
||||||
|
rs = latest.LFSDiff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -226,45 +236,27 @@ namespace SourceGit.ViewModels
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private (Bitmap, long) BitmapFromRevisionFile(string repo, string revision, string file)
|
|
||||||
{
|
|
||||||
var stream = Commands.QueryFileContent.Run(repo, revision, file);
|
|
||||||
var size = stream.Length;
|
|
||||||
return size > 0 ? (new Bitmap(stream), size) : (null, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Models.RevisionSubmodule QuerySubmoduleRevision(string repo, string sha)
|
private Models.RevisionSubmodule QuerySubmoduleRevision(string repo, string sha)
|
||||||
{
|
{
|
||||||
var commit = new Commands.QuerySingleCommit(repo, sha).Result();
|
var commit = new Commands.QuerySingleCommit(repo, sha).Result();
|
||||||
if (commit != null)
|
if (commit == null)
|
||||||
{
|
return new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = sha } };
|
||||||
var body = new Commands.QueryCommitFullMessage(repo, sha).Result();
|
|
||||||
return new Models.RevisionSubmodule()
|
|
||||||
{
|
|
||||||
Commit = commit,
|
|
||||||
FullMessage = new Models.CommitFullMessage { Message = body }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var body = new Commands.QueryCommitFullMessage(repo, sha).Result();
|
||||||
return new Models.RevisionSubmodule()
|
return new Models.RevisionSubmodule()
|
||||||
{
|
{
|
||||||
Commit = new Models.Commit() { SHA = sha },
|
Commit = commit,
|
||||||
FullMessage = null,
|
FullMessage = new Models.CommitFullMessage { Message = body }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
|
|
||||||
{
|
|
||||||
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
|
|
||||||
};
|
|
||||||
|
|
||||||
private class Info
|
private class Info
|
||||||
{
|
{
|
||||||
public string Argument { get; set; }
|
public string Argument { get; }
|
||||||
public int UnifiedLines { get; set; }
|
public int UnifiedLines { get; }
|
||||||
public bool IgnoreWhitespace { get; set; }
|
public bool IgnoreWhitespace { get; }
|
||||||
public string OldHash { get; set; }
|
public string OldHash { get; }
|
||||||
public string NewHash { get; set; }
|
public string NewHash { get; }
|
||||||
|
|
||||||
public Info(Models.DiffOption option, int unifiedLines, bool ignoreWhitespace, Models.DiffResult result)
|
public Info(Models.DiffOption option, int unifiedLines, bool ignoreWhitespace, Models.DiffResult result)
|
||||||
{
|
{
|
||||||
|
@ -287,7 +279,6 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
private readonly string _repo;
|
private readonly string _repo;
|
||||||
private readonly Models.DiffOption _option = null;
|
private readonly Models.DiffOption _option = null;
|
||||||
private string _title;
|
|
||||||
private string _fileModeChange = string.Empty;
|
private string _fileModeChange = string.Empty;
|
||||||
private int _unifiedLines = 4;
|
private int _unifiedLines = 4;
|
||||||
private bool _isTextDiff = false;
|
private bool _isTextDiff = false;
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Avalonia.Collections;
|
using Avalonia.Collections;
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
@ -18,7 +15,7 @@ namespace SourceGit.ViewModels
|
||||||
public object Content { get; set; } = content;
|
public object Content { get; set; } = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class FileHistoriesSingleRevision : ObservableObject
|
public class FileHistoriesSingleRevision : ObservableObject
|
||||||
{
|
{
|
||||||
public bool IsDiffMode
|
public bool IsDiffMode
|
||||||
{
|
{
|
||||||
|
@ -47,9 +44,9 @@ namespace SourceGit.ViewModels
|
||||||
RefreshViewContent();
|
RefreshViewContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetToSelectedRevision()
|
public Task<bool> ResetToSelectedRevision()
|
||||||
{
|
{
|
||||||
new Commands.Checkout(_repo.FullPath).FileWithRevision(_file, $"{_revision.SHA}");
|
return Task.Run(() => new Commands.Checkout(_repo.FullPath).FileWithRevision(_file, $"{_revision.SHA}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshViewContent()
|
private void RefreshViewContent()
|
||||||
|
@ -78,14 +75,11 @@ namespace SourceGit.ViewModels
|
||||||
var isBinary = new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).Result();
|
var isBinary = new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).Result();
|
||||||
if (isBinary)
|
if (isBinary)
|
||||||
{
|
{
|
||||||
var ext = Path.GetExtension(_file);
|
var imgDecoder = ImageSource.GetDecoder(_file);
|
||||||
if (IMG_EXTS.Contains(ext))
|
if (imgDecoder != Models.ImageDecoder.None)
|
||||||
{
|
{
|
||||||
var stream = Commands.QueryFileContent.Run(_repo.FullPath, _revision.SHA, _file);
|
var source = ImageSource.FromRevision(_repo.FullPath, _revision.SHA, _file, imgDecoder);
|
||||||
var fileSize = stream.Length;
|
var image = new Models.RevisionImageFile(_file, source.Bitmap, source.Size);
|
||||||
var bitmap = fileSize > 0 ? new Bitmap(stream) : null;
|
|
||||||
var imageType = Path.GetExtension(_file).TrimStart('.').ToUpper(CultureInfo.CurrentCulture);
|
|
||||||
var image = new Models.RevisionImageFile() { Image = bitmap, FileSize = fileSize, ImageType = imageType };
|
|
||||||
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, image));
|
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, image));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -100,13 +94,20 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _revision.SHA, _file);
|
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _revision.SHA, _file);
|
||||||
var content = new StreamReader(contentStream).ReadToEnd();
|
var content = new StreamReader(contentStream).ReadToEnd();
|
||||||
var matchLFS = REG_LFS_FORMAT().Match(content);
|
var lfs = Models.LFSObject.Parse(content);
|
||||||
if (matchLFS.Success)
|
if (lfs != null)
|
||||||
{
|
{
|
||||||
var lfs = new Models.RevisionLFSObject() { Object = new Models.LFSObject() };
|
var imgDecoder = ImageSource.GetDecoder(_file);
|
||||||
lfs.Object.Oid = matchLFS.Groups[1].Value;
|
if (imgDecoder != Models.ImageDecoder.None)
|
||||||
lfs.Object.Size = long.Parse(matchLFS.Groups[2].Value);
|
{
|
||||||
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, lfs));
|
var combined = new RevisionLFSImage(_repo.FullPath, _file, lfs, imgDecoder);
|
||||||
|
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, combined));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rlfs = new Models.RevisionLFSObject() { Object = lfs };
|
||||||
|
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, rlfs));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -120,25 +121,14 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
var submoduleRoot = Path.Combine(_repo.FullPath, _file);
|
var submoduleRoot = Path.Combine(_repo.FullPath, _file);
|
||||||
var commit = new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).Result();
|
var commit = new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).Result();
|
||||||
if (commit != null)
|
var message = commit != null ? new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result() : null;
|
||||||
|
var module = new Models.RevisionSubmodule()
|
||||||
{
|
{
|
||||||
var message = new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result();
|
Commit = commit ?? new Models.Commit() { SHA = obj.SHA },
|
||||||
var module = new Models.RevisionSubmodule()
|
FullMessage = new Models.CommitFullMessage { Message = message }
|
||||||
{
|
};
|
||||||
Commit = commit,
|
|
||||||
FullMessage = new Models.CommitFullMessage { Message = message }
|
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
|
||||||
};
|
|
||||||
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var module = new Models.RevisionSubmodule()
|
|
||||||
{
|
|
||||||
Commit = new Models.Commit() { SHA = obj.SHA },
|
|
||||||
FullMessage = null
|
|
||||||
};
|
|
||||||
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -153,18 +143,10 @@ namespace SourceGit.ViewModels
|
||||||
ViewContent = new DiffContext(_repo.FullPath, option, _viewContent as DiffContext);
|
ViewContent = new DiffContext(_repo.FullPath, option, _viewContent as DiffContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
|
|
||||||
private static partial Regex REG_LFS_FORMAT();
|
|
||||||
|
|
||||||
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
|
|
||||||
{
|
|
||||||
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
|
|
||||||
};
|
|
||||||
|
|
||||||
private Repository _repo = null;
|
private Repository _repo = null;
|
||||||
private string _file = null;
|
private string _file = null;
|
||||||
private Models.Commit _revision = null;
|
private Models.Commit _revision = null;
|
||||||
private bool _isDiffMode = true;
|
private bool _isDiffMode = false;
|
||||||
private object _viewContent = null;
|
private object _viewContent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +247,6 @@ namespace SourceGit.ViewModels
|
||||||
public FileHistories(Repository repo, string file, string commit = null)
|
public FileHistories(Repository repo, string file, string commit = null)
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
_file = file;
|
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
|
@ -288,10 +269,10 @@ namespace SourceGit.ViewModels
|
||||||
switch (SelectedCommits.Count)
|
switch (SelectedCommits.Count)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
ViewContent = new FileHistoriesSingleRevision(_repo, _file, SelectedCommits[0], _prevIsDiffMode);
|
ViewContent = new FileHistoriesSingleRevision(_repo, file, SelectedCommits[0], _prevIsDiffMode);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
ViewContent = new FileHistoriesCompareRevisions(_repo, _file, SelectedCommits[0], SelectedCommits[1]);
|
ViewContent = new FileHistoriesCompareRevisions(_repo, file, SelectedCommits[0], SelectedCommits[1]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ViewContent = SelectedCommits.Count;
|
ViewContent = SelectedCommits.Count;
|
||||||
|
@ -317,11 +298,10 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Repository _repo = null;
|
private readonly Repository _repo = null;
|
||||||
private readonly string _file = null;
|
|
||||||
private bool _isLoading = true;
|
private bool _isLoading = true;
|
||||||
private bool _prevIsDiffMode = true;
|
private bool _prevIsDiffMode = true;
|
||||||
private List<Models.Commit> _commits = null;
|
private List<Models.Commit> _commits = null;
|
||||||
private Dictionary<string, string> _fullCommitMessages = new Dictionary<string, string>();
|
private Dictionary<string, string> _fullCommitMessages = new();
|
||||||
private object _viewContent = null;
|
private object _viewContent = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
62
src/ViewModels/FilterModeInGraph.cs
Normal file
62
src/ViewModels/FilterModeInGraph.cs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
using System;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace SourceGit.ViewModels
|
||||||
|
{
|
||||||
|
public class FilterModeInGraph : ObservableObject
|
||||||
|
{
|
||||||
|
public bool IsFiltered
|
||||||
|
{
|
||||||
|
get => _mode == Models.FilterMode.Included;
|
||||||
|
set => SetFilterMode(value ? Models.FilterMode.Included : Models.FilterMode.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsExcluded
|
||||||
|
{
|
||||||
|
get => _mode == Models.FilterMode.Excluded;
|
||||||
|
set => SetFilterMode(value ? Models.FilterMode.Excluded : Models.FilterMode.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FilterModeInGraph(Repository repo, object target)
|
||||||
|
{
|
||||||
|
_repo = repo;
|
||||||
|
_target = target;
|
||||||
|
|
||||||
|
if (_target is Models.Branch b)
|
||||||
|
_mode = GetFilterMode(b.FullName);
|
||||||
|
else if (_target is Models.Tag t)
|
||||||
|
_mode = GetFilterMode(t.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Models.FilterMode GetFilterMode(string pattern)
|
||||||
|
{
|
||||||
|
foreach (var filter in _repo.Settings.HistoriesFilters)
|
||||||
|
{
|
||||||
|
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
||||||
|
return filter.Mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Models.FilterMode.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFilterMode(Models.FilterMode mode)
|
||||||
|
{
|
||||||
|
if (_mode != mode)
|
||||||
|
{
|
||||||
|
_mode = mode;
|
||||||
|
|
||||||
|
if (_target is Models.Branch branch)
|
||||||
|
_repo.SetBranchFilterMode(branch, _mode, false, true);
|
||||||
|
else if (_target is Models.Tag tag)
|
||||||
|
_repo.SetTagFilterMode(tag, _mode);
|
||||||
|
|
||||||
|
OnPropertyChanged(nameof(IsFiltered));
|
||||||
|
OnPropertyChanged(nameof(IsExcluded));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Repository _repo = null;
|
||||||
|
private object _target = null;
|
||||||
|
private Models.FilterMode _mode = Models.FilterMode.None;
|
||||||
|
}
|
||||||
|
}
|
|
@ -809,116 +809,17 @@ namespace SourceGit.ViewModels
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Models.FilterMode GetFilterMode(string pattern)
|
|
||||||
{
|
|
||||||
foreach (var filter in _repo.Settings.HistoriesFilters)
|
|
||||||
{
|
|
||||||
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
|
||||||
return filter.Mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Models.FilterMode.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillBranchVisibilityMenu(MenuItem submenu, Models.Branch branch)
|
|
||||||
{
|
|
||||||
var visibility = new MenuItem();
|
|
||||||
visibility.Icon = App.CreateMenuIcon("Icons.Eye");
|
|
||||||
visibility.Header = App.Text("Repository.FilterCommits");
|
|
||||||
|
|
||||||
var exclude = new MenuItem();
|
|
||||||
exclude.Icon = App.CreateMenuIcon("Icons.EyeClose");
|
|
||||||
exclude.Header = App.Text("Repository.FilterCommits.Exclude");
|
|
||||||
exclude.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
_repo.SetBranchFilterMode(branch, Models.FilterMode.Excluded, false, true);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var filterMode = GetFilterMode(branch.FullName);
|
|
||||||
if (filterMode == Models.FilterMode.None)
|
|
||||||
{
|
|
||||||
var include = new MenuItem();
|
|
||||||
include.Icon = App.CreateMenuIcon("Icons.Filter");
|
|
||||||
include.Header = App.Text("Repository.FilterCommits.Include");
|
|
||||||
include.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
_repo.SetBranchFilterMode(branch, Models.FilterMode.Included, false, true);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
visibility.Items.Add(include);
|
|
||||||
visibility.Items.Add(exclude);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var unset = new MenuItem();
|
|
||||||
unset.Header = App.Text("Repository.FilterCommits.Default");
|
|
||||||
unset.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
_repo.SetBranchFilterMode(branch, Models.FilterMode.None, false, true);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
visibility.Items.Add(exclude);
|
|
||||||
visibility.Items.Add(unset);
|
|
||||||
}
|
|
||||||
|
|
||||||
submenu.Items.Add(visibility);
|
|
||||||
submenu.Items.Add(new MenuItem() { Header = "-" });
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillTagVisibilityMenu(MenuItem submenu, Models.Tag tag)
|
|
||||||
{
|
|
||||||
var visibility = new MenuItem();
|
|
||||||
visibility.Icon = App.CreateMenuIcon("Icons.Eye");
|
|
||||||
visibility.Header = App.Text("Repository.FilterCommits");
|
|
||||||
|
|
||||||
var exclude = new MenuItem();
|
|
||||||
exclude.Icon = App.CreateMenuIcon("Icons.EyeClose");
|
|
||||||
exclude.Header = App.Text("Repository.FilterCommits.Exclude");
|
|
||||||
exclude.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
_repo.SetTagFilterMode(tag, Models.FilterMode.Excluded);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var filterMode = GetFilterMode(tag.Name);
|
|
||||||
if (filterMode == Models.FilterMode.None)
|
|
||||||
{
|
|
||||||
var include = new MenuItem();
|
|
||||||
include.Icon = App.CreateMenuIcon("Icons.Filter");
|
|
||||||
include.Header = App.Text("Repository.FilterCommits.Include");
|
|
||||||
include.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
_repo.SetTagFilterMode(tag, Models.FilterMode.Included);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
visibility.Items.Add(include);
|
|
||||||
visibility.Items.Add(exclude);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var unset = new MenuItem();
|
|
||||||
unset.Header = App.Text("Repository.FilterCommits.Default");
|
|
||||||
unset.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
_repo.SetTagFilterMode(tag, Models.FilterMode.None);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
visibility.Items.Add(exclude);
|
|
||||||
visibility.Items.Add(unset);
|
|
||||||
}
|
|
||||||
|
|
||||||
submenu.Items.Add(visibility);
|
|
||||||
submenu.Items.Add(new MenuItem() { Header = "-" });
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillCurrentBranchMenu(ContextMenu menu, Models.Branch current)
|
private void FillCurrentBranchMenu(ContextMenu menu, Models.Branch current)
|
||||||
{
|
{
|
||||||
var submenu = new MenuItem();
|
var submenu = new MenuItem();
|
||||||
submenu.Icon = App.CreateMenuIcon("Icons.Branch");
|
submenu.Icon = App.CreateMenuIcon("Icons.Branch");
|
||||||
submenu.Header = current.Name;
|
submenu.Header = current.Name;
|
||||||
|
|
||||||
FillBranchVisibilityMenu(submenu, current);
|
var visibility = new MenuItem();
|
||||||
|
visibility.Classes.Add("filter_mode_switcher");
|
||||||
|
visibility.Header = new FilterModeInGraph(_repo, current);
|
||||||
|
submenu.Items.Add(visibility);
|
||||||
|
submenu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(current.Upstream))
|
if (!string.IsNullOrEmpty(current.Upstream))
|
||||||
{
|
{
|
||||||
|
@ -1015,7 +916,11 @@ namespace SourceGit.ViewModels
|
||||||
submenu.Icon = App.CreateMenuIcon("Icons.Branch");
|
submenu.Icon = App.CreateMenuIcon("Icons.Branch");
|
||||||
submenu.Header = branch.Name;
|
submenu.Header = branch.Name;
|
||||||
|
|
||||||
FillBranchVisibilityMenu(submenu, branch);
|
var visibility = new MenuItem();
|
||||||
|
visibility.Classes.Add("filter_mode_switcher");
|
||||||
|
visibility.Header = new FilterModeInGraph(_repo, branch);
|
||||||
|
submenu.Items.Add(visibility);
|
||||||
|
submenu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
if (!_repo.IsBare)
|
if (!_repo.IsBare)
|
||||||
{
|
{
|
||||||
|
@ -1105,7 +1010,11 @@ namespace SourceGit.ViewModels
|
||||||
submenu.Icon = App.CreateMenuIcon("Icons.Branch");
|
submenu.Icon = App.CreateMenuIcon("Icons.Branch");
|
||||||
submenu.Header = name;
|
submenu.Header = name;
|
||||||
|
|
||||||
FillBranchVisibilityMenu(submenu, branch);
|
var visibility = new MenuItem();
|
||||||
|
visibility.Classes.Add("filter_mode_switcher");
|
||||||
|
visibility.Header = new FilterModeInGraph(_repo, branch);
|
||||||
|
submenu.Items.Add(visibility);
|
||||||
|
submenu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
var checkout = new MenuItem();
|
var checkout = new MenuItem();
|
||||||
checkout.Header = App.Text("BranchCM.Checkout", name);
|
checkout.Header = App.Text("BranchCM.Checkout", name);
|
||||||
|
@ -1162,7 +1071,11 @@ namespace SourceGit.ViewModels
|
||||||
submenu.Icon = App.CreateMenuIcon("Icons.Tag");
|
submenu.Icon = App.CreateMenuIcon("Icons.Tag");
|
||||||
submenu.MinWidth = 200;
|
submenu.MinWidth = 200;
|
||||||
|
|
||||||
FillTagVisibilityMenu(submenu, tag);
|
var visibility = new MenuItem();
|
||||||
|
visibility.Classes.Add("filter_mode_switcher");
|
||||||
|
visibility.Header = new FilterModeInGraph(_repo, tag);
|
||||||
|
submenu.Items.Add(visibility);
|
||||||
|
submenu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
var push = new MenuItem();
|
var push = new MenuItem();
|
||||||
push.Header = App.Text("TagCM.Push", tag.Name);
|
push.Header = App.Text("TagCM.Push", tag.Name);
|
||||||
|
|
155
src/ViewModels/ImageSource.cs
Normal file
155
src/ViewModels/ImageSource.cs
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
using Avalonia.Platform;
|
||||||
|
|
||||||
|
using Pfim;
|
||||||
|
|
||||||
|
namespace SourceGit.ViewModels
|
||||||
|
{
|
||||||
|
public class ImageSource
|
||||||
|
{
|
||||||
|
public Bitmap Bitmap { get; }
|
||||||
|
public long Size { get; }
|
||||||
|
|
||||||
|
public ImageSource(Bitmap bitmap, long size)
|
||||||
|
{
|
||||||
|
Bitmap = bitmap;
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Models.ImageDecoder GetDecoder(string file)
|
||||||
|
{
|
||||||
|
var ext = (Path.GetExtension(file) ?? ".invalid_img").ToLower(CultureInfo.CurrentCulture);
|
||||||
|
|
||||||
|
switch (ext)
|
||||||
|
{
|
||||||
|
case ".ico":
|
||||||
|
case ".bmp":
|
||||||
|
case ".jpg":
|
||||||
|
case ".jpeg":
|
||||||
|
case ".png":
|
||||||
|
case ".webp":
|
||||||
|
return Models.ImageDecoder.Builtin;
|
||||||
|
case ".tga":
|
||||||
|
case ".dds":
|
||||||
|
return Models.ImageDecoder.Pfim;
|
||||||
|
default:
|
||||||
|
return Models.ImageDecoder.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImageSource FromFile(string fullpath, Models.ImageDecoder decoder)
|
||||||
|
{
|
||||||
|
using (var stream = File.OpenRead(fullpath))
|
||||||
|
return LoadFromStream(stream, decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImageSource FromRevision(string repo, string revision, string file, Models.ImageDecoder decoder)
|
||||||
|
{
|
||||||
|
var stream = Commands.QueryFileContent.Run(repo, revision, file);
|
||||||
|
return LoadFromStream(stream, decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImageSource FromLFSObject(string repo, Models.LFSObject lfs, Models.ImageDecoder decoder)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(lfs.Oid) || lfs.Size == 0)
|
||||||
|
return new ImageSource(null, 0);
|
||||||
|
|
||||||
|
var stream = Commands.QueryFileContent.FromLFS(repo, lfs.Oid, lfs.Size);
|
||||||
|
return LoadFromStream(stream, decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImageSource LoadFromStream(Stream stream, Models.ImageDecoder decoder)
|
||||||
|
{
|
||||||
|
var size = stream.Length;
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
if (decoder == Models.ImageDecoder.Builtin)
|
||||||
|
return DecodeWithAvalonia(stream, size);
|
||||||
|
else if (decoder == Models.ImageDecoder.Pfim)
|
||||||
|
return DecodeWithPfim(stream, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ImageSource(null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImageSource DecodeWithAvalonia(Stream stream, long size)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bitmap = new Bitmap(stream);
|
||||||
|
return new ImageSource(bitmap, size);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new ImageSource(null, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImageSource DecodeWithPfim(Stream stream, long size)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var pfiImage = Pfimage.FromStream(stream))
|
||||||
|
{
|
||||||
|
var data = pfiImage.Data;
|
||||||
|
var stride = pfiImage.Stride;
|
||||||
|
|
||||||
|
var pixelFormat = PixelFormats.Bgra8888;
|
||||||
|
var alphaFormat = AlphaFormat.Opaque;
|
||||||
|
switch (pfiImage.Format)
|
||||||
|
{
|
||||||
|
case ImageFormat.Rgb8:
|
||||||
|
pixelFormat = PixelFormats.Gray8;
|
||||||
|
break;
|
||||||
|
case ImageFormat.R5g5b5:
|
||||||
|
case ImageFormat.R5g5b5a1:
|
||||||
|
pixelFormat = PixelFormats.Bgr555;
|
||||||
|
break;
|
||||||
|
case ImageFormat.R5g6b5:
|
||||||
|
pixelFormat = PixelFormats.Bgr565;
|
||||||
|
break;
|
||||||
|
case ImageFormat.Rgb24:
|
||||||
|
pixelFormat = PixelFormats.Bgr24;
|
||||||
|
break;
|
||||||
|
case ImageFormat.Rgba16:
|
||||||
|
var pixels2 = pfiImage.DataLen / 2;
|
||||||
|
data = new byte[pixels2 * 4];
|
||||||
|
stride = pfiImage.Width * 4;
|
||||||
|
for (var i = 0; i < pixels2; i++)
|
||||||
|
{
|
||||||
|
var src = BitConverter.ToUInt16(pfiImage.Data, i * 2);
|
||||||
|
data[i * 4 + 0] = (byte)Math.Round((src & 0x0F) / 15F * 255); // B
|
||||||
|
data[i * 4 + 1] = (byte)Math.Round(((src >> 4) & 0x0F) / 15F * 255); // G
|
||||||
|
data[i * 4 + 2] = (byte)Math.Round(((src >> 8) & 0x0F) / 15F * 255); // R
|
||||||
|
data[i * 4 + 3] = (byte)Math.Round(((src >> 12) & 0x0F) / 15F * 255); // A
|
||||||
|
}
|
||||||
|
|
||||||
|
alphaFormat = AlphaFormat.Premul;
|
||||||
|
break;
|
||||||
|
case ImageFormat.Rgba32:
|
||||||
|
alphaFormat = AlphaFormat.Premul;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return new ImageSource(null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
|
||||||
|
var pixelSize = new PixelSize(pfiImage.Width, pfiImage.Height);
|
||||||
|
var dpi = new Vector(96, 96);
|
||||||
|
var bitmap = new Bitmap(pixelFormat, alphaFormat, ptr, pixelSize, dpi, stride);
|
||||||
|
return new ImageSource(bitmap, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new ImageSource(null, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
[Required(ErrorMessage = "Feature prefix is required!!!")]
|
[Required(ErrorMessage = "Feature prefix is required!!!")]
|
||||||
[RegularExpression(@"^[\w\-\.]+/$", ErrorMessage = "Bad feature prefix format!")]
|
[RegularExpression(@"^[\w\-\.]+/$", ErrorMessage = "Bad feature prefix format!")]
|
||||||
public string FeturePrefix
|
public string FeaturePrefix
|
||||||
{
|
{
|
||||||
get => _featurePrefix;
|
get => _featurePrefix;
|
||||||
set => SetProperty(ref _featurePrefix, value, true);
|
set => SetProperty(ref _featurePrefix, value, true);
|
||||||
|
|
43
src/ViewModels/LFSImageDiff.cs
Normal file
43
src/ViewModels/LFSImageDiff.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace SourceGit.ViewModels
|
||||||
|
{
|
||||||
|
public class LFSImageDiff : ObservableObject
|
||||||
|
{
|
||||||
|
public Models.LFSDiff LFS
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Models.ImageDiff Image
|
||||||
|
{
|
||||||
|
get => _image;
|
||||||
|
private set => SetProperty(ref _image, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LFSImageDiff(string repo, Models.LFSDiff lfs, Models.ImageDecoder decoder)
|
||||||
|
{
|
||||||
|
LFS = lfs;
|
||||||
|
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
var oldImage = ImageSource.FromLFSObject(repo, lfs.Old, decoder);
|
||||||
|
var newImage = ImageSource.FromLFSObject(repo, lfs.New, decoder);
|
||||||
|
|
||||||
|
var img = new Models.ImageDiff()
|
||||||
|
{
|
||||||
|
Old = oldImage.Bitmap,
|
||||||
|
OldFileSize = oldImage.Size,
|
||||||
|
New = newImage.Bitmap,
|
||||||
|
NewFileSize = newImage.Size
|
||||||
|
};
|
||||||
|
|
||||||
|
Dispatcher.UIThread.Invoke(() => Image = img);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Models.ImageDiff _image;
|
||||||
|
}
|
||||||
|
}
|
|
@ -360,7 +360,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
if (!Path.Exists(node.Id))
|
if (!Path.Exists(node.Id))
|
||||||
{
|
{
|
||||||
App.RaiseException(node.Id, "Repository does NOT exists any more. Please remove it.");
|
App.RaiseException(node.Id, "Repository does NOT exist any more. Please remove it.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +421,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
foreach (var page in Pages)
|
foreach (var page in Pages)
|
||||||
{
|
{
|
||||||
var id = page.Node.Id.Replace("\\", "/");
|
var id = page.Node.Id.Replace('\\', '/').TrimEnd('/');
|
||||||
if (id == pageId)
|
if (id == pageId)
|
||||||
{
|
{
|
||||||
page.Notifications.Add(notification);
|
page.Notifications.Add(notification);
|
||||||
|
|
|
@ -261,6 +261,12 @@ namespace SourceGit.ViewModels
|
||||||
set => SetProperty(ref _useBlockNavigationInDiffView, value);
|
set => SetProperty(ref _useBlockNavigationInDiffView, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int LFSImageActiveIdx
|
||||||
|
{
|
||||||
|
get => _lfsImageActiveIdx;
|
||||||
|
set => SetProperty(ref _lfsImageActiveIdx, value);
|
||||||
|
}
|
||||||
|
|
||||||
public Models.ChangeViewMode UnstagedChangeViewMode
|
public Models.ChangeViewMode UnstagedChangeViewMode
|
||||||
{
|
{
|
||||||
get => _unstagedChangeViewMode;
|
get => _unstagedChangeViewMode;
|
||||||
|
@ -430,16 +436,21 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
var collection = to == null ? RepositoryNodes : to.SubNodes;
|
var collection = to == null ? RepositoryNodes : to.SubNodes;
|
||||||
collection.Add(node);
|
collection.Add(node);
|
||||||
collection.Sort((l, r) =>
|
SortNodes(collection);
|
||||||
|
|
||||||
|
if (save)
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SortNodes(List<RepositoryNode> collection)
|
||||||
|
{
|
||||||
|
collection?.Sort((l, r) =>
|
||||||
{
|
{
|
||||||
if (l.IsRepository != r.IsRepository)
|
if (l.IsRepository != r.IsRepository)
|
||||||
return l.IsRepository ? 1 : -1;
|
return l.IsRepository ? 1 : -1;
|
||||||
|
|
||||||
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
|
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (save)
|
|
||||||
Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepositoryNode FindNode(string id)
|
public RepositoryNode FindNode(string id)
|
||||||
|
@ -447,11 +458,9 @@ namespace SourceGit.ViewModels
|
||||||
return FindNodeRecursive(id, RepositoryNodes);
|
return FindNodeRecursive(id, RepositoryNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepositoryNode FindOrAddNodeByRepositoryPath(string repo, RepositoryNode parent, bool shouldMoveNode)
|
public RepositoryNode FindOrAddNodeByRepositoryPath(string repo, RepositoryNode parent, bool shouldMoveNode, bool save = true)
|
||||||
{
|
{
|
||||||
var normalized = repo.Replace('\\', '/');
|
var normalized = repo.Replace('\\', '/').TrimEnd('/');
|
||||||
if (normalized.EndsWith("/"))
|
|
||||||
normalized = normalized.TrimEnd('/');
|
|
||||||
|
|
||||||
var node = FindNodeRecursive(normalized, RepositoryNodes);
|
var node = FindNodeRecursive(normalized, RepositoryNodes);
|
||||||
if (node == null)
|
if (node == null)
|
||||||
|
@ -464,11 +473,11 @@ namespace SourceGit.ViewModels
|
||||||
IsRepository = true,
|
IsRepository = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddNode(node, parent, true);
|
AddNode(node, parent, save);
|
||||||
}
|
}
|
||||||
else if (shouldMoveNode)
|
else if (shouldMoveNode)
|
||||||
{
|
{
|
||||||
MoveNode(node, parent, true);
|
MoveNode(node, parent, save);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
@ -499,22 +508,13 @@ namespace SourceGit.ViewModels
|
||||||
public void SortByRenamedNode(RepositoryNode node)
|
public void SortByRenamedNode(RepositoryNode node)
|
||||||
{
|
{
|
||||||
var container = FindNodeContainer(node, RepositoryNodes);
|
var container = FindNodeContainer(node, RepositoryNodes);
|
||||||
container?.Sort((l, r) =>
|
SortNodes(container);
|
||||||
{
|
|
||||||
if (l.IsRepository != r.IsRepository)
|
|
||||||
return l.IsRepository ? 1 : -1;
|
|
||||||
|
|
||||||
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
|
|
||||||
});
|
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AutoRemoveInvalidNode()
|
public void AutoRemoveInvalidNode()
|
||||||
{
|
{
|
||||||
var changed = RemoveInvalidRepositoriesRecursive(RepositoryNodes);
|
RemoveInvalidRepositoriesRecursive(RepositoryNodes);
|
||||||
if (changed)
|
|
||||||
Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
|
@ -584,6 +584,13 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SortNodesRecursive(List<RepositoryNode> collection)
|
||||||
|
{
|
||||||
|
SortNodes(collection);
|
||||||
|
foreach (var node in collection)
|
||||||
|
SortNodesRecursive(node.SubNodes);
|
||||||
|
}
|
||||||
|
|
||||||
private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection)
|
private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection)
|
||||||
{
|
{
|
||||||
foreach (var node in collection)
|
foreach (var node in collection)
|
||||||
|
@ -661,7 +668,7 @@ namespace SourceGit.ViewModels
|
||||||
private string _themeOverrides = string.Empty;
|
private string _themeOverrides = string.Empty;
|
||||||
private string _defaultFontFamily = string.Empty;
|
private string _defaultFontFamily = string.Empty;
|
||||||
private string _monospaceFontFamily = string.Empty;
|
private string _monospaceFontFamily = string.Empty;
|
||||||
private bool _onlyUseMonoFontInEditor = false;
|
private bool _onlyUseMonoFontInEditor = true;
|
||||||
private double _defaultFontSize = 13;
|
private double _defaultFontSize = 13;
|
||||||
private double _editorFontSize = 13;
|
private double _editorFontSize = 13;
|
||||||
private int _editorTabWidth = 4;
|
private int _editorTabWidth = 4;
|
||||||
|
@ -687,6 +694,7 @@ namespace SourceGit.ViewModels
|
||||||
private bool _showHiddenSymbolsInDiffView = false;
|
private bool _showHiddenSymbolsInDiffView = false;
|
||||||
private bool _useFullTextDiff = false;
|
private bool _useFullTextDiff = false;
|
||||||
private bool _useBlockNavigationInDiffView = false;
|
private bool _useBlockNavigationInDiffView = false;
|
||||||
|
private int _lfsImageActiveIdx = 0;
|
||||||
|
|
||||||
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
|
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
|
||||||
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;
|
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
if (value != null)
|
if (value != null)
|
||||||
{
|
{
|
||||||
var normalized = value.Replace('\\', '/');
|
var normalized = value.Replace('\\', '/').TrimEnd('/');
|
||||||
SetProperty(ref _fullpath, normalized);
|
SetProperty(ref _fullpath, normalized);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -127,12 +127,12 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public bool OnlyHighlightCurrentBranchInHistories
|
public bool OnlyHighlightCurrentBranchInHistories
|
||||||
{
|
{
|
||||||
get => _settings.OnlyHighlighCurrentBranchInHistories;
|
get => _settings.OnlyHighlightCurrentBranchInHistories;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value != _settings.OnlyHighlighCurrentBranchInHistories)
|
if (value != _settings.OnlyHighlightCurrentBranchInHistories)
|
||||||
{
|
{
|
||||||
_settings.OnlyHighlighCurrentBranchInHistories = value;
|
_settings.OnlyHighlightCurrentBranchInHistories = value;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,6 +434,21 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsSortingLocalBranchByName
|
||||||
|
{
|
||||||
|
get => _settings.LocalBranchSortMode == Models.BranchSortMode.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSortingRemoteBranchByName
|
||||||
|
{
|
||||||
|
get => _settings.RemoteBranchSortMode == Models.BranchSortMode.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSortingTagsByName
|
||||||
|
{
|
||||||
|
get => _settings.TagSortMode == Models.TagSortMode.Name;
|
||||||
|
}
|
||||||
|
|
||||||
public InProgressContext InProgressContext
|
public InProgressContext InProgressContext
|
||||||
{
|
{
|
||||||
get => _workingCopy?.InProgressContext;
|
get => _workingCopy?.InProgressContext;
|
||||||
|
@ -499,7 +514,7 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
// For worktrees, we need to watch the $GIT_COMMON_DIR instead of the $GIT_DIR.
|
// For worktrees, we need to watch the $GIT_COMMON_DIR instead of the $GIT_DIR.
|
||||||
var gitDirForWatcher = _gitDir;
|
var gitDirForWatcher = _gitDir;
|
||||||
if (_gitDir.Replace("\\", "/").IndexOf("/worktrees/", StringComparison.Ordinal) > 0)
|
if (_gitDir.Replace('\\', '/').IndexOf("/worktrees/", StringComparison.Ordinal) > 0)
|
||||||
{
|
{
|
||||||
var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result();
|
var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result();
|
||||||
if (!string.IsNullOrEmpty(commonDir))
|
if (!string.IsNullOrEmpty(commonDir))
|
||||||
|
@ -772,7 +787,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
if (_currentBranch == null)
|
if (_currentBranch == null)
|
||||||
{
|
{
|
||||||
App.RaiseException(_fullpath, "Can NOT found current branch!!!");
|
App.RaiseException(_fullpath, "Can NOT find current branch!!!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,7 +811,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
if (_currentBranch == null)
|
if (_currentBranch == null)
|
||||||
{
|
{
|
||||||
App.RaiseException(_fullpath, "Can NOT found current branch!!!");
|
App.RaiseException(_fullpath, "Can NOT find current branch!!!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,7 +1135,8 @@ namespace SourceGit.ViewModels
|
||||||
if (_workingCopy != null)
|
if (_workingCopy != null)
|
||||||
_workingCopy.HasRemotes = remotes.Count > 0;
|
_workingCopy.HasRemotes = remotes.Count > 0;
|
||||||
|
|
||||||
GetOwnerPage()?.ChangeDirtyState(Models.DirtyState.HasPendingPullOrPush, !CurrentBranch.TrackStatus.IsVisible);
|
var hasPendingPullOrPush = CurrentBranch?.TrackStatus.IsVisible ?? false;
|
||||||
|
GetOwnerPage()?.ChangeDirtyState(Models.DirtyState.HasPendingPullOrPush, !hasPendingPullOrPush);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1288,7 +1304,7 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
if (_currentBranch == null)
|
if (_currentBranch == null)
|
||||||
{
|
{
|
||||||
App.RaiseException(_fullpath, "Git do not hold any branch until you do first commit.");
|
App.RaiseException(_fullpath, "Git cannot create a branch before your first commit.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1354,7 +1370,7 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
if (_currentBranch == null)
|
if (_currentBranch == null)
|
||||||
{
|
{
|
||||||
App.RaiseException(_fullpath, "Git do not hold any branch until you do first commit.");
|
App.RaiseException(_fullpath, "Git cannot create a branch before your first commit.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1387,7 +1403,7 @@ namespace SourceGit.ViewModels
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
|
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
|
||||||
var normalizedPath = root.Replace("\\", "/");
|
var normalizedPath = root.Replace('\\', '/').TrimEnd('/');
|
||||||
|
|
||||||
var node = Preferences.Instance.FindNode(normalizedPath);
|
var node = Preferences.Instance.FindNode(normalizedPath);
|
||||||
if (node == null)
|
if (node == null)
|
||||||
|
@ -1401,7 +1417,7 @@ namespace SourceGit.ViewModels
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
App.GetLauncer().OpenRepositoryInTab(node, null);
|
App.GetLauncher().OpenRepositoryInTab(node, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddWorktree()
|
public void AddWorktree()
|
||||||
|
@ -1430,10 +1446,10 @@ namespace SourceGit.ViewModels
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
App.GetLauncer()?.OpenRepositoryInTab(node, null);
|
App.GetLauncher()?.OpenRepositoryInTab(node, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Models.OpenAIService> GetPreferedOpenAIServices()
|
public List<Models.OpenAIService> GetPreferredOpenAIServices()
|
||||||
{
|
{
|
||||||
var services = Preferences.Instance.OpenAIServices;
|
var services = Preferences.Instance.OpenAIServices;
|
||||||
if (services == null || services.Count == 0)
|
if (services == null || services.Count == 0)
|
||||||
|
@ -1442,11 +1458,11 @@ namespace SourceGit.ViewModels
|
||||||
if (services.Count == 1)
|
if (services.Count == 1)
|
||||||
return [services[0]];
|
return [services[0]];
|
||||||
|
|
||||||
var prefered = _settings.PreferedOpenAIService;
|
var preferred = _settings.PreferredOpenAIService;
|
||||||
var all = new List<Models.OpenAIService>();
|
var all = new List<Models.OpenAIService>();
|
||||||
foreach (var service in services)
|
foreach (var service in services)
|
||||||
{
|
{
|
||||||
if (service.Name.Equals(prefered, StringComparison.Ordinal))
|
if (service.Name.Equals(preferred, StringComparison.Ordinal))
|
||||||
return [service];
|
return [service];
|
||||||
|
|
||||||
all.Add(service);
|
all.Add(service);
|
||||||
|
@ -2380,9 +2396,15 @@ namespace SourceGit.ViewModels
|
||||||
var changeMode = new Action<Models.BranchSortMode>(m =>
|
var changeMode = new Action<Models.BranchSortMode>(m =>
|
||||||
{
|
{
|
||||||
if (local)
|
if (local)
|
||||||
|
{
|
||||||
_settings.LocalBranchSortMode = m;
|
_settings.LocalBranchSortMode = m;
|
||||||
|
OnPropertyChanged(nameof(IsSortingLocalBranchByName));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
_settings.RemoteBranchSortMode = m;
|
_settings.RemoteBranchSortMode = m;
|
||||||
|
OnPropertyChanged(nameof(IsSortingRemoteBranchByName));
|
||||||
|
}
|
||||||
|
|
||||||
var builder = BuildBranchTree(_branches, _remotes);
|
var builder = BuildBranchTree(_branches, _remotes);
|
||||||
LocalBranchTrees = builder.Locals;
|
LocalBranchTrees = builder.Locals;
|
||||||
|
@ -2414,6 +2436,7 @@ namespace SourceGit.ViewModels
|
||||||
};
|
};
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
|
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
||||||
menu.Items.Add(byNameAsc);
|
menu.Items.Add(byNameAsc);
|
||||||
menu.Items.Add(byCommitterDate);
|
menu.Items.Add(byCommitterDate);
|
||||||
return menu;
|
return menu;
|
||||||
|
@ -2427,6 +2450,7 @@ namespace SourceGit.ViewModels
|
||||||
if (_settings.TagSortMode != m)
|
if (_settings.TagSortMode != m)
|
||||||
{
|
{
|
||||||
_settings.TagSortMode = m;
|
_settings.TagSortMode = m;
|
||||||
|
OnPropertyChanged(nameof(IsSortingTagsByName));
|
||||||
VisibleTags = BuildVisibleTags();
|
VisibleTags = BuildVisibleTags();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2441,30 +2465,20 @@ namespace SourceGit.ViewModels
|
||||||
ev.Handled = true;
|
ev.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
var byNameAsc = new MenuItem();
|
var byName = new MenuItem();
|
||||||
byNameAsc.Header = App.Text("Repository.Tags.OrderByNameAsc");
|
byName.Header = App.Text("Repository.Tags.OrderByName");
|
||||||
if (mode == Models.TagSortMode.NameInAscending)
|
if (mode == Models.TagSortMode.Name)
|
||||||
byNameAsc.Icon = App.CreateMenuIcon("Icons.Check");
|
byName.Icon = App.CreateMenuIcon("Icons.Check");
|
||||||
byNameAsc.Click += (_, ev) =>
|
byName.Click += (_, ev) =>
|
||||||
{
|
{
|
||||||
changeMode(Models.TagSortMode.NameInAscending);
|
changeMode(Models.TagSortMode.Name);
|
||||||
ev.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var byNameDes = new MenuItem();
|
|
||||||
byNameDes.Header = App.Text("Repository.Tags.OrderByNameDes");
|
|
||||||
if (mode == Models.TagSortMode.NameInDescending)
|
|
||||||
byNameDes.Icon = App.CreateMenuIcon("Icons.Check");
|
|
||||||
byNameDes.Click += (_, ev) =>
|
|
||||||
{
|
|
||||||
changeMode(Models.TagSortMode.NameInDescending);
|
|
||||||
ev.Handled = true;
|
ev.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
|
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
||||||
menu.Items.Add(byCreatorDate);
|
menu.Items.Add(byCreatorDate);
|
||||||
menu.Items.Add(byNameAsc);
|
menu.Items.Add(byName);
|
||||||
menu.Items.Add(byNameDes);
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2588,7 +2602,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
private LauncherPage GetOwnerPage()
|
private LauncherPage GetOwnerPage()
|
||||||
{
|
{
|
||||||
var launcher = App.GetLauncer();
|
var launcher = App.GetLauncher();
|
||||||
if (launcher == null)
|
if (launcher == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -2637,11 +2651,8 @@ namespace SourceGit.ViewModels
|
||||||
case Models.TagSortMode.CreatorDate:
|
case Models.TagSortMode.CreatorDate:
|
||||||
_tags.Sort((l, r) => r.CreatorDate.CompareTo(l.CreatorDate));
|
_tags.Sort((l, r) => r.CreatorDate.CompareTo(l.CreatorDate));
|
||||||
break;
|
break;
|
||||||
case Models.TagSortMode.NameInAscending:
|
|
||||||
_tags.Sort((l, r) => Models.NumericSort.Compare(l.Name, r.Name));
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
_tags.Sort((l, r) => Models.NumericSort.Compare(r.Name, l.Name));
|
_tags.Sort((l, r) => Models.NumericSort.Compare(l.Name, r.Name));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,10 +127,10 @@ namespace SourceGit.ViewModels
|
||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string PreferedOpenAIService
|
public string PreferredOpenAIService
|
||||||
{
|
{
|
||||||
get => _repo.Settings.PreferedOpenAIService;
|
get => _repo.Settings.PreferredOpenAIService;
|
||||||
set => _repo.Settings.PreferedOpenAIService = value;
|
set => _repo.Settings.PreferredOpenAIService = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AvaloniaList<Models.CustomAction> CustomActions
|
public AvaloniaList<Models.CustomAction> CustomActions
|
||||||
|
@ -156,8 +156,8 @@ namespace SourceGit.ViewModels
|
||||||
foreach (var service in Preferences.Instance.OpenAIServices)
|
foreach (var service in Preferences.Instance.OpenAIServices)
|
||||||
AvailableOpenAIServices.Add(service.Name);
|
AvailableOpenAIServices.Add(service.Name);
|
||||||
|
|
||||||
if (AvailableOpenAIServices.IndexOf(PreferedOpenAIService) == -1)
|
if (AvailableOpenAIServices.IndexOf(PreferredOpenAIService) == -1)
|
||||||
PreferedOpenAIService = "---";
|
PreferredOpenAIService = "---";
|
||||||
|
|
||||||
_cached = new Commands.Config(repo.FullPath).ListAll();
|
_cached = new Commands.Config(repo.FullPath).ListAll();
|
||||||
if (_cached.TryGetValue("user.name", out var name))
|
if (_cached.TryGetValue("user.name", out var name))
|
||||||
|
@ -304,6 +304,18 @@ namespace SourceGit.ViewModels
|
||||||
SelectedCustomAction = null;
|
SelectedCustomAction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void MoveSelectedCustomActionUp()
|
||||||
|
{
|
||||||
|
if (_selectedCustomAction != null)
|
||||||
|
_repo.Settings.MoveCustomActionUp(_selectedCustomAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveSelectedCustomActionDown()
|
||||||
|
{
|
||||||
|
if (_selectedCustomAction != null)
|
||||||
|
_repo.Settings.MoveCustomActionDown(_selectedCustomAction);
|
||||||
|
}
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
SetIfChanged("user.name", UserName, "");
|
SetIfChanged("user.name", UserName, "");
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace SourceGit.ViewModels
|
||||||
get => _id;
|
get => _id;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var normalized = value.Replace('\\', '/');
|
var normalized = value.Replace('\\', '/').TrimEnd('/');
|
||||||
SetProperty(ref _id, normalized);
|
SetProperty(ref _id, normalized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,14 +70,14 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public void Edit()
|
public void Edit()
|
||||||
{
|
{
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage != null && activePage.CanCreatePopup())
|
if (activePage != null && activePage.CanCreatePopup())
|
||||||
activePage.Popup = new EditRepositoryNode(this);
|
activePage.Popup = new EditRepositoryNode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSubFolder()
|
public void AddSubFolder()
|
||||||
{
|
{
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage != null && activePage.CanCreatePopup())
|
if (activePage != null && activePage.CanCreatePopup())
|
||||||
activePage.Popup = new CreateGroup(this);
|
activePage.Popup = new CreateGroup(this);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public void Delete()
|
public void Delete()
|
||||||
{
|
{
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage != null && activePage.CanCreatePopup())
|
if (activePage != null && activePage.CanCreatePopup())
|
||||||
activePage.Popup = new DeleteRepositoryNode(this);
|
activePage.Popup = new DeleteRepositoryNode(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public void NavigateTo(string commitSHA)
|
public void NavigateTo(string commitSHA)
|
||||||
{
|
{
|
||||||
var launcher = App.GetLauncer();
|
var launcher = App.GetLauncher();
|
||||||
if (launcher == null)
|
if (launcher == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
34
src/ViewModels/RevisionLFSImage.cs
Normal file
34
src/ViewModels/RevisionLFSImage.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace SourceGit.ViewModels
|
||||||
|
{
|
||||||
|
public class RevisionLFSImage : ObservableObject
|
||||||
|
{
|
||||||
|
public Models.RevisionLFSObject LFS
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Models.RevisionImageFile Image
|
||||||
|
{
|
||||||
|
get => _image;
|
||||||
|
private set => SetProperty(ref _image, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RevisionLFSImage(string repo, string file, Models.LFSObject lfs, Models.ImageDecoder decoder)
|
||||||
|
{
|
||||||
|
LFS = new Models.RevisionLFSObject() { Object = lfs };
|
||||||
|
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
var source = ImageSource.FromLFSObject(repo, lfs, decoder);
|
||||||
|
var img = new Models.RevisionImageFile(file, source.Bitmap, source.Size);
|
||||||
|
Dispatcher.UIThread.Invoke(() => Image = img);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Models.RevisionImageFile _image = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,8 +31,8 @@ namespace SourceGit.ViewModels
|
||||||
watch.Start();
|
watch.Start();
|
||||||
|
|
||||||
var rootDir = new DirectoryInfo(RootDir);
|
var rootDir = new DirectoryInfo(RootDir);
|
||||||
var founded = new List<FoundRepository>();
|
var found = new List<string>();
|
||||||
GetUnmanagedRepositories(rootDir, founded, new EnumerationOptions()
|
GetUnmanagedRepositories(rootDir, found, new EnumerationOptions()
|
||||||
{
|
{
|
||||||
AttributesToSkip = FileAttributes.Hidden | FileAttributes.System,
|
AttributesToSkip = FileAttributes.Hidden | FileAttributes.System,
|
||||||
IgnoreInaccessible = true,
|
IgnoreInaccessible = true,
|
||||||
|
@ -46,24 +46,27 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
Dispatcher.UIThread.Invoke(() =>
|
Dispatcher.UIThread.Invoke(() =>
|
||||||
{
|
{
|
||||||
var normalizedRoot = rootDir.FullName.Replace("\\", "/");
|
var normalizedRoot = rootDir.FullName.Replace('\\', '/').TrimEnd('/');
|
||||||
|
|
||||||
foreach (var f in founded)
|
foreach (var f in found)
|
||||||
{
|
{
|
||||||
var parent = new DirectoryInfo(f.Path).Parent!.FullName.Replace("\\", "/");
|
var parent = new DirectoryInfo(f).Parent!.FullName.Replace('\\', '/').TrimEnd('/');
|
||||||
if (parent.Equals(normalizedRoot, StringComparison.Ordinal))
|
if (parent.Equals(normalizedRoot, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
Preferences.Instance.FindOrAddNodeByRepositoryPath(f.Path, null, false);
|
Preferences.Instance.FindOrAddNodeByRepositoryPath(f, null, false, false);
|
||||||
}
|
}
|
||||||
else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal))
|
else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
var relative = parent.Substring(normalizedRoot.Length).TrimStart('/');
|
var relative = parent.Substring(normalizedRoot.Length).TrimStart('/');
|
||||||
var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative);
|
var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative);
|
||||||
Preferences.Instance.FindOrAddNodeByRepositoryPath(f.Path, group, false);
|
Preferences.Instance.FindOrAddNodeByRepositoryPath(f, group, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Preferences.Instance.AutoRemoveInvalidNode();
|
Preferences.Instance.AutoRemoveInvalidNode();
|
||||||
|
Preferences.Instance.SortNodes(Preferences.Instance.RepositoryNodes);
|
||||||
|
Preferences.Instance.Save();
|
||||||
|
|
||||||
Welcome.Instance.Refresh();
|
Welcome.Instance.Refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -82,7 +85,7 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetUnmanagedRepositories(DirectoryInfo dir, List<FoundRepository> outs, EnumerationOptions opts, int depth = 0)
|
private void GetUnmanagedRepositories(DirectoryInfo dir, List<string> outs, EnumerationOptions opts, int depth = 0)
|
||||||
{
|
{
|
||||||
var subdirs = dir.GetDirectories("*", opts);
|
var subdirs = dir.GetDirectories("*", opts);
|
||||||
foreach (var subdir in subdirs)
|
foreach (var subdir in subdirs)
|
||||||
|
@ -93,7 +96,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
CallUIThread(() => ProgressDescription = $"Scanning {subdir.FullName}...");
|
CallUIThread(() => ProgressDescription = $"Scanning {subdir.FullName}...");
|
||||||
|
|
||||||
var normalizedSelf = subdir.FullName.Replace("\\", "/");
|
var normalizedSelf = subdir.FullName.Replace('\\', '/').TrimEnd('/');
|
||||||
if (_managed.Contains(normalizedSelf))
|
if (_managed.Contains(normalizedSelf))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -103,9 +106,9 @@ namespace SourceGit.ViewModels
|
||||||
var test = new Commands.QueryRepositoryRootPath(subdir.FullName).ReadToEnd();
|
var test = new Commands.QueryRepositoryRootPath(subdir.FullName).ReadToEnd();
|
||||||
if (test.IsSuccess && !string.IsNullOrEmpty(test.StdOut))
|
if (test.IsSuccess && !string.IsNullOrEmpty(test.StdOut))
|
||||||
{
|
{
|
||||||
var normalized = test.StdOut.Trim().Replace("\\", "/");
|
var normalized = test.StdOut.Trim().Replace('\\', '/').TrimEnd('/');
|
||||||
if (!_managed.Contains(normalized))
|
if (!_managed.Contains(normalized))
|
||||||
outs.Add(new FoundRepository(normalized, false));
|
outs.Add(normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -114,7 +117,7 @@ namespace SourceGit.ViewModels
|
||||||
var isBare = new Commands.IsBareRepository(subdir.FullName).Result();
|
var isBare = new Commands.IsBareRepository(subdir.FullName).Result();
|
||||||
if (isBare)
|
if (isBare)
|
||||||
{
|
{
|
||||||
outs.Add(new FoundRepository(normalizedSelf, true));
|
outs.Add(normalizedSelf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,23 +154,11 @@ namespace SourceGit.ViewModels
|
||||||
IsExpanded = true,
|
IsExpanded = true,
|
||||||
};
|
};
|
||||||
collection.Add(added);
|
collection.Add(added);
|
||||||
collection.Sort((l, r) =>
|
Preferences.Instance.SortNodes(collection);
|
||||||
{
|
|
||||||
if (l.IsRepository != r.IsRepository)
|
|
||||||
return l.IsRepository ? 1 : -1;
|
|
||||||
|
|
||||||
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
|
|
||||||
});
|
|
||||||
|
|
||||||
return added;
|
return added;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record FoundRepository(string path, bool isBare)
|
private HashSet<string> _managed = new();
|
||||||
{
|
|
||||||
public string Path { get; set; } = path;
|
|
||||||
public bool IsBare { get; set; } = isBare;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HashSet<string> _managed = new HashSet<string>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,10 +234,28 @@ namespace SourceGit.ViewModels
|
||||||
var resetToThisRevision = new MenuItem();
|
var resetToThisRevision = new MenuItem();
|
||||||
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
|
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
|
||||||
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
|
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
|
||||||
resetToThisRevision.Click += (_, ev) =>
|
resetToThisRevision.Click += async (_, ev) =>
|
||||||
{
|
{
|
||||||
var log = _repo.CreateLog($"Reset File to '{_selectedStash.SHA}'");
|
var log = _repo.CreateLog($"Reset File to '{_selectedStash.SHA}'");
|
||||||
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_selectedStash.SHA}");
|
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
if (_untracked.Contains(change))
|
||||||
|
{
|
||||||
|
Commands.SaveRevisionFile.Run(_repo.FullPath, _selectedStash.Parents[2], change.Path, fullPath);
|
||||||
|
}
|
||||||
|
else if (change.Index == Models.ChangeState.Added)
|
||||||
|
{
|
||||||
|
Commands.SaveRevisionFile.Run(_repo.FullPath, _selectedStash.SHA, change.Path, fullPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new Commands.Checkout(_repo.FullPath)
|
||||||
|
.Use(log)
|
||||||
|
.FileWithRevision(change.Path, $"{_selectedStash.SHA}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
log.Complete();
|
log.Complete();
|
||||||
ev.Handled = true;
|
ev.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace SourceGit.ViewModels
|
||||||
Counter = 1;
|
Counter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SubmoduleTreeNode> Build(IList<Models.Submodule> submodules, HashSet<string> expaneded)
|
public static List<SubmoduleTreeNode> Build(IList<Models.Submodule> submodules, HashSet<string> expanded)
|
||||||
{
|
{
|
||||||
var nodes = new List<SubmoduleTreeNode>();
|
var nodes = new List<SubmoduleTreeNode>();
|
||||||
var folders = new Dictionary<string, SubmoduleTreeNode>();
|
var folders = new Dictionary<string, SubmoduleTreeNode>();
|
||||||
|
@ -79,13 +79,13 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
else if (lastFolder == null)
|
else if (lastFolder == null)
|
||||||
{
|
{
|
||||||
lastFolder = new SubmoduleTreeNode(folder, depth, expaneded.Contains(folder));
|
lastFolder = new SubmoduleTreeNode(folder, depth, expanded.Contains(folder));
|
||||||
folders.Add(folder, lastFolder);
|
folders.Add(folder, lastFolder);
|
||||||
InsertFolder(nodes, lastFolder);
|
InsertFolder(nodes, lastFolder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var cur = new SubmoduleTreeNode(folder, depth, expaneded.Contains(folder));
|
var cur = new SubmoduleTreeNode(folder, depth, expanded.Contains(folder));
|
||||||
folders.Add(folder, cur);
|
folders.Add(folder, cur);
|
||||||
InsertFolder(lastFolder.Children, cur);
|
InsertFolder(lastFolder.Children, cur);
|
||||||
lastFolder = cur;
|
lastFolder = cur;
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace SourceGit.ViewModels
|
||||||
Counter = 1;
|
Counter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<TagTreeNode> Build(List<Models.Tag> tags, HashSet<string> expaneded)
|
public static List<TagTreeNode> Build(List<Models.Tag> tags, HashSet<string> expanded)
|
||||||
{
|
{
|
||||||
var nodes = new List<TagTreeNode>();
|
var nodes = new List<TagTreeNode>();
|
||||||
var folders = new Dictionary<string, TagTreeNode>();
|
var folders = new Dictionary<string, TagTreeNode>();
|
||||||
|
@ -90,13 +90,13 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
else if (lastFolder == null)
|
else if (lastFolder == null)
|
||||||
{
|
{
|
||||||
lastFolder = new TagTreeNode(folder, expaneded.Contains(folder), depth);
|
lastFolder = new TagTreeNode(folder, expanded.Contains(folder), depth);
|
||||||
folders.Add(folder, lastFolder);
|
folders.Add(folder, lastFolder);
|
||||||
InsertFolder(nodes, lastFolder);
|
InsertFolder(nodes, lastFolder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var cur = new TagTreeNode(folder, expaneded.Contains(folder), depth);
|
var cur = new TagTreeNode(folder, expanded.Contains(folder), depth);
|
||||||
folders.Add(folder, cur);
|
folders.Add(folder, cur);
|
||||||
InsertFolder(lastFolder.Children, cur);
|
InsertFolder(lastFolder.Children, cur);
|
||||||
lastFolder = cur;
|
lastFolder = cur;
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace SourceGit.ViewModels
|
||||||
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(repoRoot, parent, bMoveExistedNode);
|
var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(repoRoot, parent, bMoveExistedNode);
|
||||||
Refresh();
|
Refresh();
|
||||||
|
|
||||||
var launcher = App.GetLauncer();
|
var launcher = App.GetLauncher();
|
||||||
launcher?.OpenRepositoryInTab(node, launcher.ActivePage);
|
launcher?.OpenRepositoryInTab(node, launcher.ActivePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ namespace SourceGit.ViewModels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage != null && activePage.CanCreatePopup())
|
if (activePage != null && activePage.CanCreatePopup())
|
||||||
activePage.Popup = new Init(activePage.Node.Id, path, parent, reason);
|
activePage.Popup = new Init(activePage.Node.Id, path, parent, reason);
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ namespace SourceGit.ViewModels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage != null && activePage.CanCreatePopup())
|
if (activePage != null && activePage.CanCreatePopup())
|
||||||
activePage.Popup = new Clone(activePage.Node.Id);
|
activePage.Popup = new Clone(activePage.Node.Id);
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ namespace SourceGit.ViewModels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage != null && activePage.CanCreatePopup())
|
if (activePage != null && activePage.CanCreatePopup())
|
||||||
activePage.StartPopup(new ScanRepositories(defaultCloneDir));
|
activePage.StartPopup(new ScanRepositories(defaultCloneDir));
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public void AddRootNode()
|
public void AddRootNode()
|
||||||
{
|
{
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage != null && activePage.CanCreatePopup())
|
if (activePage != null && activePage.CanCreatePopup())
|
||||||
activePage.Popup = new CreateGroup(null);
|
activePage.Popup = new CreateGroup(null);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ namespace SourceGit.ViewModels
|
||||||
openAll.Icon = App.CreateMenuIcon("Icons.Folder.Open");
|
openAll.Icon = App.CreateMenuIcon("Icons.Folder.Open");
|
||||||
openAll.Click += (_, e) =>
|
openAll.Click += (_, e) =>
|
||||||
{
|
{
|
||||||
OpenAllInNode(App.GetLauncer(), node);
|
OpenAllInNode(App.GetLauncher(), node);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ namespace SourceGit.ViewModels
|
||||||
open.Icon = App.CreateMenuIcon("Icons.Folder.Open");
|
open.Icon = App.CreateMenuIcon("Icons.Folder.Open");
|
||||||
open.Click += (_, e) =>
|
open.Click += (_, e) =>
|
||||||
{
|
{
|
||||||
App.GetLauncer()?.OpenRepositoryInTab(node, null);
|
App.GetLauncher()?.OpenRepositoryInTab(node, null);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ namespace SourceGit.ViewModels
|
||||||
move.Icon = App.CreateMenuIcon("Icons.MoveToAnotherGroup");
|
move.Icon = App.CreateMenuIcon("Icons.MoveToAnotherGroup");
|
||||||
move.Click += (_, e) =>
|
move.Click += (_, e) =>
|
||||||
{
|
{
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage != null && activePage.CanCreatePopup())
|
if (activePage != null && activePage.CanCreatePopup())
|
||||||
activePage.Popup = new MoveRepositoryNode(node);
|
activePage.Popup = new MoveRepositoryNode(node);
|
||||||
|
|
||||||
|
|
|
@ -780,7 +780,7 @@ namespace SourceGit.ViewModels
|
||||||
byParentFolder.IsVisible = !isRooted;
|
byParentFolder.IsVisible = !isRooted;
|
||||||
byParentFolder.Click += (_, e) =>
|
byParentFolder.Click += (_, e) =>
|
||||||
{
|
{
|
||||||
var dir = Path.GetDirectoryName(change.Path)!.Replace("\\", "/");
|
var dir = Path.GetDirectoryName(change.Path)!.Replace('\\', '/').TrimEnd('/');
|
||||||
Commands.GitIgnore.Add(_repo.FullPath, dir + "/");
|
Commands.GitIgnore.Add(_repo.FullPath, dir + "/");
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
@ -802,7 +802,7 @@ namespace SourceGit.ViewModels
|
||||||
byExtensionInSameFolder.IsVisible = !isRooted;
|
byExtensionInSameFolder.IsVisible = !isRooted;
|
||||||
byExtensionInSameFolder.Click += (_, e) =>
|
byExtensionInSameFolder.Click += (_, e) =>
|
||||||
{
|
{
|
||||||
var dir = Path.GetDirectoryName(change.Path)!.Replace("\\", "/");
|
var dir = Path.GetDirectoryName(change.Path)!.Replace('\\', '/').TrimEnd('/');
|
||||||
Commands.GitIgnore.Add(_repo.FullPath, $"{dir}/*{extension}");
|
Commands.GitIgnore.Add(_repo.FullPath, $"{dir}/*{extension}");
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
@ -1099,7 +1099,7 @@ namespace SourceGit.ViewModels
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
|
|
||||||
var ai = null as MenuItem;
|
var ai = null as MenuItem;
|
||||||
var services = _repo.GetPreferedOpenAIServices();
|
var services = _repo.GetPreferredOpenAIServices();
|
||||||
if (services.Count > 0)
|
if (services.Count > 0)
|
||||||
{
|
{
|
||||||
ai = new MenuItem();
|
ai = new MenuItem();
|
||||||
|
@ -1497,7 +1497,7 @@ namespace SourceGit.ViewModels
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var services = _repo.GetPreferedOpenAIServices();
|
var services = _repo.GetPreferredOpenAIServices();
|
||||||
if (services.Count == 0)
|
if (services.Count == 0)
|
||||||
{
|
{
|
||||||
App.RaiseException(_repo.FullPath, "Bad configuration for OpenAI");
|
App.RaiseException(_repo.FullPath, "Bad configuration for OpenAI");
|
||||||
|
@ -1707,7 +1707,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
if (!_repo.CanCreatePopup())
|
if (!_repo.CanCreatePopup())
|
||||||
{
|
{
|
||||||
App.RaiseException(_repo.FullPath, "Repository has unfinished job! Please wait!");
|
App.RaiseException(_repo.FullPath, "Repository has an unfinished job! Please wait!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
@ -8,6 +9,7 @@ using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Media.Imaging;
|
using Avalonia.Media.Imaging;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
|
@ -24,16 +26,6 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
public Avatar()
|
public Avatar()
|
||||||
{
|
{
|
||||||
var refetch = new MenuItem() { Header = App.Text("RefetchAvatar") };
|
|
||||||
refetch.Click += (_, _) =>
|
|
||||||
{
|
|
||||||
if (User != null)
|
|
||||||
Models.AvatarManager.Instance.Request(User.Email, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
ContextMenu = new ContextMenu();
|
|
||||||
ContextMenu.Items.Add(refetch);
|
|
||||||
|
|
||||||
RenderOptions.SetBitmapInterpolationMode(this, BitmapInterpolationMode.HighQuality);
|
RenderOptions.SetBitmapInterpolationMode(this, BitmapInterpolationMode.HighQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,11 +94,11 @@ namespace SourceGit.Views
|
||||||
clip.Dispose();
|
clip.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnAvatarResourceChanged(string email)
|
public void OnAvatarResourceChanged(string email, Bitmap image)
|
||||||
{
|
{
|
||||||
if (User.Email.Equals(email, StringComparison.Ordinal))
|
if (User.Email.Equals(email, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
_img = Models.AvatarManager.Instance.Request(User.Email, false);
|
_img = image;
|
||||||
InvalidateVisual();
|
InvalidateVisual();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,11 +107,13 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
base.OnLoaded(e);
|
base.OnLoaded(e);
|
||||||
Models.AvatarManager.Instance.Subscribe(this);
|
Models.AvatarManager.Instance.Subscribe(this);
|
||||||
|
ContextRequested += OnContextRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnUnloaded(RoutedEventArgs e)
|
protected override void OnUnloaded(RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnUnloaded(e);
|
base.OnUnloaded(e);
|
||||||
|
ContextRequested -= OnContextRequested;
|
||||||
Models.AvatarManager.Instance.Unsubscribe(this);
|
Models.AvatarManager.Instance.Unsubscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +132,94 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnContextRequested(object sender, ContextRequestedEventArgs e)
|
||||||
|
{
|
||||||
|
var toplevel = TopLevel.GetTopLevel(this);
|
||||||
|
if (toplevel == null)
|
||||||
|
{
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var refetch = new MenuItem();
|
||||||
|
refetch.Icon = App.CreateMenuIcon("Icons.Loading");
|
||||||
|
refetch.Header = App.Text("Avatar.Refetch");
|
||||||
|
refetch.Click += (_, ev) =>
|
||||||
|
{
|
||||||
|
if (User != null)
|
||||||
|
Models.AvatarManager.Instance.Request(User.Email, true);
|
||||||
|
|
||||||
|
ev.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var load = new MenuItem();
|
||||||
|
load.Icon = App.CreateMenuIcon("Icons.Folder.Open");
|
||||||
|
load.Header = App.Text("Avatar.Load");
|
||||||
|
load.Click += async (_, ev) =>
|
||||||
|
{
|
||||||
|
var options = new FilePickerOpenOptions()
|
||||||
|
{
|
||||||
|
FileTypeFilter = [new FilePickerFileType("PNG") { Patterns = ["*.png"] }],
|
||||||
|
AllowMultiple = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var selected = await toplevel.StorageProvider.OpenFilePickerAsync(options);
|
||||||
|
if (selected.Count == 1)
|
||||||
|
{
|
||||||
|
var localFile = selected[0].Path.LocalPath;
|
||||||
|
Models.AvatarManager.Instance.SetFromLocal(User.Email, localFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
ev.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var saveAs = new MenuItem();
|
||||||
|
saveAs.Icon = App.CreateMenuIcon("Icons.Save");
|
||||||
|
saveAs.Header = App.Text("SaveAs");
|
||||||
|
saveAs.Click += async (_, ev) =>
|
||||||
|
{
|
||||||
|
var options = new FilePickerSaveOptions();
|
||||||
|
options.Title = App.Text("SaveAs");
|
||||||
|
options.DefaultExtension = ".png";
|
||||||
|
options.FileTypeChoices = [new FilePickerFileType("PNG") { Patterns = ["*.png"] }];
|
||||||
|
|
||||||
|
var storageFile = await toplevel.StorageProvider.SaveFilePickerAsync(options);
|
||||||
|
if (storageFile != null)
|
||||||
|
{
|
||||||
|
var saveTo = storageFile.Path.LocalPath;
|
||||||
|
using (var writer = File.OpenWrite(saveTo))
|
||||||
|
{
|
||||||
|
if (_img != null)
|
||||||
|
{
|
||||||
|
_img.Save(writer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var pixelSize = new PixelSize((int)Bounds.Width, (int)Bounds.Height);
|
||||||
|
var dpi = new Vector(96, 96);
|
||||||
|
|
||||||
|
using (var rt = new RenderTargetBitmap(pixelSize, dpi))
|
||||||
|
using (var ctx = rt.CreateDrawingContext())
|
||||||
|
{
|
||||||
|
this.Render(ctx);
|
||||||
|
rt.Save(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ev.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var menu = new ContextMenu();
|
||||||
|
menu.Items.Add(refetch);
|
||||||
|
menu.Items.Add(load);
|
||||||
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
menu.Items.Add(saveAs);
|
||||||
|
|
||||||
|
menu.Open(this);
|
||||||
|
}
|
||||||
|
|
||||||
private Bitmap _img = null;
|
private Bitmap _img = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace SourceGit.Views
|
||||||
context.DrawLine(pen, new Point(j * 32, 0), new Point(j * 32, 192));
|
context.DrawLine(pen, new Point(j * 32, 0), new Point(j * 32, 192));
|
||||||
|
|
||||||
// Selected
|
// Selected
|
||||||
if (_hightlightedTableRect is { } rect)
|
if (_highlightedTableRect is { } rect)
|
||||||
context.DrawRectangle(new Pen(Brushes.White, 2), rect);
|
context.DrawRectangle(new Pen(Brushes.White, 2), rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ namespace SourceGit.Views
|
||||||
protected override void OnDataContextChanged(EventArgs e)
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnDataContextChanged(e);
|
base.OnDataContextChanged(e);
|
||||||
_hightlightedTableRect = null;
|
_highlightedTableRect = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Size MeasureOverride(Size availableSize)
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
|
@ -161,9 +161,9 @@ namespace SourceGit.Views
|
||||||
var col = (int)Math.Floor(p.X / 32.0);
|
var col = (int)Math.Floor(p.X / 32.0);
|
||||||
var row = (int)Math.Floor(p.Y / 32.0);
|
var row = (int)Math.Floor(p.Y / 32.0);
|
||||||
var rect = new Rect(col * 32 + 2, row * 32 + 2, 28, 28);
|
var rect = new Rect(col * 32 + 2, row * 32 + 2, 28, 28);
|
||||||
if (!rect.Equals(_hightlightedTableRect))
|
if (!rect.Equals(_highlightedTableRect))
|
||||||
{
|
{
|
||||||
_hightlightedTableRect = rect;
|
_highlightedTableRect = rect;
|
||||||
SetCurrentValue(ValueProperty, COLOR_TABLE[row, col].ToUInt32());
|
SetCurrentValue(ValueProperty, COLOR_TABLE[row, col].ToUInt32());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,32 +172,32 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
if (_darkestRect.Rect.Contains(p))
|
if (_darkestRect.Rect.Contains(p))
|
||||||
{
|
{
|
||||||
_hightlightedTableRect = null;
|
_highlightedTableRect = null;
|
||||||
SetCurrentValue(ValueProperty, _darkestColor.ToUInt32());
|
SetCurrentValue(ValueProperty, _darkestColor.ToUInt32());
|
||||||
}
|
}
|
||||||
else if (_darkerRect.Contains(p))
|
else if (_darkerRect.Contains(p))
|
||||||
{
|
{
|
||||||
_hightlightedTableRect = null;
|
_highlightedTableRect = null;
|
||||||
SetCurrentValue(ValueProperty, _darkerColor.ToUInt32());
|
SetCurrentValue(ValueProperty, _darkerColor.ToUInt32());
|
||||||
}
|
}
|
||||||
else if (_darkRect.Contains(p))
|
else if (_darkRect.Contains(p))
|
||||||
{
|
{
|
||||||
_hightlightedTableRect = null;
|
_highlightedTableRect = null;
|
||||||
SetCurrentValue(ValueProperty, _darkColor.ToUInt32());
|
SetCurrentValue(ValueProperty, _darkColor.ToUInt32());
|
||||||
}
|
}
|
||||||
else if (_lightRect.Contains(p))
|
else if (_lightRect.Contains(p))
|
||||||
{
|
{
|
||||||
_hightlightedTableRect = null;
|
_highlightedTableRect = null;
|
||||||
SetCurrentValue(ValueProperty, _lightColor.ToUInt32());
|
SetCurrentValue(ValueProperty, _lightColor.ToUInt32());
|
||||||
}
|
}
|
||||||
else if (_lighterRect.Contains(p))
|
else if (_lighterRect.Contains(p))
|
||||||
{
|
{
|
||||||
_hightlightedTableRect = null;
|
_highlightedTableRect = null;
|
||||||
SetCurrentValue(ValueProperty, _lighterColor.ToUInt32());
|
SetCurrentValue(ValueProperty, _lighterColor.ToUInt32());
|
||||||
}
|
}
|
||||||
else if (_lightestRect.Rect.Contains(p))
|
else if (_lightestRect.Rect.Contains(p))
|
||||||
{
|
{
|
||||||
_hightlightedTableRect = null;
|
_highlightedTableRect = null;
|
||||||
SetCurrentValue(ValueProperty, _lightestColor.ToUInt32());
|
SetCurrentValue(ValueProperty, _lightestColor.ToUInt32());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ namespace SourceGit.Views
|
||||||
private Rect _lightRect = new Rect(160, 200, 32, 32);
|
private Rect _lightRect = new Rect(160, 200, 32, 32);
|
||||||
private Rect _lighterRect = new Rect(192, 200, 32, 32);
|
private Rect _lighterRect = new Rect(192, 200, 32, 32);
|
||||||
private RoundedRect _lightestRect = new RoundedRect(new Rect(224, 200, 32, 32), new CornerRadius(0, 4, 4, 0));
|
private RoundedRect _lightestRect = new RoundedRect(new Rect(224, 200, 32, 32), new CornerRadius(0, 4, 4, 0));
|
||||||
private Rect? _hightlightedTableRect = null;
|
private Rect? _highlightedTableRect = null;
|
||||||
|
|
||||||
private Color _darkestColor;
|
private Color _darkestColor;
|
||||||
private Color _darkerColor;
|
private Color _darkerColor;
|
||||||
|
|
|
@ -48,8 +48,9 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
var inlines = new List<Inline>();
|
var inlines = new List<Inline>();
|
||||||
var pos = 0;
|
var pos = 0;
|
||||||
foreach (var link in links)
|
for (var i = 0; i < links.Count; i++)
|
||||||
{
|
{
|
||||||
|
var link = links[i];
|
||||||
if (link.Start > pos)
|
if (link.Start > pos)
|
||||||
inlines.Add(new Run(message.Substring(pos, link.Start - pos)));
|
inlines.Add(new Run(message.Substring(pos, link.Start - pos)));
|
||||||
|
|
||||||
|
@ -95,26 +96,10 @@ namespace SourceGit.Views
|
||||||
point = new Point(x, y);
|
point = new Point(x, y);
|
||||||
|
|
||||||
var pos = TextLayout.HitTestPoint(point).TextPosition;
|
var pos = TextLayout.HitTestPoint(point).TextPosition;
|
||||||
foreach (var link in links)
|
if (links.Intersect(pos, 1) is { } link)
|
||||||
{
|
SetHoveredIssueLink(link);
|
||||||
if (!link.Intersect(pos, 1))
|
else
|
||||||
continue;
|
ClearHoveredIssueLink();
|
||||||
|
|
||||||
if (link == _lastHover)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetCurrentValue(CursorProperty, Cursor.Parse("Hand"));
|
|
||||||
|
|
||||||
_lastHover = link;
|
|
||||||
if (link.Type == Models.InlineElementType.Link)
|
|
||||||
ToolTip.SetTip(this, link.Link);
|
|
||||||
else
|
|
||||||
ProcessHoverCommitLink(link);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClearHoveredIssueLink();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +276,20 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetHoveredIssueLink(Models.InlineElement link)
|
||||||
|
{
|
||||||
|
if (link == _lastHover)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetCurrentValue(CursorProperty, Cursor.Parse("Hand"));
|
||||||
|
|
||||||
|
_lastHover = link;
|
||||||
|
if (link.Type == Models.InlineElementType.Link)
|
||||||
|
ToolTip.SetTip(this, link.Link);
|
||||||
|
else
|
||||||
|
ProcessHoverCommitLink(link);
|
||||||
|
}
|
||||||
|
|
||||||
private void ClearHoveredIssueLink()
|
private void ClearHoveredIssueLink()
|
||||||
{
|
{
|
||||||
if (_lastHover != null)
|
if (_lastHover != null)
|
||||||
|
|
|
@ -151,11 +151,15 @@ namespace SourceGit.Views
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rules = IssueTrackerRules ?? [];
|
||||||
|
foreach (var rule in rules)
|
||||||
|
rule.Matches(_elements, subject);
|
||||||
|
|
||||||
var keywordMatch = REG_KEYWORD_FORMAT1().Match(subject);
|
var keywordMatch = REG_KEYWORD_FORMAT1().Match(subject);
|
||||||
if (!keywordMatch.Success)
|
if (!keywordMatch.Success)
|
||||||
keywordMatch = REG_KEYWORD_FORMAT2().Match(subject);
|
keywordMatch = REG_KEYWORD_FORMAT2().Match(subject);
|
||||||
|
|
||||||
if (keywordMatch.Success)
|
if (keywordMatch.Success && _elements.Intersect(0, keywordMatch.Length) == null)
|
||||||
_elements.Add(new Models.InlineElement(Models.InlineElementType.Keyword, 0, keywordMatch.Length, string.Empty));
|
_elements.Add(new Models.InlineElement(Models.InlineElementType.Keyword, 0, keywordMatch.Length, string.Empty));
|
||||||
|
|
||||||
var codeMatches = REG_INLINECODE_FORMAT().Matches(subject);
|
var codeMatches = REG_INLINECODE_FORMAT().Matches(subject);
|
||||||
|
@ -167,27 +171,13 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
var start = match.Index;
|
var start = match.Index;
|
||||||
var len = match.Length;
|
var len = match.Length;
|
||||||
var intersect = false;
|
if (_elements.Intersect(start, len) != null)
|
||||||
foreach (var exist in _elements)
|
|
||||||
{
|
|
||||||
if (exist.Intersect(start, len))
|
|
||||||
{
|
|
||||||
intersect = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intersect)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_elements.Add(new Models.InlineElement(Models.InlineElementType.Code, start, len, string.Empty));
|
_elements.Add(new Models.InlineElement(Models.InlineElementType.Code, start, len, string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
var rules = IssueTrackerRules ?? [];
|
_elements.Sort();
|
||||||
foreach (var rule in rules)
|
|
||||||
rule.Matches(_elements, subject);
|
|
||||||
|
|
||||||
_elements.Sort((l, r) => l.Start - r.Start);
|
|
||||||
_needRebuildInlines = true;
|
_needRebuildInlines = true;
|
||||||
InvalidateVisual();
|
InvalidateVisual();
|
||||||
}
|
}
|
||||||
|
@ -261,8 +251,9 @@ namespace SourceGit.Views
|
||||||
var codeTypeface = new Typeface(codeFontFamily, FontStyle.Normal, FontWeight);
|
var codeTypeface = new Typeface(codeFontFamily, FontStyle.Normal, FontWeight);
|
||||||
var pos = 0;
|
var pos = 0;
|
||||||
var x = 0.0;
|
var x = 0.0;
|
||||||
foreach (var elem in _elements)
|
for (var i = 0; i < _elements.Count; i++)
|
||||||
{
|
{
|
||||||
|
var elem = _elements[i];
|
||||||
if (elem.Start > pos)
|
if (elem.Start > pos)
|
||||||
{
|
{
|
||||||
var normal = new FormattedText(
|
var normal = new FormattedText(
|
||||||
|
@ -364,7 +355,7 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Models.InlineElement> _elements = [];
|
private Models.InlineElementCollector _elements = new();
|
||||||
private List<Inline> _inlines = [];
|
private List<Inline> _inlines = [];
|
||||||
private Models.InlineElement _lastHover = null;
|
private Models.InlineElement _lastHover = null;
|
||||||
private bool _needRebuildInlines = false;
|
private bool _needRebuildInlines = false;
|
||||||
|
|
|
@ -122,7 +122,7 @@
|
||||||
|
|
||||||
<ToggleButton Classes="line_path"
|
<ToggleButton Classes="line_path"
|
||||||
Width="28"
|
Width="28"
|
||||||
Command="{Binding ToggleFullTextDiff}"
|
Click="OnUseFullTextDiffClicked"
|
||||||
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
|
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
|
||||||
IsVisible="{Binding IsTextDiff}"
|
IsVisible="{Binding IsTextDiff}"
|
||||||
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.All}">
|
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.All}">
|
||||||
|
@ -213,7 +213,7 @@
|
||||||
<TextBlock Grid.Row="0" Grid.Column="2" Classes="primary" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" FontSize="16"/>
|
<TextBlock Grid.Row="0" Grid.Column="2" Classes="primary" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" FontSize="16"/>
|
||||||
|
|
||||||
<Border Grid.Row="1" Grid.Column="0" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
|
<Border Grid.Row="1" Grid.Column="0" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
|
||||||
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
|
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="1" Classes="primary" Text="{Binding NewSize}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Right" FontSize="16" Margin="8,0"/>
|
<TextBlock Grid.Row="1" Grid.Column="1" Classes="primary" Text="{Binding NewSize}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Right" FontSize="16" Margin="8,0"/>
|
||||||
|
@ -240,7 +240,7 @@
|
||||||
<TextBlock Grid.Row="0" Grid.Column="2" Classes="primary" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" FontSize="16"/>
|
<TextBlock Grid.Row="0" Grid.Column="2" Classes="primary" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" FontSize="16"/>
|
||||||
|
|
||||||
<Border Grid.Row="1" Grid.Column="0" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
|
<Border Grid.Row="1" Grid.Column="0" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
|
||||||
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
|
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="1" Classes="primary" Text="{Binding New.Size}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Right" FontSize="16" Margin="8,0"/>
|
<TextBlock Grid.Row="1" Grid.Column="1" Classes="primary" Text="{Binding New.Size}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Right" FontSize="16" Margin="8,0"/>
|
||||||
|
@ -274,7 +274,7 @@
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<Border Height="16" HorizontalAlignment="Center" Background="Green" CornerRadius="8" IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNull}}">
|
<Border Height="16" HorizontalAlignment="Center" Background="Green" CornerRadius="8" IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNull}}">
|
||||||
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Submodule.New}" Margin="8,0" FontSize="10"/>
|
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Submodule.New}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<Path Width="16" Height="16" Data="{StaticResource Icons.DoubleDown}" HorizontalAlignment="Center" IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
<Path Width="16" Height="16" Data="{StaticResource Icons.DoubleDown}" HorizontalAlignment="Center" IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||||
|
@ -290,7 +290,7 @@
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<Border Margin="0,8,0,0" Height="16" HorizontalAlignment="Center" Background="Red" CornerRadius="8" IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNull}}">
|
<Border Margin="0,8,0,0" Height="16" HorizontalAlignment="Center" Background="Red" CornerRadius="8" IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNull}}">
|
||||||
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Submodule.Deleted}" Margin="8,0" FontSize="10"/>
|
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Submodule.Deleted}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
@ -302,6 +302,33 @@
|
||||||
<v:ImageDiffView/>
|
<v:ImageDiffView/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
|
<!-- LFS Image Diff -->
|
||||||
|
<DataTemplate DataType="vm:LFSImageDiff">
|
||||||
|
<TabControl Margin="0,8,0,0" SelectedIndex="{Binding Source={x:Static vm:Preferences.Instance}, Path=LFSImageActiveIdx, Mode=TwoWay}">
|
||||||
|
<TabControl.Styles>
|
||||||
|
<Style Selector="TabControl /template/ ItemsPresenter#PART_ItemsPresenter > WrapPanel">
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||||
|
</Style>
|
||||||
|
</TabControl.Styles>
|
||||||
|
|
||||||
|
<TabItem>
|
||||||
|
<TabItem.Header>
|
||||||
|
<TextBlock Text="LFS" FontWeight="Bold"/>
|
||||||
|
</TabItem.Header>
|
||||||
|
|
||||||
|
<ContentControl Content="{Binding LFS}"/>
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem>
|
||||||
|
<TabItem.Header>
|
||||||
|
<TextBlock Text="IMAGE" FontWeight="Bold"/>
|
||||||
|
</TabItem.Header>
|
||||||
|
|
||||||
|
<ContentControl Content="{Binding Image}"/>
|
||||||
|
</TabItem>
|
||||||
|
</TabControl>
|
||||||
|
</DataTemplate>
|
||||||
|
|
||||||
<!-- Text Diff -->
|
<!-- Text Diff -->
|
||||||
<DataTemplate DataType="m:TextDiff">
|
<DataTemplate DataType="m:TextDiff">
|
||||||
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
|
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.VisualTree;
|
using Avalonia.VisualTree;
|
||||||
|
@ -40,5 +41,24 @@ namespace SourceGit.Views
|
||||||
if (sender is TextDiffView textDiff)
|
if (sender is TextDiffView textDiff)
|
||||||
BlockNavigationIndicator.Text = textDiff.BlockNavigation?.Indicator ?? string.Empty;
|
BlockNavigationIndicator.Text = textDiff.BlockNavigation?.Indicator ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnUseFullTextDiffClicked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var textDiffView = this.FindDescendantOfType<TextDiffView>();
|
||||||
|
if (textDiffView == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var presenter = textDiffView.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||||
|
if (presenter == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (presenter.DataContext is Models.TextDiff combined)
|
||||||
|
combined.ScrollOffset = Vector.Zero;
|
||||||
|
else if (presenter.DataContext is ViewModels.TwoSideTextDiff twoSides)
|
||||||
|
twoSides.File = string.Empty; // Just to reset `SyncScrollOffset` without affect UI refresh.
|
||||||
|
|
||||||
|
(DataContext as ViewModels.DiffContext)?.ToggleFullTextDiff();
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@
|
||||||
<Border Grid.Row="0"
|
<Border Grid.Row="0"
|
||||||
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
|
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
Background="{DynamicResource Brush.Window}">
|
Background="{DynamicResource Brush.Window}">
|
||||||
<Grid ColumnDefinitions="Auto,*">
|
<Grid ColumnDefinitions="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"
|
||||||
|
@ -147,6 +147,20 @@
|
||||||
Text="{Binding Path}"
|
Text="{Binding Path}"
|
||||||
FontSize="11"
|
FontSize="11"
|
||||||
TextTrimming="CharacterEllipsis"/>
|
TextTrimming="CharacterEllipsis"/>
|
||||||
|
<ToggleButton Grid.Column="2"
|
||||||
|
Classes="line_path"
|
||||||
|
Width="28"
|
||||||
|
Background="Transparent"
|
||||||
|
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting, Mode=TwoWay}"
|
||||||
|
ToolTip.Tip="{DynamicResource Text.Diff.SyntaxHighlight}">
|
||||||
|
<ToggleButton.IsVisible>
|
||||||
|
<Binding Path="Content"
|
||||||
|
Mode="OneWay"
|
||||||
|
Converter="{x:Static c:ObjectConverters.IsTypeOf}"
|
||||||
|
ConverterParameter="{x:Type m:RevisionTextFile}"/>
|
||||||
|
</ToggleButton.IsVisible>
|
||||||
|
<Path Width="13" Height="13" Data="{StaticResource Icons.SyntaxHighlight}" Margin="0,3,0,0"/>
|
||||||
|
</ToggleButton>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,11 @@ namespace SourceGit.Views
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnResetToSelectedRevision(object sender, RoutedEventArgs e)
|
private async void OnResetToSelectedRevision(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is Button { DataContext: ViewModels.FileHistoriesSingleRevision single })
|
if (sender is Button { DataContext: ViewModels.FileHistoriesSingleRevision single })
|
||||||
{
|
{
|
||||||
single.ResetToSelectedRevision();
|
await single.ResetToSelectedRevision();
|
||||||
NotifyDonePanel.IsVisible = true;
|
NotifyDonePanel.IsVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
src/Views/FilterModeInGraph.axaml
Normal file
31
src/Views/FilterModeInGraph.axaml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="SourceGit.Views.FilterModeInGraph"
|
||||||
|
x:DataType="vm:FilterModeInGraph">
|
||||||
|
<Grid RowDefinitions="22,26">
|
||||||
|
<TextBlock Grid.Row="0"
|
||||||
|
Text="{DynamicResource Text.Repository.FilterCommits}"
|
||||||
|
Foreground="{DynamicResource Brush.FG2}"/>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="1" Orientation="Horizontal">
|
||||||
|
<ToggleButton Classes="line_path"
|
||||||
|
Width="15" Height="26"
|
||||||
|
Background="Transparent"
|
||||||
|
IsChecked="{Binding IsFiltered, Mode=TwoWay}">
|
||||||
|
<Path Width="13" Height="13" Data="{StaticResource Icons.Filter}"/>
|
||||||
|
</ToggleButton>
|
||||||
|
|
||||||
|
<ToggleButton Classes="line_path"
|
||||||
|
Width="15" Height="26"
|
||||||
|
Margin="8,0,0,0"
|
||||||
|
Background="Transparent"
|
||||||
|
IsChecked="{Binding IsExcluded, Mode=TwoWay}">
|
||||||
|
<Path Width="13" Height="13" Data="{StaticResource Icons.EyeClose}"/>
|
||||||
|
</ToggleButton>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
12
src/Views/FilterModeInGraph.axaml.cs
Normal file
12
src/Views/FilterModeInGraph.axaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace SourceGit.Views
|
||||||
|
{
|
||||||
|
public partial class FilterModeInGraph : UserControl
|
||||||
|
{
|
||||||
|
public FilterModeInGraph()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,7 @@
|
||||||
<Grid RowDefinitions="Auto,*" Margin="16,0" IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNotNull}}">
|
<Grid RowDefinitions="Auto,*" Margin="16,0" IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center">
|
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
<Border Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
|
<Border Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
|
||||||
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
|
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<TextBlock Classes="primary" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
|
<TextBlock Classes="primary" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
<TextBlock Grid.Column="3" Classes="primary" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
|
<TextBlock Grid.Column="3" Classes="primary" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
|
||||||
|
|
||||||
<Border Grid.Column="4" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center" Margin="32,0,0,0">
|
<Border Grid.Column="4" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center" Margin="32,0,0,0">
|
||||||
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
|
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<TextBlock Grid.Column="5" Classes="primary" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="5" Classes="primary" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
<TextBlock Grid.Column="3" Classes="primary" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
|
<TextBlock Grid.Column="3" Classes="primary" Text="{DynamicResource Text.Bytes}" Foreground="{DynamicResource Brush.FG2}" Margin="2,0,0,0"/>
|
||||||
|
|
||||||
<Border Grid.Column="4" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center" Margin="32,0,0,0">
|
<Border Grid.Column="4" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center" Margin="32,0,0,0">
|
||||||
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10"/>
|
<TextBlock Classes="primary" Text="{DynamicResource Text.Diff.Binary.New}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<TextBlock Grid.Column="5" Classes="primary" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="5" Classes="primary" Text="{Binding NewImageSize}" Margin="8,0,0,0"/>
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
Height="26"
|
Height="26"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
CornerRadius="2"
|
CornerRadius="2"
|
||||||
Text="{Binding FeturePrefix, Mode=TwoWay}"/>
|
Text="{Binding FeaturePrefix, Mode=TwoWay}"/>
|
||||||
|
|
||||||
<TextBlock Grid.Row="4" Grid.Column="0"
|
<TextBlock Grid.Row="4" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
|
|
|
@ -284,7 +284,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
base.OnKeyDown(e);
|
base.OnKeyDown(e);
|
||||||
|
|
||||||
// Record unhandled key modifers.
|
// Record unhandled key modifiers.
|
||||||
if (!e.Handled)
|
if (!e.Handled)
|
||||||
{
|
{
|
||||||
_unhandledModifiers = e.KeyModifiers;
|
_unhandledModifiers = e.KeyModifiers;
|
||||||
|
|
|
@ -211,7 +211,7 @@
|
||||||
|
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate DataType="vm:LauncherPage">
|
<DataTemplate DataType="vm:LauncherPage">
|
||||||
<Grid ColumnDefinitions="Auto,*" Background="Transparent" DoubleTapped="OnTabsDropdownItemDoubleTapped">
|
<Grid ColumnDefinitions="Auto,*" Background="Transparent" Tapped="OnTabsDropdownItemTapped">
|
||||||
<Path Grid.Column="0"
|
<Path Grid.Column="0"
|
||||||
Width="12" Height="12" Margin="12,0"
|
Width="12" Height="12" Margin="12,0"
|
||||||
Fill="{Binding Node.Bookmark, Converter={x:Static c:IntConverters.ToBookmarkBrush}}"
|
Fill="{Binding Node.Bookmark, Converter={x:Static c:IntConverters.ToBookmarkBrush}}"
|
||||||
|
|
|
@ -327,7 +327,7 @@ namespace SourceGit.Views
|
||||||
SearchFilter = string.Empty;
|
SearchFilter = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTabsDropdownItemDoubleTapped(object sender, TappedEventArgs e)
|
private void OnTabsDropdownItemTapped(object sender, TappedEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is Control { DataContext: ViewModels.LauncherPage page } &&
|
if (sender is Control { DataContext: ViewModels.LauncherPage page } &&
|
||||||
DataContext is ViewModels.Launcher vm)
|
DataContext is ViewModels.Launcher vm)
|
||||||
|
|
|
@ -55,9 +55,10 @@ namespace SourceGit.Views
|
||||||
if (string.IsNullOrEmpty(text))
|
if (string.IsNullOrEmpty(text))
|
||||||
return base.MeasureOverride(availableSize);
|
return base.MeasureOverride(availableSize);
|
||||||
|
|
||||||
|
var trimmed = text.Replace("$", "");
|
||||||
var typeface = new Typeface(FontFamily);
|
var typeface = new Typeface(FontFamily);
|
||||||
var formatted = new FormattedText(
|
var formatted = new FormattedText(
|
||||||
Text,
|
trimmed,
|
||||||
CultureInfo.CurrentCulture,
|
CultureInfo.CurrentCulture,
|
||||||
FlowDirection.LeftToRight,
|
FlowDirection.LeftToRight,
|
||||||
typeface,
|
typeface,
|
||||||
|
|
|
@ -583,19 +583,34 @@
|
||||||
|
|
||||||
<Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
|
<Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
|
||||||
|
|
||||||
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="{DynamicResource Brush.ToolBar}">
|
<Grid Grid.Row="2" ColumnDefinitions="Auto,Auto,*,Auto,Auto" Background="{DynamicResource Brush.ToolBar}">
|
||||||
<Button Classes="icon_button" Click="OnAddCustomAction">
|
<Button Grid.Column="0"
|
||||||
|
Classes="icon_button"
|
||||||
|
Width="28" Height="28"
|
||||||
|
Click="OnAddCustomAction">
|
||||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
|
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button Grid.Column="1"
|
||||||
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
|
Classes="icon_button"
|
||||||
|
Width="28" Height="28"
|
||||||
<Button Classes="icon_button" Click="OnRemoveSelectedCustomAction">
|
Click="OnRemoveSelectedCustomAction">
|
||||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Window.Minimize}"/>
|
<Path Width="14" Height="14" Data="{StaticResource Icons.Window.Minimize}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button Grid.Column="3"
|
||||||
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
|
Classes="icon_button"
|
||||||
</StackPanel>
|
Width="28" Height="28"
|
||||||
|
Click="OnMoveSelectedCustomActionUp"
|
||||||
|
IsVisible="{Binding #ThisControl.SelectedCustomAction, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
|
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
|
||||||
|
</Button>
|
||||||
|
<Button Grid.Column="4"
|
||||||
|
Classes="icon_button"
|
||||||
|
Width="28" Height="28"
|
||||||
|
Click="OnMoveSelectedCustomActionDown"
|
||||||
|
IsVisible="{Binding #ThisControl.SelectedCustomAction, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
|
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
|
|
@ -415,6 +415,30 @@ namespace SourceGit.Views
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnMoveSelectedCustomActionUp(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (SelectedCustomAction == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var idx = ViewModels.Preferences.Instance.CustomActions.IndexOf(SelectedCustomAction);
|
||||||
|
if (idx > 0)
|
||||||
|
ViewModels.Preferences.Instance.CustomActions.Move(idx - 1, idx);
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMoveSelectedCustomActionDown(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (SelectedCustomAction == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var idx = ViewModels.Preferences.Instance.CustomActions.IndexOf(SelectedCustomAction);
|
||||||
|
if (idx < ViewModels.Preferences.Instance.CustomActions.Count - 1)
|
||||||
|
ViewModels.Preferences.Instance.CustomActions.Move(idx + 1, idx);
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateGitVersion()
|
private void UpdateGitVersion()
|
||||||
{
|
{
|
||||||
GitVersion = Native.OS.GitVersionString;
|
GitVersion = Native.OS.GitVersionString;
|
||||||
|
|
|
@ -229,7 +229,10 @@
|
||||||
Margin="8,0,0,0"
|
Margin="8,0,0,0"
|
||||||
Click="OnOpenSortLocalBranchMenu"
|
Click="OnOpenSortLocalBranchMenu"
|
||||||
ToolTip.Tip="{DynamicResource Text.Repository.BranchSort}">
|
ToolTip.Tip="{DynamicResource Text.Repository.BranchSort}">
|
||||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Order}"/>
|
<Grid>
|
||||||
|
<Path Width="12" Height="12" Data="{StaticResource Icons.OrderByName}" IsVisible="{Binding IsSortingLocalBranchByName, Mode=OneWay}"/>
|
||||||
|
<Path Width="12" Height="12" Data="{StaticResource Icons.OrderByTime}" IsVisible="{Binding !IsSortingLocalBranchByName, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
</Button>
|
</Button>
|
||||||
<Button Grid.Column="3" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding CreateNewBranch}" ToolTip.Tip="{DynamicResource Text.Repository.NewBranch}">
|
<Button Grid.Column="3" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding CreateNewBranch}" ToolTip.Tip="{DynamicResource Text.Repository.NewBranch}">
|
||||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Branch.Add}"/>
|
<Path Width="12" Height="12" Data="{StaticResource Icons.Branch.Add}"/>
|
||||||
|
@ -259,7 +262,10 @@
|
||||||
Margin="8,0,0,0"
|
Margin="8,0,0,0"
|
||||||
Click="OnOpenSortRemoteBranchMenu"
|
Click="OnOpenSortRemoteBranchMenu"
|
||||||
ToolTip.Tip="{DynamicResource Text.Repository.BranchSort}">
|
ToolTip.Tip="{DynamicResource Text.Repository.BranchSort}">
|
||||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Order}"/>
|
<Grid>
|
||||||
|
<Path Width="12" Height="12" Data="{StaticResource Icons.OrderByName}" IsVisible="{Binding IsSortingRemoteBranchByName, Mode=OneWay}"/>
|
||||||
|
<Path Width="12" Height="12" Data="{StaticResource Icons.OrderByTime}" IsVisible="{Binding !IsSortingRemoteBranchByName, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
</Button>
|
</Button>
|
||||||
<Button Grid.Column="3" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding AddRemote}" ToolTip.Tip="{DynamicResource Text.Repository.Remotes.Add}">
|
<Button Grid.Column="3" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding AddRemote}" ToolTip.Tip="{DynamicResource Text.Repository.Remotes.Add}">
|
||||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Remote.Add}"/>
|
<Path Width="12" Height="12" Data="{StaticResource Icons.Remote.Add}"/>
|
||||||
|
@ -294,7 +300,10 @@
|
||||||
Margin="8,0,0,0"
|
Margin="8,0,0,0"
|
||||||
Click="OnOpenSortTagMenu"
|
Click="OnOpenSortTagMenu"
|
||||||
ToolTip.Tip="{DynamicResource Text.Repository.Tags.Sort}">
|
ToolTip.Tip="{DynamicResource Text.Repository.Tags.Sort}">
|
||||||
<Path Width="12" Height="12" Margin="0,2,0,0" Data="{StaticResource Icons.Order}"/>
|
<Grid>
|
||||||
|
<Path Width="12" Height="12" Data="{StaticResource Icons.OrderByName}" IsVisible="{Binding IsSortingTagsByName, Mode=OneWay}"/>
|
||||||
|
<Path Width="12" Height="12" Data="{StaticResource Icons.OrderByTime}" IsVisible="{Binding !IsSortingTagsByName, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
</Button>
|
</Button>
|
||||||
<Button Grid.Column="4"
|
<Button Grid.Column="4"
|
||||||
Classes="icon_button"
|
Classes="icon_button"
|
||||||
|
|
|
@ -417,19 +417,34 @@
|
||||||
|
|
||||||
<Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
|
<Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
|
||||||
|
|
||||||
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="{DynamicResource Brush.ToolBar}">
|
<Grid Grid.Row="2" ColumnDefinitions="Auto,Auto,*,Auto,Auto" Background="{DynamicResource Brush.ToolBar}">
|
||||||
<Button Classes="icon_button" Command="{Binding AddNewCustomAction}">
|
<Button Grid.Column="0"
|
||||||
|
Classes="icon_button"
|
||||||
|
Width="28" Height="28"
|
||||||
|
Command="{Binding AddNewCustomAction}">
|
||||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
|
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button Grid.Column="1"
|
||||||
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
|
Classes="icon_button"
|
||||||
|
Width="28" Height="28"
|
||||||
<Button Classes="icon_button" Command="{Binding RemoveSelectedCustomAction}">
|
Command="{Binding RemoveSelectedCustomAction}">
|
||||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Window.Minimize}"/>
|
<Path Width="14" Height="14" Data="{StaticResource Icons.Window.Minimize}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button Grid.Column="3"
|
||||||
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
|
Classes="icon_button"
|
||||||
</StackPanel>
|
Width="28" Height="28"
|
||||||
|
Command="{Binding MoveSelectedCustomActionUp}"
|
||||||
|
IsVisible="{Binding SelectedCustomAction, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
|
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
|
||||||
|
</Button>
|
||||||
|
<Button Grid.Column="4"
|
||||||
|
Classes="icon_button"
|
||||||
|
Width="28" Height="28"
|
||||||
|
Command="{Binding MoveSelectedCustomActionDown}"
|
||||||
|
IsVisible="{Binding SelectedCustomAction, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
|
<Path Width="14" Height="14" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
@ -494,7 +509,7 @@
|
||||||
Height="28" Padding="8,0"
|
Height="28" Padding="8,0"
|
||||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||||
ItemsSource="{Binding AvailableOpenAIServices}"
|
ItemsSource="{Binding AvailableOpenAIServices}"
|
||||||
SelectedItem="{Binding PreferedOpenAIService, Mode=TwoWay}">
|
SelectedItem="{Binding PreferredOpenAIService, Mode=TwoWay}">
|
||||||
<ComboBox.ItemTemplate>
|
<ComboBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
|
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
<v:RevisionTextFileView FontFamily="{DynamicResource Fonts.Monospace}"
|
<v:RevisionTextFileView FontFamily="{DynamicResource Fonts.Monospace}"
|
||||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
|
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
|
||||||
TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
|
TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
|
||||||
|
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
|
||||||
Background="{DynamicResource Brush.Contents}"/>
|
Background="{DynamicResource Brush.Contents}"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@
|
||||||
|
|
||||||
<StackPanel Grid.Row="1" Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
|
<StackPanel Grid.Row="1" Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
<Border Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
|
<Border Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center">
|
||||||
<TextBlock Classes="primary" Text="{Binding ImageType}" Margin="8,0" FontSize="10" Foreground="{DynamicResource Brush.BadgeFG}"/>
|
<TextBlock Classes="primary" Text="{Binding ImageType}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<TextBlock Classes="primary" Text="{Binding ImageSize}" Margin="8,0,0,0"/>
|
<TextBlock Classes="primary" Text="{Binding ImageSize}" Margin="8,0,0,0"/>
|
||||||
|
@ -68,6 +69,32 @@
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
|
<DataTemplate DataType="vm:RevisionLFSImage">
|
||||||
|
<TabControl Margin="0,8,0,0" SelectedIndex="{Binding Source={x:Static vm:Preferences.Instance}, Path=LFSImageActiveIdx, Mode=TwoWay}">
|
||||||
|
<TabControl.Styles>
|
||||||
|
<Style Selector="TabControl /template/ ItemsPresenter#PART_ItemsPresenter > WrapPanel">
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||||
|
</Style>
|
||||||
|
</TabControl.Styles>
|
||||||
|
|
||||||
|
<TabItem>
|
||||||
|
<TabItem.Header>
|
||||||
|
<TextBlock Text="LFS" FontWeight="Bold"/>
|
||||||
|
</TabItem.Header>
|
||||||
|
|
||||||
|
<ContentControl Content="{Binding LFS}"/>
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem>
|
||||||
|
<TabItem.Header>
|
||||||
|
<TextBlock Text="IMAGE" FontWeight="Bold"/>
|
||||||
|
</TabItem.Header>
|
||||||
|
|
||||||
|
<ContentControl Content="{Binding Image}"/>
|
||||||
|
</TabItem>
|
||||||
|
</TabControl>
|
||||||
|
</DataTemplate>
|
||||||
</UserControl.DataTemplates>
|
</UserControl.DataTemplates>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,15 @@ namespace SourceGit.Views
|
||||||
set => SetValue(TabWidthProperty, value);
|
set => SetValue(TabWidthProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> UseSyntaxHighlightingProperty =
|
||||||
|
AvaloniaProperty.Register<RevisionTextFileView, bool>(nameof(UseSyntaxHighlighting));
|
||||||
|
|
||||||
|
public bool UseSyntaxHighlighting
|
||||||
|
{
|
||||||
|
get => GetValue(UseSyntaxHighlightingProperty);
|
||||||
|
set => SetValue(UseSyntaxHighlightingProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||||
|
|
||||||
public RevisionTextFileView() : base(new TextArea(), new TextDocument())
|
public RevisionTextFileView() : base(new TextArea(), new TextDocument())
|
||||||
|
@ -72,8 +81,9 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
if (DataContext is Models.RevisionTextFile source)
|
if (DataContext is Models.RevisionTextFile source)
|
||||||
{
|
{
|
||||||
UpdateTextMate();
|
|
||||||
Text = source.Content;
|
Text = source.Content;
|
||||||
|
Models.TextMateHelper.SetGrammarByFileName(_textMate, source.FileName);
|
||||||
|
ScrollToHome();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -86,9 +96,9 @@ namespace SourceGit.Views
|
||||||
base.OnPropertyChanged(change);
|
base.OnPropertyChanged(change);
|
||||||
|
|
||||||
if (change.Property == TabWidthProperty)
|
if (change.Property == TabWidthProperty)
|
||||||
{
|
|
||||||
Options.IndentationSize = TabWidth;
|
Options.IndentationSize = TabWidth;
|
||||||
}
|
else if (change.Property == UseSyntaxHighlightingProperty)
|
||||||
|
UpdateTextMate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||||
|
@ -124,11 +134,22 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void UpdateTextMate()
|
private void UpdateTextMate()
|
||||||
{
|
{
|
||||||
if (_textMate == null)
|
if (UseSyntaxHighlighting)
|
||||||
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
{
|
||||||
|
if (_textMate == null)
|
||||||
|
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
||||||
|
|
||||||
if (DataContext is Models.RevisionTextFile file)
|
if (DataContext is Models.RevisionTextFile file)
|
||||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, file.FileName);
|
Models.TextMateHelper.SetGrammarByFileName(_textMate, file.FileName);
|
||||||
|
}
|
||||||
|
else if (_textMate != null)
|
||||||
|
{
|
||||||
|
_textMate.Dispose();
|
||||||
|
_textMate = null;
|
||||||
|
GC.Collect();
|
||||||
|
|
||||||
|
TextArea.TextView.Redraw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextMate.Installation _textMate = null;
|
private TextMate.Installation _textMate = null;
|
||||||
|
|
|
@ -313,16 +313,13 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void OnRowsSelectionChanged(object sender, SelectionChangedEventArgs _)
|
private void OnRowsSelectionChanged(object sender, SelectionChangedEventArgs _)
|
||||||
{
|
{
|
||||||
if (_disableSelectionChangingEvent)
|
if (_disableSelectionChangingEvent || DataContext is not ViewModels.CommitDetail vm)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sender is ListBox { SelectedItem: ViewModels.RevisionFileTreeNode node } && DataContext is ViewModels.CommitDetail vm)
|
if (sender is ListBox { SelectedItem: ViewModels.RevisionFileTreeNode { IsFolder: false } node })
|
||||||
{
|
vm.ViewRevisionFile(node.Backend);
|
||||||
if (!node.IsFolder)
|
else
|
||||||
vm.ViewRevisionFile(node.Backend);
|
vm.ViewRevisionFile(null);
|
||||||
else
|
|
||||||
vm.ViewRevisionFile(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ViewModels.RevisionFileTreeNode> GetChildrenOfTreeNode(ViewModels.RevisionFileTreeNode node)
|
private List<ViewModels.RevisionFileTreeNode> GetChildrenOfTreeNode(ViewModels.RevisionFileTreeNode node)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:m="using:SourceGit.Models"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
xmlns:c="using:SourceGit.Converters"
|
xmlns:c="using:SourceGit.Converters"
|
||||||
|
@ -113,7 +114,39 @@
|
||||||
<!-- Right: File Content Viewer -->
|
<!-- Right: File Content Viewer -->
|
||||||
<Grid Grid.Column="2">
|
<Grid Grid.Column="2">
|
||||||
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
|
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
|
||||||
<v:RevisionFileContentViewer Content="{Binding ViewRevisionFileContent}"/>
|
<Grid RowDefinitions="Auto,*">
|
||||||
|
<Border Grid.Row="0"
|
||||||
|
Height="26"
|
||||||
|
BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1"
|
||||||
|
IsVisible="{Binding ViewRevisionFilePath, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||||
|
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||||
|
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.File}" Margin="8,0,0,0"/>
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
Classes="primary"
|
||||||
|
Margin="4,0,0,0"
|
||||||
|
Text="{Binding ViewRevisionFilePath}"
|
||||||
|
FontSize="11"
|
||||||
|
TextTrimming="CharacterEllipsis"/>
|
||||||
|
|
||||||
|
<ToggleButton Grid.Column="2"
|
||||||
|
Classes="line_path"
|
||||||
|
Width="28"
|
||||||
|
Background="Transparent"
|
||||||
|
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting, Mode=TwoWay}"
|
||||||
|
ToolTip.Tip="{DynamicResource Text.Diff.SyntaxHighlight}">
|
||||||
|
<ToggleButton.IsVisible>
|
||||||
|
<Binding Path="ViewRevisionFileContent"
|
||||||
|
Mode="OneWay"
|
||||||
|
Converter="{x:Static c:ObjectConverters.IsTypeOf}"
|
||||||
|
ConverterParameter="{x:Type m:RevisionTextFile}"/>
|
||||||
|
</ToggleButton.IsVisible>
|
||||||
|
<Path Width="13" Height="13" Data="{StaticResource Icons.SyntaxHighlight}" Margin="0,3,0,0"/>
|
||||||
|
</ToggleButton>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<v:RevisionFileContentViewer Grid.Row="1" Content="{Binding ViewRevisionFileContent}"/>
|
||||||
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -136,7 +136,7 @@
|
||||||
<DataTemplate DataType="m:StatisticsReport">
|
<DataTemplate DataType="m:StatisticsReport">
|
||||||
<Grid ColumnDefinitions="256,*">
|
<Grid ColumnDefinitions="256,*">
|
||||||
<Grid Grid.Column="0" RowDefinitions="*,16">
|
<Grid Grid.Column="0" RowDefinitions="*,16">
|
||||||
<!-- Table By Autor -->
|
<!-- Table By Author -->
|
||||||
<ListBox Grid.Column="0"
|
<ListBox Grid.Column="0"
|
||||||
ItemsSource="{Binding Authors}"
|
ItemsSource="{Binding Authors}"
|
||||||
SelectedItem="{Binding SelectedAuthor, Mode=TwoWay}"
|
SelectedItem="{Binding SelectedAuthor, Mode=TwoWay}"
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private async void OpenLocalRepository(object _1, RoutedEventArgs e)
|
private async void OpenLocalRepository(object _1, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var activePage = App.GetLauncer().ActivePage;
|
var activePage = App.GetLauncher().ActivePage;
|
||||||
if (activePage == null || !activePage.CanCreatePopup())
|
if (activePage == null || !activePage.CanCreatePopup())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
Classes="icon_button"
|
Classes="icon_button"
|
||||||
Width="26" Height="14"
|
Width="26" Height="14"
|
||||||
Padding="0"
|
Padding="0"
|
||||||
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.ViewAssumeUnchaged}"
|
ToolTip.Tip="{DynamicResource Text.WorkingCopy.Unstaged.ViewAssumeUnchanged}"
|
||||||
Command="{Binding OpenAssumeUnchanged}">
|
Command="{Binding OpenAssumeUnchanged}">
|
||||||
<Path Width="14" Height="14" Data="{StaticResource Icons.File.Ignore}"/>
|
<Path Width="14" Height="14" Data="{StaticResource Icons.File.Ignore}"/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue