mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-24 02:40:24 +08:00
Merge branch 'release/v2025.32'
This commit is contained in:
200
TRANSLATION.md
200
TRANSLATION.md
@@ -6,11 +6,29 @@ This document shows the translation status of each locale file in the repository
|
||||
|
||||
### 
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
### 
|
||||
<details>
|
||||
<summary>Missing keys in de_DE.axaml</summary>
|
||||
|
||||
### 
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in es_ES.axaml</summary>
|
||||
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in fr_FR.axaml</summary>
|
||||
@@ -113,7 +131,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.Appearance.EnableCompactFolders
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
- Text.Preferences.Git.UseLibsecret
|
||||
- Text.Pull.RecurseSubmodules
|
||||
@@ -178,6 +197,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ViewLogs.CopyLog
|
||||
- Text.ViewLogs.Delete
|
||||
- Text.WorkingCopy.AddToGitIgnore.InFolder
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
- Text.WorkingCopy.ConfirmCommitWithDetachedHead
|
||||
- Text.WorkingCopy.ConfirmCommitWithFilter
|
||||
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
|
||||
@@ -188,140 +209,19 @@ This document shows the translation status of each locale file in the repository
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in it_IT.axaml</summary>
|
||||
|
||||
- Text.AddToIgnore
|
||||
- Text.AddToIgnore.Pattern
|
||||
- Text.AddToIgnore.Storage
|
||||
- Text.App.Hide
|
||||
- Text.App.ShowAll
|
||||
- Text.Askpass.Passphrase
|
||||
- Text.Avatar.Load
|
||||
- Text.BranchCM.ResetToSelectedCommit
|
||||
- Text.BranchTree.InvalidUpstream
|
||||
- Text.BranchTree.Remote
|
||||
- Text.BranchTree.Tracking
|
||||
- Text.BranchTree.URL
|
||||
- Text.ChangeSubmoduleUrl
|
||||
- Text.ChangeSubmoduleUrl.Submodule
|
||||
- Text.ChangeSubmoduleUrl.URL
|
||||
- Text.Checkout.WarnLostCommits
|
||||
- Text.Checkout.WithFastForward
|
||||
- Text.Checkout.WithFastForward.Upstream
|
||||
- Text.CommitCM.CopyCommitMessage
|
||||
- Text.CommitCM.InteractiveRebase
|
||||
- Text.CommitCM.InteractiveRebase.Drop
|
||||
- Text.CommitCM.InteractiveRebase.Edit
|
||||
- Text.CommitCM.InteractiveRebase.Fixup
|
||||
- Text.CommitCM.InteractiveRebase.Manually
|
||||
- Text.CommitCM.InteractiveRebase.Reword
|
||||
- Text.CommitCM.InteractiveRebase.Squash
|
||||
- Text.CommitCM.PushRevision
|
||||
- Text.CommitCM.Rebase
|
||||
- Text.CommitCM.Reset
|
||||
- Text.CommitDetail.Changes.Count
|
||||
- Text.CommitDetail.Info.Key
|
||||
- Text.CommitDetail.Info.Signer
|
||||
- Text.Configure.CommitMessageTemplate.BuiltinVars
|
||||
- Text.Configure.CustomAction.Arguments.Tip
|
||||
- Text.Configure.CustomAction.InputControls
|
||||
- Text.Configure.CustomAction.InputControls.Edit
|
||||
- Text.Configure.CustomAction.Scope.Remote
|
||||
- Text.Configure.CustomAction.Scope.Tag
|
||||
- Text.Configure.IssueTracker.AddSampleGerritChangeIdCommit
|
||||
- Text.Configure.IssueTracker.Share
|
||||
- Text.ConfigureCustomActionControls
|
||||
- Text.ConfigureCustomActionControls.CheckedValue
|
||||
- Text.ConfigureCustomActionControls.CheckedValue.Tip
|
||||
- Text.ConfigureCustomActionControls.Description
|
||||
- Text.ConfigureCustomActionControls.DefaultValue
|
||||
- Text.ConfigureCustomActionControls.IsFolder
|
||||
- Text.ConfigureCustomActionControls.Label
|
||||
- Text.ConfigureCustomActionControls.Options
|
||||
- Text.ConfigureCustomActionControls.Options.Tip
|
||||
- Text.ConfigureCustomActionControls.Type
|
||||
- Text.ConfirmRestart.Title
|
||||
- Text.ConfirmRestart.Message
|
||||
- Text.CreateBranch.OverwriteExisting
|
||||
- Text.DeinitSubmodule
|
||||
- Text.DeinitSubmodule.Force
|
||||
- Text.DeinitSubmodule.Path
|
||||
- Text.DeleteMultiTags
|
||||
- Text.DeleteMultiTags.DeleteFromRemotes
|
||||
- Text.DeleteMultiTags.Tip
|
||||
- Text.Diff.Image.Blend
|
||||
- Text.Diff.Image.SideBySide
|
||||
- Text.Diff.Image.Swipe
|
||||
- Text.Diff.New
|
||||
- Text.Diff.Old
|
||||
- Text.Diff.Submodule.Deleted
|
||||
- Text.DirHistories
|
||||
- Text.Discard.IncludeUntracked
|
||||
- Text.ExecuteCustomAction.Target
|
||||
- Text.ExecuteCustomAction.Repository
|
||||
- Text.Hotkeys.Global.SwitchWorkspace
|
||||
- Text.Hotkeys.Global.SwitchTab
|
||||
- Text.InteractiveRebase.ReorderTip
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Launcher.Pages
|
||||
- Text.Merge.Edit
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.Appearance.EnableCompactFolders
|
||||
- Text.Preferences.Git.UseLibsecret
|
||||
- Text.Pull.RecurseSubmodules
|
||||
- Text.Push.New
|
||||
- Text.Push.Revision
|
||||
- Text.Push.Revision.Title
|
||||
- Text.RemoteCM.CustomAction
|
||||
- Text.Repository.ClearStashes
|
||||
- Text.Repository.Dashboard
|
||||
- Text.Repository.MoreOptions
|
||||
- Text.Repository.OnlyHighlightCurrentBranchInGraph
|
||||
- Text.Repository.Search.ByPath
|
||||
- Text.Repository.ShowDecoratedCommitsOnly
|
||||
- Text.Repository.ShowFirstParentOnly
|
||||
- Text.Repository.ShowFlags
|
||||
- Text.Repository.ShowLostCommits
|
||||
- Text.Repository.UseRelativeTimeInGraph
|
||||
- Text.ResetWithoutCheckout
|
||||
- Text.ResetWithoutCheckout.MoveTo
|
||||
- Text.ResetWithoutCheckout.Target
|
||||
- Text.SetSubmoduleBranch
|
||||
- Text.SetSubmoduleBranch.Submodule
|
||||
- Text.SetSubmoduleBranch.Current
|
||||
- Text.SetSubmoduleBranch.New
|
||||
- Text.SetSubmoduleBranch.New.Tip
|
||||
- Text.Stash.Mode
|
||||
- Text.StashCM.CopyMessage
|
||||
- Text.Submodule.Branch
|
||||
- Text.Submodule.CopyBranch
|
||||
- Text.Submodule.Deinit
|
||||
- Text.Submodule.Histories
|
||||
- Text.Submodule.Move
|
||||
- Text.Submodule.SetBranch
|
||||
- Text.Submodule.SetURL
|
||||
- Text.Submodule.Update
|
||||
- Text.Tag.Tagger
|
||||
- Text.Tag.Time
|
||||
- Text.TagCM.Copy.Message
|
||||
- Text.TagCM.Copy.Name
|
||||
- Text.TagCM.Copy.Tagger
|
||||
- Text.TagCM.CopyName
|
||||
- Text.TagCM.CustomAction
|
||||
- Text.TagCM.DeleteMultiple
|
||||
- Text.UpdateSubmodules.UpdateToRemoteTrackingBranch
|
||||
- Text.WorkingCopy.AddToGitIgnore.InFolder
|
||||
- Text.WorkingCopy.ConfirmCommitWithDetachedHead
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in ja_JP.axaml</summary>
|
||||
@@ -425,7 +325,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.Appearance.EnableCompactFolders
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
- Text.Preferences.Git.UseLibsecret
|
||||
- Text.Pull.RecurseSubmodules
|
||||
@@ -489,6 +390,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ViewLogs.CopyLog
|
||||
- Text.ViewLogs.Delete
|
||||
- Text.WorkingCopy.AddToGitIgnore.InFolder
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
- Text.WorkingCopy.ConfirmCommitWithDetachedHead
|
||||
- Text.WorkingCopy.ConfirmCommitWithFilter
|
||||
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
|
||||
@@ -499,7 +402,7 @@ This document shows the translation status of each locale file in the repository
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in pt_BR.axaml</summary>
|
||||
@@ -610,7 +513,6 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Diff.New
|
||||
- Text.Diff.Old
|
||||
- Text.Diff.Submodule.Deleted
|
||||
- Text.Diff.UseBlockNavigation
|
||||
- Text.DirHistories
|
||||
- Text.Discard.IncludeUntracked
|
||||
- Text.ExecuteCustomAction.Target
|
||||
@@ -641,8 +543,9 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.Preferences.Appearance.EditorTabWidth
|
||||
- Text.Preferences.Appearance.EnableCompactFolders
|
||||
- Text.Preferences.General.DateFormat
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.General.ShowChildren
|
||||
- Text.Preferences.General.ShowTagsInGraph
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
@@ -724,6 +627,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ViewLogs.CopyLog
|
||||
- Text.ViewLogs.Delete
|
||||
- Text.WorkingCopy.AddToGitIgnore.InFolder
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
- Text.WorkingCopy.CommitToEdit
|
||||
- Text.WorkingCopy.ConfirmCommitWithDetachedHead
|
||||
- Text.WorkingCopy.ConfirmCommitWithFilter
|
||||
@@ -736,18 +641,9 @@ This document shows the translation status of each locale file in the repository
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in ru_RU.axaml</summary>
|
||||
|
||||
- Text.App.Hide
|
||||
- Text.App.ShowAll
|
||||
- Text.Configure.CustomAction.Arguments.Tip
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in ta_IN.axaml</summary>
|
||||
@@ -851,7 +747,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.Appearance.EnableCompactFolders
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
- Text.Preferences.Git.UseLibsecret
|
||||
- Text.Pull.RecurseSubmodules
|
||||
@@ -915,6 +812,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ViewLogs.CopyLog
|
||||
- Text.ViewLogs.Delete
|
||||
- Text.WorkingCopy.AddToGitIgnore.InFolder
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
- Text.WorkingCopy.ConfirmCommitWithDetachedHead
|
||||
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
|
||||
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
|
||||
@@ -924,7 +823,7 @@ This document shows the translation status of each locale file in the repository
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in uk_UA.axaml</summary>
|
||||
@@ -1023,7 +922,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.Appearance.EnableCompactFolders
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
- Text.Preferences.Git.UseLibsecret
|
||||
- Text.Pull.RecurseSubmodules
|
||||
@@ -1086,6 +986,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ViewLogs.CopyLog
|
||||
- Text.ViewLogs.Delete
|
||||
- Text.WorkingCopy.AddToGitIgnore.InFolder
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
- Text.WorkingCopy.ConfirmCommitWithDetachedHead
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ mkdir -p %{buildroot}/opt/sourcegit
|
||||
mkdir -p %{buildroot}/%{_bindir}
|
||||
mkdir -p %{buildroot}/usr/share/applications
|
||||
mkdir -p %{buildroot}/usr/share/icons
|
||||
cp -f ../../../SourceGit/* %{buildroot}/opt/sourcegit/
|
||||
cp -f %{_topdir}/../../SourceGit/* %{buildroot}/opt/sourcegit/
|
||||
ln -rsf %{buildroot}/opt/sourcegit/sourcegit %{buildroot}/%{_bindir}
|
||||
cp -r ../../_common/applications %{buildroot}/%{_datadir}
|
||||
cp -r ../../_common/icons %{buildroot}/%{_datadir}
|
||||
cp -r %{_topdir}/../_common/applications %{buildroot}/%{_datadir}
|
||||
cp -r %{_topdir}/../_common/icons %{buildroot}/%{_datadir}
|
||||
chmod 755 -R %{buildroot}/opt/sourcegit
|
||||
chmod 755 %{buildroot}/%{_datadir}/applications/sourcegit.desktop
|
||||
|
||||
|
||||
@@ -608,10 +608,10 @@ namespace SourceGit
|
||||
try
|
||||
{
|
||||
// Fetch latest release information.
|
||||
using var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(5) };
|
||||
var data = await client.GetStringAsync("https://sourcegit-scm.github.io/data/version.json");
|
||||
using var client = new HttpClient();
|
||||
client.Timeout = TimeSpan.FromSeconds(5);
|
||||
|
||||
// Parse JSON into Models.Version.
|
||||
var data = await client.GetStringAsync("https://sourcegit-scm.github.io/data/version.json");
|
||||
var ver = JsonSerializer.Deserialize(data, JsonCodeGen.Default.Version);
|
||||
if (ver == null)
|
||||
return;
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace SourceGit.Commands
|
||||
proc.OutputDataReceived += (_, e) => HandleOutput(e.Data, errs);
|
||||
proc.ErrorDataReceived += (_, e) => HandleOutput(e.Data, errs);
|
||||
|
||||
Process dummy = null;
|
||||
var dummyProcLock = new object();
|
||||
var captured = new CapturedProcess() { Process = proc };
|
||||
var capturedLock = new object();
|
||||
try
|
||||
{
|
||||
proc.Start();
|
||||
@@ -57,13 +57,12 @@ namespace SourceGit.Commands
|
||||
// Not safe, please only use `CancellationToken` in readonly commands.
|
||||
if (CancellationToken.CanBeCanceled)
|
||||
{
|
||||
dummy = proc;
|
||||
CancellationToken.Register(() =>
|
||||
{
|
||||
lock (dummyProcLock)
|
||||
lock (capturedLock)
|
||||
{
|
||||
if (dummy is { HasExited: false })
|
||||
dummy.Kill();
|
||||
if (captured is { Process: { HasExited: false } })
|
||||
captured.Process.Kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -89,12 +88,9 @@ namespace SourceGit.Commands
|
||||
HandleOutput(e.Message, errs);
|
||||
}
|
||||
|
||||
if (dummy != null)
|
||||
lock (capturedLock)
|
||||
{
|
||||
lock (dummyProcLock)
|
||||
{
|
||||
dummy = null;
|
||||
}
|
||||
captured.Process = null;
|
||||
}
|
||||
|
||||
Log?.AppendLine(string.Empty);
|
||||
@@ -116,7 +112,8 @@ namespace SourceGit.Commands
|
||||
|
||||
protected Result ReadToEnd()
|
||||
{
|
||||
using var proc = new Process() { StartInfo = CreateGitStartInfo(true) };
|
||||
using var proc = new Process();
|
||||
proc.StartInfo = CreateGitStartInfo(true);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -138,7 +135,8 @@ namespace SourceGit.Commands
|
||||
|
||||
protected async Task<Result> ReadToEndAsync()
|
||||
{
|
||||
using var proc = new Process() { StartInfo = CreateGitStartInfo(true) };
|
||||
using var proc = new Process();
|
||||
proc.StartInfo = CreateGitStartInfo(true);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -245,6 +243,11 @@ namespace SourceGit.Commands
|
||||
errs.Add(line);
|
||||
}
|
||||
|
||||
private class CapturedProcess
|
||||
{
|
||||
public Process Process { get; set; } = null;
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"\d+%")]
|
||||
private static partial Regex REG_PROGRESS();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace SourceGit.Commands
|
||||
}
|
||||
}
|
||||
|
||||
private readonly string _tmpFile = string.Empty;
|
||||
private readonly string _message = string.Empty;
|
||||
private readonly string _tmpFile;
|
||||
private readonly string _message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,7 @@ namespace SourceGit.Commands
|
||||
|
||||
public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespace)
|
||||
{
|
||||
_result.TextDiff = new Models.TextDiff()
|
||||
{
|
||||
Repo = repo,
|
||||
Option = opt,
|
||||
};
|
||||
_result.TextDiff = new Models.TextDiff() { Option = opt };
|
||||
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
|
||||
@@ -94,8 +94,7 @@ namespace SourceGit.Commands
|
||||
branch.IsLocal = true;
|
||||
}
|
||||
|
||||
ulong committerDate = 0;
|
||||
ulong.TryParse(parts[1], out committerDate);
|
||||
ulong.TryParse(parts[1], out var committerDate);
|
||||
|
||||
branch.FullName = refName;
|
||||
branch.CommitterDate = committerDate;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace SourceGit.Commands
|
||||
var stream = new MemoryStream();
|
||||
try
|
||||
{
|
||||
using var proc = Process.Start(starter);
|
||||
using var proc = Process.Start(starter)!;
|
||||
await proc.StandardOutput.BaseStream.CopyToAsync(stream).ConfigureAwait(false);
|
||||
await proc.WaitForExitAsync().ConfigureAwait(false);
|
||||
}
|
||||
@@ -49,7 +49,7 @@ namespace SourceGit.Commands
|
||||
var stream = new MemoryStream();
|
||||
try
|
||||
{
|
||||
using var proc = Process.Start(starter);
|
||||
using var proc = Process.Start(starter)!;
|
||||
await proc.StandardInput.WriteLineAsync("version https://git-lfs.github.com/spec/v1").ConfigureAwait(false);
|
||||
await proc.StandardInput.WriteLineAsync($"oid sha256:{oid}").ConfigureAwait(false);
|
||||
await proc.StandardInput.WriteLineAsync($"size {size}").ConfigureAwait(false);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Commands
|
||||
{
|
||||
@@ -16,12 +15,6 @@ namespace SourceGit.Commands
|
||||
return Parse(ReadToEnd());
|
||||
}
|
||||
|
||||
public async Task<string> GetResultAsync()
|
||||
{
|
||||
var rs = await ReadToEndAsync().ConfigureAwait(false);
|
||||
return Parse(rs);
|
||||
}
|
||||
|
||||
private string Parse(Result rs)
|
||||
{
|
||||
if (!rs.IsSuccess)
|
||||
|
||||
@@ -34,8 +34,7 @@ namespace SourceGit.Commands
|
||||
if (!string.IsNullOrEmpty(message) && message.Equals(name, StringComparison.Ordinal))
|
||||
message = null;
|
||||
|
||||
ulong creactorDate = 0;
|
||||
ulong.TryParse(subs[5], out creactorDate);
|
||||
ulong.TryParse(subs[5], out var creatorDate);
|
||||
|
||||
tags.Add(new Models.Tag()
|
||||
{
|
||||
@@ -43,7 +42,7 @@ namespace SourceGit.Commands
|
||||
IsAnnotated = subs[1].Equals("tag", StringComparison.Ordinal),
|
||||
SHA = string.IsNullOrEmpty(subs[3]) ? subs[2] : subs[3],
|
||||
Creator = Models.User.FindOrAdd(subs[4]),
|
||||
CreatorDate = creactorDate,
|
||||
CreatorDate = creatorDate,
|
||||
Message = message,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace SourceGit.Commands
|
||||
|
||||
try
|
||||
{
|
||||
using var proc = Process.Start(starter);
|
||||
using var proc = Process.Start(starter)!;
|
||||
await proc.StandardOutput.BaseStream.CopyToAsync(writer).ConfigureAwait(false);
|
||||
await proc.WaitForExitAsync().ConfigureAwait(false);
|
||||
return proc.ExitCode == 0;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace SourceGit.Commands
|
||||
{
|
||||
public static async Task RunAsync(string repo, string revision, string file, string saveTo)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(saveTo);
|
||||
var dir = Path.GetDirectoryName(saveTo) ?? string.Empty;
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace SourceGit.Commands
|
||||
{
|
||||
try
|
||||
{
|
||||
using var proc = Process.Start(starter);
|
||||
using var proc = Process.Start(starter)!;
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace SourceGit.Commands
|
||||
|
||||
try
|
||||
{
|
||||
using var proc = Process.Start(starter);
|
||||
using var proc = Process.Start(starter)!;
|
||||
await proc.StandardInput.WriteAsync(_patchBuilder.ToString());
|
||||
proc.StandardInput.Close();
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace SourceGit.Commands
|
||||
}
|
||||
}
|
||||
|
||||
private string _repo = "";
|
||||
private StringBuilder _patchBuilder = new StringBuilder();
|
||||
private readonly string _repo;
|
||||
private readonly StringBuilder _patchBuilder = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,6 @@ namespace SourceGit.Converters
|
||||
{
|
||||
public static class ListConverters
|
||||
{
|
||||
public static readonly FuncValueConverter<IList, string> Count =
|
||||
new FuncValueConverter<IList, string>(v => v == null ? "0" : $"{v.Count}");
|
||||
|
||||
public static readonly FuncValueConverter<IList, string> ToCount =
|
||||
new FuncValueConverter<IList, string>(v => v == null ? "(0)" : $"({v.Count})");
|
||||
|
||||
|
||||
@@ -190,9 +190,6 @@ namespace SourceGit.Models
|
||||
image = Bitmap.DecodeToWidth(stream, 128);
|
||||
}
|
||||
|
||||
if (image == null)
|
||||
return;
|
||||
|
||||
_resources[email] = image;
|
||||
|
||||
lock (_synclock)
|
||||
|
||||
@@ -6,12 +6,7 @@ using Avalonia.Media;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public record CommitGraphLayout(double startY, double clipWidth, double rowHeight)
|
||||
{
|
||||
public double StartY { get; set; } = startY;
|
||||
public double ClipWidth { get; set; } = clipWidth;
|
||||
public double RowHeight { get; set; } = rowHeight;
|
||||
}
|
||||
public record CommitGraphLayout(double StartY, double ClipWidth, double RowHeight);
|
||||
|
||||
public class CommitGraph
|
||||
{
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace SourceGit.Models
|
||||
{
|
||||
public class CommitLink
|
||||
{
|
||||
public string Name { get; set; } = null;
|
||||
public string URLPrefix { get; set; } = null;
|
||||
public string Name { get; } = null;
|
||||
public string URLPrefix { get; } = null;
|
||||
|
||||
public CommitLink(string name, string prefix)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Media.Imaging;
|
||||
|
||||
namespace SourceGit.Models
|
||||
@@ -62,12 +60,9 @@ namespace SourceGit.Models
|
||||
public partial class TextDiff
|
||||
{
|
||||
public string File { get; set; } = string.Empty;
|
||||
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
|
||||
public Vector ScrollOffset { get; set; } = Vector.Zero;
|
||||
public int MaxLineNumber = 0;
|
||||
|
||||
public string Repo { get; set; } = null;
|
||||
public DiffOption Option { get; set; } = null;
|
||||
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
|
||||
public int MaxLineNumber = 0;
|
||||
|
||||
public TextDiffSelection MakeSelection(int startLine, int endLine, bool isCombined, bool isOldSide)
|
||||
{
|
||||
@@ -148,7 +143,8 @@ namespace SourceGit.Models
|
||||
var isTracked = !string.IsNullOrEmpty(fileBlobGuid);
|
||||
var fileGuid = isTracked ? fileBlobGuid : "00000000";
|
||||
|
||||
using var writer = new StreamWriter(output) { NewLine = "\n" };
|
||||
using var writer = new StreamWriter(output);
|
||||
writer.NewLine = "\n";
|
||||
writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
|
||||
if (!revert && !isTracked)
|
||||
writer.WriteLine("new file mode 100644");
|
||||
@@ -192,7 +188,8 @@ namespace SourceGit.Models
|
||||
{
|
||||
var orgFile = !string.IsNullOrEmpty(change.OriginalPath) ? change.OriginalPath : change.Path;
|
||||
|
||||
using var writer = new StreamWriter(output) { NewLine = "\n" };
|
||||
using var writer = new StreamWriter(output);
|
||||
writer.NewLine = "\n";
|
||||
writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
|
||||
writer.WriteLine($"index 00000000...{fileTreeGuid} 100644");
|
||||
writer.WriteLine($"--- a/{orgFile}");
|
||||
@@ -305,7 +302,8 @@ namespace SourceGit.Models
|
||||
{
|
||||
var orgFile = !string.IsNullOrEmpty(change.OriginalPath) ? change.OriginalPath : change.Path;
|
||||
|
||||
using var writer = new StreamWriter(output) { NewLine = "\n" };
|
||||
using var writer = new StreamWriter(output);
|
||||
writer.NewLine = "\n";
|
||||
writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
|
||||
writer.WriteLine($"index 00000000...{fileTreeGuid} 100644");
|
||||
writer.WriteLine($"--- a/{orgFile}");
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace SourceGit.Models
|
||||
if (!_cancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
var line = await reader.ReadToEndAsync(_cancellationTokenSource.Token);
|
||||
MessageReceived?.Invoke(line?.Trim());
|
||||
MessageReceived?.Invoke(line.Trim());
|
||||
}
|
||||
|
||||
_server.Disconnect();
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace SourceGit.Models
|
||||
{
|
||||
public static int Compare(string s1, string s2)
|
||||
{
|
||||
var comparer = StringComparer.InvariantCultureIgnoreCase;
|
||||
|
||||
int len1 = s1.Length;
|
||||
int len2 = s2.Length;
|
||||
|
||||
@@ -20,7 +22,7 @@ namespace SourceGit.Models
|
||||
bool isDigit1 = char.IsDigit(c1);
|
||||
bool isDigit2 = char.IsDigit(c2);
|
||||
if (isDigit1 != isDigit2)
|
||||
return c1.CompareTo(c2);
|
||||
return comparer.Compare(c1.ToString(), c2.ToString());
|
||||
|
||||
int subLen1 = 1;
|
||||
while (marker1 + subLen1 < len1 && char.IsDigit(s1[marker1 + subLen1]) == isDigit1)
|
||||
@@ -40,7 +42,7 @@ namespace SourceGit.Models
|
||||
if (isDigit1)
|
||||
result = (subLen1 == subLen2) ? string.CompareOrdinal(sub1, sub2) : (subLen1 - subLen2);
|
||||
else
|
||||
result = string.Compare(sub1, sub2, StringComparison.OrdinalIgnoreCase);
|
||||
result = comparer.Compare(sub1, sub2);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
@@ -285,7 +285,7 @@ namespace SourceGit.Models
|
||||
switch (c)
|
||||
{
|
||||
case ESCAPE:
|
||||
// allow to escape only }
|
||||
// allow to escape only right-brace
|
||||
if (Peek() == VARIABLE_END)
|
||||
{
|
||||
esc = true;
|
||||
|
||||
@@ -82,19 +82,19 @@ namespace SourceGit.Models
|
||||
}
|
||||
}
|
||||
|
||||
public void MarkBranchDirtyManually()
|
||||
public void MarkBranchUpdated()
|
||||
{
|
||||
_updateBranch = DateTime.Now.ToFileTime() - 1;
|
||||
_updateBranch = 0;
|
||||
}
|
||||
|
||||
public void MarkTagDirtyManually()
|
||||
public void MarkTagUpdated()
|
||||
{
|
||||
_updateTags = DateTime.Now.ToFileTime() - 1;
|
||||
_updateTags = 0;
|
||||
}
|
||||
|
||||
public void MarkWorkingCopyDirtyManually()
|
||||
public void MarkWorkingCopyUpdated()
|
||||
{
|
||||
_updateWC = DateTime.Now.ToFileTime() - 1;
|
||||
_updateWC = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace SourceGit.Native
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Platform unsupported!!!");
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace SourceGit.Native
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
var execFile = Process.GetCurrentProcess().MainModule!.FileName;
|
||||
var portableDir = Path.Combine(Path.GetDirectoryName(execFile), "data");
|
||||
var portableDir = Path.Combine(Path.GetDirectoryName(execFile)!, "data");
|
||||
if (Directory.Exists(portableDir))
|
||||
{
|
||||
DataDir = portableDir;
|
||||
@@ -250,7 +250,7 @@ namespace SourceGit.Native
|
||||
|
||||
try
|
||||
{
|
||||
using var proc = Process.Start(start);
|
||||
using var proc = Process.Start(start)!;
|
||||
var rs = proc.StandardOutput.ReadToEnd();
|
||||
proc.WaitForExit();
|
||||
if (proc.ExitCode == 0 && !string.IsNullOrWhiteSpace(rs))
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace SourceGit.Native
|
||||
[SupportedOSPlatform("windows")]
|
||||
internal class Windows : OS.IBackend
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct RECT
|
||||
{
|
||||
public int left;
|
||||
@@ -393,7 +394,7 @@ namespace SourceGit.Native
|
||||
|
||||
try
|
||||
{
|
||||
using var proc = Process.Start(startInfo);
|
||||
using var proc = Process.Start(startInfo)!;
|
||||
var output = proc.StandardOutput.ReadToEnd();
|
||||
proc.WaitForExit();
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<StreamGeometry x:Key="Icons.Clone">M1280 704c0 141-115 256-256 256H288C129 960 0 831 0 672c0-126 80-232 192-272A327 327 0 01192 384c0-177 143-320 320-320 119 0 222 64 277 160C820 204 857 192 896 192c106 0 192 86 192 192 0 24-5 48-13 69C1192 477 1280 580 1280 704zm-493-128H656V352c0-18-14-32-32-32h-96c-18 0-32 14-32 32v224h-131c-29 0-43 34-23 55l211 211c12 12 33 12 45 0l211-211c20-20 6-55-23-55z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Close">M523 398 918 3l113 113-396 396 397 397-113 113-397-397-397 397-113-113 397-397L14 116l113-113 396 396z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Code">M853 102H171C133 102 102 133 102 171v683C102 891 133 922 171 922h683C891 922 922 891 922 853V171C922 133 891 102 853 102zM390 600l-48 48L205 512l137-137 48 48L301 512l88 88zM465 819l-66-18L559 205l66 18L465 819zm218-171L634 600 723 512l-88-88 48-48L819 512 683 649z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.CodeBlock">M684 736 340 736l0-53 344 1-0 53zM552 565l-213-2 0-53 212 2-0 53zM684 392 340 392l0-53 344 1-0 53zM301 825c-45 0-78-9-100-27-22-18-33-43-33-75v-116c0-22-4-37-12-45-7-9-20-13-40-13v-61c19 0 32-4 40-12 8-9 12-24 12-46v-116c0-32 11-57 33-75 22-18 56-27 100-27h24v61h-24a35 35 0 00-27 12 41 41 0 00-11 29v116c0 35-10 60-31 75a66 66 0 01-31 14c11 2 22 6 31 14 20 17 31 42 31 75v116c0 12 4 22 11 29 7 8 16 12 27 12h24v61h-24zM701 764h24c10 0 19-4 27-12a41 41 0 0011-29v-116c0-33 10-58 31-75 9-7 19-12 31-14a66 66 0 01-31-14c-20-15-31-40-31-75v-116a41 41 0 00-11-29 35 35 0 00-27-12h-24v-61h24c45 0 78 9 100 27 22 18 33 43 33 75v116c0 22 4 37 11 46 8 8 21 12 40 12v61c-19 0-33 4-40 13-7 8-11 23-11 45v116c0 32-11 57-33 75-22 18-55 27-100 27h-24v-61z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.ColorPicker">M128 854h768v86H128zM390 797c13 13 29 19 48 19s35-6 45-19l291-288c26-22 26-64 0-90L435 83l-61 61L426 192l-272 269c-22 22-22 64 0 90l237 246zm93-544 211 211-32 32H240l243-243zM707 694c0 48 38 86 86 86 48 0 86-38 86-86 0-22-10-45-26-61L794 576l-61 61c-13 13-26 35-26 58z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Commit">M0 512M1024 512M512 0M512 1024M796 471A292 292 0 00512 256a293 293 0 00-284 215H0v144h228A293 293 0 00512 832a291 291 0 00284-217H1024V471h-228M512 688A146 146 0 01366 544A145 145 0 01512 400c80 0 146 63 146 144A146 146 0 01512 688</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.CommitMessageGenerator">M796 561a5 5 0 014 7l-39 90a5 5 0 004 7h100a5 5 0 014 8l-178 247a5 5 0 01-9-4l32-148a5 5 0 00-5-6h-89a5 5 0 01-4-7l86-191a5 5 0 014-3h88zM731 122a73 73 0 0173 73v318a54 54 0 00-8-1H731V195H244v634h408l-16 73H244a73 73 0 01-73-73V195a73 73 0 0173-73h488zm-219 366v73h-195v-73h195zm146-146v73H317v-73h341z</StreamGeometry>
|
||||
|
||||
@@ -333,7 +333,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Seiten wechseln</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Hervorhebung</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Zeilenumbruch</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">Aktiviere Block-Navigation</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Öffne in Merge Tool</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Alle Zeilen anzeigen</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Weniger Zeilen anzeigen</x:String>
|
||||
@@ -541,7 +540,6 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">DARSTELLUNG</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Standardschriftart</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Editor Tab Breite</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EnableCompactFolders" xml:space="preserve">Aktiviere kompakte Ordner im Änderungsbaum</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Schriftgröße</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Standard</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Texteditor</x:String>
|
||||
@@ -558,6 +556,7 @@
|
||||
<x:String x:Key="Text.Preferences.General" xml:space="preserve">ALLGEMEIN</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Check4UpdatesOnStartup" xml:space="preserve">Beim Starten nach Updates suchen</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">Datumsformat</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.EnableCompactFolders" xml:space="preserve">Aktiviere kompakte Ordner im Änderungsbaum</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">Sprache</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Commit-Historie</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Zeige Autor Zeitpunkt anstatt Commit Zeitpunkt</x:String>
|
||||
|
||||
@@ -328,7 +328,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Swap</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Line Word Wrap</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">Enable Block-Navigation</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Open in Merge Tool</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Show All Lines</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Decrease Number of Visible Lines</x:String>
|
||||
@@ -536,7 +535,6 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APPEARANCE</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Default Font</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Editor Tab Width</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EnableCompactFolders" xml:space="preserve">Enable compact folders in changes tree</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Font Size</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Default</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Editor</x:String>
|
||||
@@ -553,9 +551,11 @@
|
||||
<x:String x:Key="Text.Preferences.General" xml:space="preserve">GENERAL</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Check4UpdatesOnStartup" xml:space="preserve">Check for updates on startup</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">Date Format</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.EnableCompactFolders" xml:space="preserve">Enable compact folders in changes tree</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">Language</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Show author time instead of commit time in graph</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChangesPageByDefault" xml:space="preserve">Show `LOCAL CHANGES` page by default</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Show children in the commit details</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Show tags in commit graph</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String>
|
||||
@@ -839,6 +839,8 @@
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignore this file only</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">You can stage this file now.</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories" xml:space="preserve">Clear History</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories.Confirm" xml:space="preserve">Are you sure you want to clear all commit message history? This action cannot be undone.</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT & PUSH</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Template/History</x:String>
|
||||
|
||||
@@ -332,7 +332,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Intercambiar</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Resaltado de Sintaxis</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Ajuste de Línea</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">Habilitar navegación en bloque</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Abrir en Herramienta de Merge</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Mostrar Todas las Líneas</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Disminuir Número de Líneas Visibles</x:String>
|
||||
@@ -540,7 +539,6 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APARIENCIA</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Fuente por defecto</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Ancho de la Pestaña del Editor</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EnableCompactFolders" xml:space="preserve">Habilitar carpetas compactas en el árbol de cambios</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Tamaño de fuente</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Por defecto</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Editor</x:String>
|
||||
@@ -557,6 +555,7 @@
|
||||
<x:String x:Key="Text.Preferences.General" xml:space="preserve">GENERAL</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Check4UpdatesOnStartup" xml:space="preserve">Buscar actualizaciones al iniciar</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">Formato de Fecha</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.EnableCompactFolders" xml:space="preserve">Habilitar carpetas compactas en el árbol de cambios</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">Idioma</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Commits en el historial</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Mostrar hora del autor en lugar de la hora del commit en el gráfico</x:String>
|
||||
|
||||
@@ -242,7 +242,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Permuter</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Coloration syntaxique</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Retour à la ligne</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">Activer la navigation par blocs</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Ouvrir dans l'outil de fusion</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Voir toutes les lignes</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Réduit le nombre de ligne visibles</x:String>
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<x:String x:Key="Text.About" xml:space="preserve">Informazioni</x:String>
|
||||
<x:String x:Key="Text.About.Menu" xml:space="preserve">Informazioni su SourceGit</x:String>
|
||||
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Client GUI Git open source e gratuito</x:String>
|
||||
<x:String x:Key="Text.AddToIgnore" xml:space="preserve">Aggiungi file a Ignora</x:String>
|
||||
<x:String x:Key="Text.AddToIgnore.Pattern" xml:space="preserve">Pattern:</x:String>
|
||||
<x:String x:Key="Text.AddToIgnore.Storage" xml:space="preserve">File di storage:</x:String>
|
||||
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Aggiungi Worktree</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Posizione:</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Percorso per questo worktree. Supportato il percorso relativo.</x:String>
|
||||
@@ -20,6 +23,8 @@
|
||||
<x:String x:Key="Text.AIAssistant.Regen" xml:space="preserve">RIGENERA</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usa AI per generare il messaggio di commit</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APPLICA COME MESSAGGIO DI COMMIT</x:String>
|
||||
<x:String x:Key="Text.App.Hide" xml:space="preserve">Nascondi SourceGit</x:String>
|
||||
<x:String x:Key="Text.App.ShowAll" xml:space="preserve">Mostra Tutto</x:String>
|
||||
<x:String x:Key="Text.Apply" xml:space="preserve">Applica</x:String>
|
||||
<x:String x:Key="Text.Apply.File" xml:space="preserve">File Patch:</x:String>
|
||||
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Seleziona file .patch da applicare</x:String>
|
||||
@@ -36,8 +41,10 @@
|
||||
<x:String x:Key="Text.Archive.Revision" xml:space="preserve">Revisione:</x:String>
|
||||
<x:String x:Key="Text.Archive.Title" xml:space="preserve">Archivia</x:String>
|
||||
<x:String x:Key="Text.Askpass" xml:space="preserve">Richiedi Password SourceGit</x:String>
|
||||
<x:String x:Key="Text.Askpass.Passphrase" xml:space="preserve">Inserisci passphrase:</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.Avatar.Load" xml:space="preserve">Carico l'Immagine...</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.Bisect" xml:space="preserve">Biseca</x:String>
|
||||
@@ -66,8 +73,13 @@
|
||||
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Invia ${0}$</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Riallinea ${0}$ su ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rinomina ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Resetta ${0}$ a ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Imposta Branch di Tracciamento...</x:String>
|
||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Confronto Branch</x:String>
|
||||
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">Invalido</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Remote" xml:space="preserve">REMOTO</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Tracking" xml:space="preserve">TRACCIAMENTO</x:String>
|
||||
<x:String x:Key="Text.BranchTree.URL" xml:space="preserve">URL</x:String>
|
||||
<x:String x:Key="Text.Cancel" xml:space="preserve">ANNULLA</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Ripristina la Revisione Padre</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Ripristina Questa Revisione</x:String>
|
||||
@@ -76,6 +88,9 @@
|
||||
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Mostra come elenco di file e cartelle</x:String>
|
||||
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Mostra come elenco di percorsi</x:String>
|
||||
<x:String x:Key="Text.ChangeDisplayMode.Tree" xml:space="preserve">Mostra come albero del filesystem</x:String>
|
||||
<x:String x:Key="Text.ChangeSubmoduleUrl" xml:space="preserve">Cambia l'URL del Sottomodulo</x:String>
|
||||
<x:String x:Key="Text.ChangeSubmoduleUrl.Submodule" xml:space="preserve">Sottomodulo:</x:String>
|
||||
<x:String x:Key="Text.ChangeSubmoduleUrl.URL" xml:space="preserve">URL:</x:String>
|
||||
<x:String x:Key="Text.Checkout" xml:space="preserve">Checkout Branch</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit" xml:space="preserve">Checkout Commit</x:String>
|
||||
<x:String x:Key="Text.Checkout.Commit.Target" xml:space="preserve">Commit:</x:String>
|
||||
@@ -85,6 +100,9 @@
|
||||
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stasha e Ripristina</x:String>
|
||||
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Aggiorna tutti i sottomoduli</x:String>
|
||||
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
|
||||
<x:String x:Key="Text.Checkout.WarnLostCommits" xml:space="preserve">Il tuo HEAD attuale contiene commit non connessi ad alcun branch/tag! Sicuro di voler continuare?</x:String>
|
||||
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">Checkout & Avanzamento Veloce</x:String>
|
||||
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">Avanzamento Veloce verso:</x:String>
|
||||
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
|
||||
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Aggiungi sorgente al messaggio di commit</x:String>
|
||||
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String>
|
||||
@@ -109,17 +127,29 @@
|
||||
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Confronta con HEAD</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Confronta con Worktree</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CopyAuthor" xml:space="preserve">Autore</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CopyCommitMessage" xml:space="preserve">Messaggio</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CopyCommitter" xml:space="preserve">Committer</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">SHA</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CopySubject" xml:space="preserve">Oggetto</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Azione Personalizzata</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Rebase Interattivo</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase.Drop" xml:space="preserve">Scarta...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase.Edit" xml:space="preserve">Modifica...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase.Fixup" xml:space="preserve">Correggi nel Genitore...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase.Manually" xml:space="preserve">Ribasare interattivamente ${0}$ su ${1}$</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase.Reword" xml:space="preserve">Riformula...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase.Squash" xml:space="preserve">Compatta nel Genitore...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Unisci a ${0}$</x:String>
|
||||
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Unisci ...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.PushRevision" xml:space="preserve">Invia ${0}$ a ${1}$</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Ribasa ${0}$ su ${1}$</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Resetta ${0}$ su ${1}$</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Annulla Commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Modifica</x:String>
|
||||
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Salva come Patch...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Compatta nel Genitore</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">MODIFICHE</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes.Count" xml:space="preserve">file modificati</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Cerca Modifiche...</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">FILE</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">File LFS</x:String>
|
||||
@@ -132,26 +162,42 @@
|
||||
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Controlla i riferimenti che contengono questo commit</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">IL COMMIT È CONTENUTO DA</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.GotoChangesPage" xml:space="preserve">Mostra solo le prime 100 modifiche. Vedi tutte le modifiche nella scheda MODIFICHE.</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Key" xml:space="preserve">Chiave:</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Message" xml:space="preserve">MESSAGGIO</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">GENITORI</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">RIFERIMENTI</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Signer" xml:space="preserve">Firmatario:</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Apri nel Browser</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Descrizione</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectCount" xml:space="preserve">OGGETTO</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Inserisci l'oggetto del commit</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">Configura Repository</x:String>
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">TEMPLATE DI COMMIT</x:String>
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.BuiltinVars" xml:space="preserve">Puoi usare ${files_num}, ${branch_name}, ${files} e ${files:N} dove N è il numero massimo di percorsi di file da mostrare.</x:String>
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Contenuto Template:</x:String>
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Nome Template:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">AZIONE PERSONALIZZATA</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">Argomenti:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">Parametri integrati:
|
||||
|
||||
${REPO} Percorso del repository
|
||||
${REMOTE} Remoto selezionato o remoto del branch selezionato
|
||||
${BRANCH} Branch selezionato, senza la parte ${REMOTE} per i branch remoti
|
||||
${BRANCH_FRIENDLY_NAME} Nome amichevole del branch selezionato, contiene la parte ${REMOTE} per i branch remoti
|
||||
${SHA} Hash del commit selezionato
|
||||
${TAG} Tag selezionato
|
||||
$1, $2 ... Valori dei controlli di input</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">File Eseguibile:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls" xml:space="preserve">Controlli di Input:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls.Edit" xml:space="preserve">Modifica</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Nome:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Ambito:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Branch" xml:space="preserve">Branch</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Remote" xml:space="preserve">Remoto</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Tag" xml:space="preserve">Tag</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.WaitForExit" xml:space="preserve">Attendi la fine dell'azione</x:String>
|
||||
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Indirizzo Email</x:String>
|
||||
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Indirizzo email</x:String>
|
||||
@@ -162,6 +208,7 @@
|
||||
<x:String x:Key="Text.Configure.Git.PreferredMergeMode" xml:space="preserve">Modalità di Merge Preferita</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">TRACCIAMENTO ISSUE</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleAzure" xml:space="preserve">Aggiungi una regola di esempio per Azure DevOps</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGerritChangeIdCommit" xml:space="preserve">Aggiungi regola per Gerrit Change-Id Commit</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteeIssue" xml:space="preserve">Aggiungi una regola di esempio per un Issue Gitee</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteePullRequest" xml:space="preserve">Aggiungi una regola di esempio per un Pull Request Gitee</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGitHub" xml:space="preserve">Aggiungi una regola di esempio per GitHub</x:String>
|
||||
@@ -171,6 +218,7 @@
|
||||
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">Nuova Regola</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">Espressione Regex Issue:</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Nome Regola:</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.Share" xml:space="preserve">Condividi questa regola nel file .issuetracker</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">URL Risultato:</x:String>
|
||||
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Utilizza $1, $2 per accedere ai valori dei gruppi regex.</x:String>
|
||||
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>
|
||||
@@ -180,6 +228,16 @@
|
||||
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">Proxy HTTP usato da questo repository</x:String>
|
||||
<x:String x:Key="Text.Configure.User" xml:space="preserve">Nome Utente</x:String>
|
||||
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">Nome utente per questo repository</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls" xml:space="preserve">Modifica Controlli Azione Personalizzata</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.CheckedValue" xml:space="preserve">Valore Selezionato:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.CheckedValue.Tip" xml:space="preserve">Quando selezionato, questo valore sarà usato negli argomenti della riga di comando</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Description" xml:space="preserve">Descrizione:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.DefaultValue" xml:space="preserve">Predefinito:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.IsFolder" xml:space="preserve">È una Cartella:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Label" xml:space="preserve">Etichetta:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Options" xml:space="preserve">Opzioni:</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Options.Tip" xml:space="preserve">Usa '|' come delimitatore per le opzioni</x:String>
|
||||
<x:String x:Key="Text.ConfigureCustomActionControls.Type" xml:space="preserve">Tipo:</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">Spazi di Lavoro</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">Colore</x:String>
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">Nome</x:String>
|
||||
@@ -188,6 +246,8 @@
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.NoLocalChanges" xml:space="preserve">Trovato un commit vuoto! Vuoi procedere (--allow-empty)?</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">STAGE DI TUTTO E COMMITTA</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">Trovato un commit vuoto! Vuoi procedere (--allow-empty) o fare lo stage di tutto e committare?</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Title" xml:space="preserve">Riavvio Necessario</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Message" xml:space="preserve">È necessario riavviare l'applicazione per applicare le modifiche.</x:String>
|
||||
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">Guida Commit Convenzionali</x:String>
|
||||
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">Modifica Sostanziale:</x:String>
|
||||
<x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">Issue Chiusa:</x:String>
|
||||
@@ -209,6 +269,7 @@
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Inserisci il nome del branch.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Gli spazi verranno rimpiazzati con dei trattini.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Crea Branch Locale</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Sovrascrivi branch esistente</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Crea Tag...</x:String>
|
||||
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Nuovo Tag Su:</x:String>
|
||||
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">Firma con GPG</x:String>
|
||||
@@ -223,12 +284,18 @@
|
||||
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">leggero</x:String>
|
||||
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Tieni premuto Ctrl per avviare direttamente</x:String>
|
||||
<x:String x:Key="Text.Cut" xml:space="preserve">Taglia</x:String>
|
||||
<x:String x:Key="Text.DeinitSubmodule" xml:space="preserve">Deinizializza Sottomodulo</x:String>
|
||||
<x:String x:Key="Text.DeinitSubmodule.Force" xml:space="preserve">Forza deinizializzazione anche se contiene modifiche locali.</x:String>
|
||||
<x:String x:Key="Text.DeinitSubmodule.Path" xml:space="preserve">Sottomodulo:</x:String>
|
||||
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Elimina Branch</x:String>
|
||||
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Branch:</x:String>
|
||||
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">Stai per eliminare un branch remoto!!!</x:String>
|
||||
<x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">Elimina anche il branch remoto ${0}$</x:String>
|
||||
<x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">Elimina Branch Multipli</x:String>
|
||||
<x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">Stai per eliminare più branch contemporaneamente. Controlla attentamente prima di procedere!</x:String>
|
||||
<x:String x:Key="Text.DeleteMultiTags" xml:space="preserve">Elimina Tag Multipli</x:String>
|
||||
<x:String x:Key="Text.DeleteMultiTags.DeleteFromRemotes" xml:space="preserve">Eliminali dai remoti</x:String>
|
||||
<x:String x:Key="Text.DeleteMultiTags.Tip" xml:space="preserve">Stai cercando di eliminare più tag contemporaneamente. Assicurati di controllare attentamente prima di procedere!</x:String>
|
||||
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">Elimina Remoto</x:String>
|
||||
<x:String x:Key="Text.DeleteRemote.Remote" xml:space="preserve">Remoto:</x:String>
|
||||
<x:String x:Key="Text.DeleteRepositoryNode.Path" xml:space="preserve">Percorso:</x:String>
|
||||
@@ -246,29 +313,36 @@
|
||||
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">Modalità File Modificata</x:String>
|
||||
<x:String x:Key="Text.Diff.First" xml:space="preserve">Prima differenza</x:String>
|
||||
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">Ignora Modifiche agli Spazi</x:String>
|
||||
<x:String x:Key="Text.Diff.Image.Blend" xml:space="preserve">FUSIONE</x:String>
|
||||
<x:String x:Key="Text.Diff.Image.SideBySide" xml:space="preserve">AFFIANCATI</x:String>
|
||||
<x:String x:Key="Text.Diff.Image.Swipe" xml:space="preserve">SCORRIMENTO</x:String>
|
||||
<x:String x:Key="Text.Diff.Last" xml:space="preserve">Ultima differenza</x:String>
|
||||
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">MODIFICA OGGETTO LFS</x:String>
|
||||
<x:String x:Key="Text.Diff.New" xml:space="preserve">NUOVO</x:String>
|
||||
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Differenza Successiva</x:String>
|
||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">NESSUNA MODIFICA O SOLO CAMBIAMENTI DI FINE LINEA</x:String>
|
||||
<x:String x:Key="Text.Diff.Old" xml:space="preserve">VECCHIO</x:String>
|
||||
<x:String x:Key="Text.Diff.Prev" xml:space="preserve">Differenza Precedente</x:String>
|
||||
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">Salva come Patch</x:String>
|
||||
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Mostra Simboli Nascosti</x:String>
|
||||
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Diff Affiancato</x:String>
|
||||
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SOTTOMODULO</x:String>
|
||||
<x:String x:Key="Text.Diff.Submodule.Deleted" xml:space="preserve">ELIMINATO</x:String>
|
||||
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">NUOVO</x:String>
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Scambia</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Evidenziazione Sintassi</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Avvolgimento delle Parole</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">Abilita la navigazione a blocchi</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Apri nello Strumento di Merge</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Mostra Tutte le Righe</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Diminuisci Numero di Righe Visibili</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Aumenta Numero di Righe Visibili</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELEZIONA UN FILE PER VISUALIZZARE LE MODIFICHE</x:String>
|
||||
<x:String x:Key="Text.DirHistories" xml:space="preserve">Cronologia Cartella</x:String>
|
||||
<x:String x:Key="Text.Discard" xml:space="preserve">Scarta Modifiche</x:String>
|
||||
<x:String x:Key="Text.Discard.All" xml:space="preserve">Tutte le modifiche locali nella copia di lavoro.</x:String>
|
||||
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Modifiche:</x:String>
|
||||
<x:String x:Key="Text.Discard.IncludeIgnored" xml:space="preserve">Includi file ignorati</x:String>
|
||||
<x:String x:Key="Text.Discard.IncludeUntracked" xml:space="preserve">Includi file non tracciati</x:String>
|
||||
<x:String x:Key="Text.Discard.Total" xml:space="preserve">Un totale di {0} modifiche saranno scartate</x:String>
|
||||
<x:String x:Key="Text.Discard.Warning" xml:space="preserve">Questa azione non può essere annullata!!!</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.Bookmark" xml:space="preserve">Segnalibro:</x:String>
|
||||
@@ -276,6 +350,8 @@
|
||||
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Destinazione:</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Modifica Gruppo Selezionato</x:String>
|
||||
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Modifica Repository Selezionato</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction.Target" xml:space="preserve">Destinazione:</x:String>
|
||||
<x:String x:Key="Text.ExecuteCustomAction.Repository" xml:space="preserve">Questo repository</x:String>
|
||||
<x:String x:Key="Text.Fetch" xml:space="preserve">Recupera</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Recupera da tutti i remoti</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Forza la sovrascrittura dei riferimenti locali</x:String>
|
||||
@@ -368,6 +444,8 @@
|
||||
<x:String x:Key="Text.Hotkeys.Global.GotoPrevTab" xml:space="preserve">Vai alla pagina precedente</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Crea una nuova pagina</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Global.OpenPreferences" xml:space="preserve">Apri la finestra delle preferenze</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Global.SwitchWorkspace" xml:space="preserve">Cambia workspace attivo</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Global.SwitchTab" xml:space="preserve">Cambia scheda attiva</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">REPOSITORY</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Committa le modifiche in tsage</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Committa e invia le modifiche in stage</x:String>
|
||||
@@ -403,12 +481,16 @@
|
||||
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Riallinea Interattivamente</x:String>
|
||||
<x:String x:Key="Text.InteractiveRebase.AutoStash" xml:space="preserve">Stasha e Riapplica modifiche locali</x:String>
|
||||
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">Su:</x:String>
|
||||
<x:String x:Key="Text.InteractiveRebase.ReorderTip" xml:space="preserve">Trascina per riordinare i commit</x:String>
|
||||
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">Branch di destinazione:</x:String>
|
||||
<x:String x:Key="Text.IssueLinkCM.CopyLink" xml:space="preserve">Copia il Link</x:String>
|
||||
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Apri nel Browser</x:String>
|
||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERRORE</x:String>
|
||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">AVVISO</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Workspaces</x:String>
|
||||
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Schede</x:String>
|
||||
<x:String x:Key="Text.Merge" xml:space="preserve">Unisci Branch</x:String>
|
||||
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">Personalizza messaggio di merge</x:String>
|
||||
<x:String x:Key="Text.Merge.Into" xml:space="preserve">In:</x:String>
|
||||
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Opzione di Unione:</x:String>
|
||||
<x:String x:Key="Text.Merge.Source" xml:space="preserve">Sorgente:</x:String>
|
||||
@@ -416,6 +498,9 @@
|
||||
<x:String x:Key="Text.MergeMultiple.CommitChanges" xml:space="preserve">Commit di tutte le modifiche</x:String>
|
||||
<x:String x:Key="Text.MergeMultiple.Strategy" xml:space="preserve">Strategia:</x:String>
|
||||
<x:String x:Key="Text.MergeMultiple.Targets" xml:space="preserve">Obiettivi:</x:String>
|
||||
<x:String x:Key="Text.MoveSubmodule" xml:space="preserve">Sposta Sottomodulo</x:String>
|
||||
<x:String x:Key="Text.MoveSubmodule.MoveTo" xml:space="preserve">Sposta Verso:</x:String>
|
||||
<x:String x:Key="Text.MoveSubmodule.Submodule" xml:space="preserve">Sottomodulo:</x:String>
|
||||
<x:String x:Key="Text.MoveRepositoryNode" xml:space="preserve">Sposta Nodo Repository</x:String>
|
||||
<x:String x:Key="Text.MoveRepositoryNode.Target" xml:space="preserve">Seleziona nodo padre per:</x:String>
|
||||
<x:String x:Key="Text.Name" xml:space="preserve">Nome:</x:String>
|
||||
@@ -486,6 +571,7 @@
|
||||
<x:String x:Key="Text.Preferences.Git.Invalid" xml:space="preserve">Questa applicazione richiede Git (>= 2.25.1)</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.Path" xml:space="preserve">Percorso Installazione</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.SSLVerify" xml:space="preserve">Abilita la verifica HTTP SSL</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.UseLibsecret" xml:space="preserve">Usa git-credential-libsecret invece di git-credential-manager</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.User" xml:space="preserve">Nome Utente</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.User.Placeholder" xml:space="preserve">Nome utente Git globale</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.Version" xml:space="preserve">Versione di Git</x:String>
|
||||
@@ -511,6 +597,7 @@
|
||||
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Modifiche Locali:</x:String>
|
||||
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Scarta</x:String>
|
||||
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stasha e Riapplica</x:String>
|
||||
<x:String x:Key="Text.Pull.RecurseSubmodules" xml:space="preserve">Aggiorna tutti i sottomoduli</x:String>
|
||||
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Remoto:</x:String>
|
||||
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Scarica (Recupera e Unisci)</x:String>
|
||||
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Riallineare anziché unire</x:String>
|
||||
@@ -518,10 +605,13 @@
|
||||
<x:String x:Key="Text.Push.CheckSubmodules" xml:space="preserve">Assicurati che i sottomoduli siano stati inviati</x:String>
|
||||
<x:String x:Key="Text.Push.Force" xml:space="preserve">Forza l'invio</x:String>
|
||||
<x:String x:Key="Text.Push.Local" xml:space="preserve">Branch Locale:</x:String>
|
||||
<x:String x:Key="Text.Push.New" xml:space="preserve">NUOVO</x:String>
|
||||
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Remoto:</x:String>
|
||||
<x:String x:Key="Text.Push.Revision" xml:space="preserve">Revisione:</x:String>
|
||||
<x:String x:Key="Text.Push.Revision.Title" xml:space="preserve">Invia Revisione Al Remoto</x:String>
|
||||
<x:String x:Key="Text.Push.Title" xml:space="preserve">Invia modifiche al remoto</x:String>
|
||||
<x:String x:Key="Text.Push.To" xml:space="preserve">Branch Remoto:</x:String>
|
||||
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Imposta come branch di tracking</x:String>
|
||||
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Imposta come branch di tracciamento</x:String>
|
||||
<x:String x:Key="Text.Push.WithAllTags" xml:space="preserve">Invia tutti i tag</x:String>
|
||||
<x:String x:Key="Text.PushTag" xml:space="preserve">Invia Tag al Remoto</x:String>
|
||||
<x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">Invia a tutti i remoti</x:String>
|
||||
@@ -538,6 +628,7 @@
|
||||
<x:String x:Key="Text.Remote.URL" xml:space="preserve">URL del Repository:</x:String>
|
||||
<x:String x:Key="Text.Remote.URL.Placeholder" xml:space="preserve">URL del repository Git remoto</x:String>
|
||||
<x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">Copia URL</x:String>
|
||||
<x:String x:Key="Text.RemoteCM.CustomAction" xml:space="preserve">Azione Personalizzata</x:String>
|
||||
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">Elimina...</x:String>
|
||||
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">Modifica...</x:String>
|
||||
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">Recupera</x:String>
|
||||
@@ -558,10 +649,12 @@
|
||||
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Pulizia (GC e Potatura)</x:String>
|
||||
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Esegui il comando `git gc` per questo repository.</x:String>
|
||||
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Cancella tutto</x:String>
|
||||
<x:String x:Key="Text.Repository.ClearStashes" xml:space="preserve">Cancella</x:String>
|
||||
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configura questo repository</x:String>
|
||||
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUA</x:String>
|
||||
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Azioni Personalizzate</x:String>
|
||||
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">Nessuna Azione Personalizzata</x:String>
|
||||
<x:String x:Key="Text.Repository.Dashboard" xml:space="preserve">Dashboard</x:String>
|
||||
<x:String x:Key="Text.Repository.DiscardAll" xml:space="preserve">Scarta tutte le modifiche</x:String>
|
||||
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Apri nell'Esplora File</x:String>
|
||||
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Cerca Branch/Tag/Sottomodulo</x:String>
|
||||
@@ -576,9 +669,11 @@
|
||||
<x:String x:Key="Text.Repository.HistoriesOrder.ByDate" xml:space="preserve">Per data del commit</x:String>
|
||||
<x:String x:Key="Text.Repository.HistoriesOrder.Topo" xml:space="preserve">Topologicamente</x:String>
|
||||
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">BRANCH LOCALI</x:String>
|
||||
<x:String x:Key="Text.Repository.MoreOptions" xml:space="preserve">Altre opzioni...</x:String>
|
||||
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Vai a HEAD</x:String>
|
||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Crea Branch</x:String>
|
||||
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">CANCELLA LE NOTIFICHE</x:String>
|
||||
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInGraph" xml:space="preserve">Evidenzia solo il branch corrente</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Apri in {0}</x:String>
|
||||
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Apri in Strumenti Esterni</x:String>
|
||||
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTI</x:String>
|
||||
@@ -588,8 +683,13 @@
|
||||
<x:String x:Key="Text.Repository.Search.ByCommitter" xml:space="preserve">Committer</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByContent" xml:space="preserve">Contenuto</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Messaggio</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.ByPath" xml:space="preserve">Percorso</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
|
||||
<x:String x:Key="Text.Repository.Search.InCurrentBranch" xml:space="preserve">Branch Corrente</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowDecoratedCommitsOnly" xml:space="preserve">Solo commit decorati</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowFirstParentOnly" xml:space="preserve">Solo primo genitore</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowFlags" xml:space="preserve">MOSTRA FLAG</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowLostCommits" xml:space="preserve">Mostra commit persi</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowSubmodulesAsTree" xml:space="preserve">Mostra i Sottomoduli Come Albero</x:String>
|
||||
<x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">Mostra Tag come Albero</x:String>
|
||||
<x:String x:Key="Text.Repository.Skip" xml:space="preserve">SALTA</x:String>
|
||||
@@ -603,6 +703,7 @@
|
||||
<x:String x:Key="Text.Repository.Tags.OrderByName" xml:space="preserve">Per nome</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.UseRelativeTimeInGraph" xml:space="preserve">Usa tempo relativo</x:String>
|
||||
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">Visualizza i Log</x:String>
|
||||
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">Visita '{0}' nel Browser</x:String>
|
||||
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREE</x:String>
|
||||
@@ -613,6 +714,9 @@
|
||||
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Modalità Reset:</x:String>
|
||||
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Sposta a:</x:String>
|
||||
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Branch Corrente:</x:String>
|
||||
<x:String x:Key="Text.ResetWithoutCheckout" xml:space="preserve">Resetta Branch (Senza Checkout)</x:String>
|
||||
<x:String x:Key="Text.ResetWithoutCheckout.MoveTo" xml:space="preserve">Sposta Verso:</x:String>
|
||||
<x:String x:Key="Text.ResetWithoutCheckout.Target" xml:space="preserve">Branch:</x:String>
|
||||
<x:String x:Key="Text.RevealFile" xml:space="preserve">Mostra nell'Esplora File</x:String>
|
||||
<x:String x:Key="Text.Revert" xml:space="preserve">Ripristina Commit</x:String>
|
||||
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
|
||||
@@ -631,6 +735,11 @@
|
||||
<x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Salta questa versione</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Aggiornamento Software</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">Non ci sono aggiornamenti disponibili.</x:String>
|
||||
<x:String x:Key="Text.SetSubmoduleBranch" xml:space="preserve">Imposta Branch del Sottomodulo</x:String>
|
||||
<x:String x:Key="Text.SetSubmoduleBranch.Submodule" xml:space="preserve">Sottomodulo:</x:String>
|
||||
<x:String x:Key="Text.SetSubmoduleBranch.Current" xml:space="preserve">Attuale:</x:String>
|
||||
<x:String x:Key="Text.SetSubmoduleBranch.New" xml:space="preserve">Cambia In:</x:String>
|
||||
<x:String x:Key="Text.SetSubmoduleBranch.New.Tip" xml:space="preserve">Opzionale. Imposta al valore predefinito quando è vuoto.</x:String>
|
||||
<x:String x:Key="Text.SetUpstream" xml:space="preserve">Imposta il Branch </x:String>
|
||||
<x:String x:Key="Text.SetUpstream.Local" xml:space="preserve">Branch:</x:String>
|
||||
<x:String x:Key="Text.SetUpstream.Unset" xml:space="preserve">Rimuovi upstream</x:String>
|
||||
@@ -646,10 +755,12 @@
|
||||
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Includi file non tracciati</x:String>
|
||||
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Messaggio:</x:String>
|
||||
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Opzionale. Informazioni di questo stash</x:String>
|
||||
<x:String x:Key="Text.Stash.Mode" xml:space="preserve">Modalità:</x:String>
|
||||
<x:String x:Key="Text.Stash.OnlyStagedChanges" xml:space="preserve">Solo modifiche in stage</x:String>
|
||||
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Sia le modifiche in stage che quelle non in stage dei file selezionati saranno stashate!!!</x:String>
|
||||
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stasha Modifiche Locali</x:String>
|
||||
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Applica</x:String>
|
||||
<x:String x:Key="Text.StashCM.CopyMessage" xml:space="preserve">Copia Messaggio</x:String>
|
||||
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Elimina</x:String>
|
||||
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Salva come Patch...</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Elimina Stash</x:String>
|
||||
@@ -665,20 +776,36 @@
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">COMMIT:</x:String>
|
||||
<x:String x:Key="Text.Submodule" xml:space="preserve">SOTTOMODULI</x:String>
|
||||
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Aggiungi Sottomodulo</x:String>
|
||||
<x:String x:Key="Text.Submodule.Branch" xml:space="preserve">BRANCH</x:String>
|
||||
<x:String x:Key="Text.Submodule.CopyBranch" xml:space="preserve">Branch</x:String>
|
||||
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Percorso Relativo</x:String>
|
||||
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">Deinizializza</x:String>
|
||||
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Recupera sottomoduli annidati</x:String>
|
||||
<x:String x:Key="Text.Submodule.Histories" xml:space="preserve">Cronologia</x:String>
|
||||
<x:String x:Key="Text.Submodule.Move" xml:space="preserve">Sposta</x:String>
|
||||
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Apri Repository del Sottomodulo</x:String>
|
||||
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Percorso Relativo:</x:String>
|
||||
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Cartella relativa per memorizzare questo modulo.</x:String>
|
||||
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Elimina Sottomodulo</x:String>
|
||||
<x:String x:Key="Text.Submodule.SetBranch" xml:space="preserve">Imposta Branch</x:String>
|
||||
<x:String x:Key="Text.Submodule.SetURL" xml:space="preserve">Cambia URL</x:String>
|
||||
<x:String x:Key="Text.Submodule.Status" xml:space="preserve">STATO</x:String>
|
||||
<x:String x:Key="Text.Submodule.Status.Modified" xml:space="preserve">modificato</x:String>
|
||||
<x:String x:Key="Text.Submodule.Status.NotInited" xml:space="preserve">non inizializzato</x:String>
|
||||
<x:String x:Key="Text.Submodule.Status.RevisionChanged" xml:space="preserve">revisione cambiata</x:String>
|
||||
<x:String x:Key="Text.Submodule.Status.Unmerged" xml:space="preserve">non unito</x:String>
|
||||
<x:String x:Key="Text.Submodule.Update" xml:space="preserve">Aggiorna</x:String>
|
||||
<x:String x:Key="Text.Submodule.URL" xml:space="preserve">URL</x:String>
|
||||
<x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String>
|
||||
<x:String x:Key="Text.Tag.Tagger" xml:space="preserve">AUTORE TAG</x:String>
|
||||
<x:String x:Key="Text.Tag.Time" xml:space="preserve">DATA</x:String>
|
||||
<x:String x:Key="Text.TagCM.Copy.Message" xml:space="preserve">Messaggio</x:String>
|
||||
<x:String x:Key="Text.TagCM.Copy.Name" xml:space="preserve">Nome</x:String>
|
||||
<x:String x:Key="Text.TagCM.Copy.Tagger" xml:space="preserve">Autore</x:String>
|
||||
<x:String x:Key="Text.TagCM.CopyName" xml:space="preserve">Copia Nome Tag</x:String>
|
||||
<x:String x:Key="Text.TagCM.CustomAction" xml:space="preserve">Azione Personalizzata</x:String>
|
||||
<x:String x:Key="Text.TagCM.Delete" xml:space="preserve">Elimina ${0}$...</x:String>
|
||||
<x:String x:Key="Text.TagCM.DeleteMultiple" xml:space="preserve">Elimina i {0} tag selezionati...</x:String>
|
||||
<x:String x:Key="Text.TagCM.Merge" xml:space="preserve">Unisci ${0}$ in ${1}$...</x:String>
|
||||
<x:String x:Key="Text.TagCM.Push" xml:space="preserve">Invia ${0}$...</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">Aggiorna Sottomoduli</x:String>
|
||||
@@ -686,6 +813,7 @@
|
||||
<x:String x:Key="Text.UpdateSubmodules.Init" xml:space="preserve">Inizializza se necessario</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.Recursive" xml:space="preserve">Ricorsivamente</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Sottomodulo:</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.UpdateToRemoteTrackingBranch" xml:space="preserve">Aggiorna al branch di tracciamento remoto del sottomodulo</x:String>
|
||||
<x:String x:Key="Text.URL" xml:space="preserve">URL:</x:String>
|
||||
<x:String x:Key="Text.ViewLogs" xml:space="preserve">Log</x:String>
|
||||
<x:String x:Key="Text.ViewLogs.Clear" xml:space="preserve">CANCELLA TUTTO</x:String>
|
||||
@@ -709,6 +837,7 @@
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignora tutti i file *{0}</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignora i file *{0} nella stessa cartella</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InFolder" xml:space="preserve">Ignora file non tracciati in questa cartella</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignora solo questo file</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Modifica</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Puoi aggiungere in stage questo file ora.</x:String>
|
||||
@@ -718,6 +847,7 @@
|
||||
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">Attiva evento click</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitToEdit" xml:space="preserve">Commit (Modifica)</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Stage di tutte le modifiche e fai il commit</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithDetachedHead" xml:space="preserve">Stai creando un commit su un HEAD distaccato. Vuoi continuare?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithFilter" xml:space="preserve">Hai stageato {0} file ma solo {1} file mostrati ({2} file sono stati filtrati). Vuoi procedere?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLITTI RILEVATI</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Conflicts.OpenExternalMergeTool" xml:space="preserve">APRI STRUMENTO DI MERGE ESTERNO</x:String>
|
||||
@@ -728,6 +858,7 @@
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUDI FILE NON TRACCIATI</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">NESSUN MESSAGGIO RECENTE INSERITO</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">NESSUN TEMPLATE DI COMMIT</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">Reimposta Autore</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">SignOff</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">IN STAGE</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Staged.Unstage" xml:space="preserve">RIMUOVI DA STAGE</x:String>
|
||||
|
||||
@@ -241,7 +241,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">スワップ</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">シンタックスハイライト</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">行の折り返し</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">ブロックナビゲーションを有効化</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">マージツールで開く</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">すべての行を表示</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">表示する行数を減らす</x:String>
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
<x:String x:Key="Text.AIAssistant.Regen" xml:space="preserve">ПЕРЕСОЗДАТЬ</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Использовать OpenAI для создания сообщения о ревизии</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">ПРИМЕНИТЬ КАК СООБЩЕНИЕ РЕВИЗИИ</x:String>
|
||||
<x:String x:Key="Text.App.Hide" xml:space="preserve">Скрыть SourceGit</x:String>
|
||||
<x:String x:Key="Text.App.ShowAll" xml:space="preserve">Показать все</x:String>
|
||||
<x:String x:Key="Text.Apply" xml:space="preserve">Исправить </x:String>
|
||||
<x:String x:Key="Text.Apply.File" xml:space="preserve">Файл заплатки:</x:String>
|
||||
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Выберите файл .patch для применения</x:String>
|
||||
@@ -177,6 +179,15 @@
|
||||
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Название:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">ПОЛЬЗОВАТЕЛЬСКОЕ ДЕЙСТВИЕ</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">Аргументы:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">Built-in parameters:
|
||||
|
||||
${REPO} Путь репозитория
|
||||
${REMOTE} Выбранная удаённая ветка
|
||||
${BRANCH} Выбранная ветка, без ${REMOTE} удалённых веток
|
||||
${BRANCH_FRIENDLY_NAME} Понятное имя выбранной ветки, содержащую ${REMOTE} удалённые ветки
|
||||
${SHA} Хеш выбранной ревизии
|
||||
${TAG} Выбранная метка
|
||||
$1, $2 ... Ввод управляющих значений</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Исполняемый файл:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls" xml:space="preserve">Элементы управления вводом:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.InputControls.Edit" xml:space="preserve">Редактор</x:String>
|
||||
@@ -321,7 +332,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Обмен</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Подсветка синтаксиса </x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Перенос слов в строке</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">Разрешить навигацию по блокам</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Открыть в инструменте слияния </x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Показывать все строки</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Меньше видимых строк</x:String>
|
||||
@@ -529,7 +539,6 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">ВИД</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Шрифт по умолчанию</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Редактировать ширину вкладки</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EnableCompactFolders" xml:space="preserve">Включить компактные каталоги в дереве изменений</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Размер шрифта</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">По умолчанию</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Редактор</x:String>
|
||||
@@ -546,9 +555,11 @@
|
||||
<x:String x:Key="Text.Preferences.General" xml:space="preserve">ОСНОВНЫЕ</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Check4UpdatesOnStartup" xml:space="preserve">Проверить обновления при старте</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">Формат даты</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.EnableCompactFolders" xml:space="preserve">Включить компактные каталоги в дереве изменений</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">Язык</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Максимальная длина истории</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Показывать время автора вместо времени ревизии на графике</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChangesPageByDefault" xml:space="preserve">Показывать вкладку «ЛОКАЛЬНЫЕ ИЗМЕНЕНИЯ» по умолчанию</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Показать наследника в деталях комментария</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Показывать метки на графике</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Длина темы ревизии</x:String>
|
||||
@@ -832,6 +843,8 @@
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Игнорировать только эти файлы</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Изменить</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Теперь вы можете сформировать этот файл.</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories" xml:space="preserve">Очистить историю</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories.Confirm" xml:space="preserve">Вы действительно хотите очистить всю историю сообщений ревизии? Данное действие нельзя отменить.</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">ЗАФИКСИРОВАТЬ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">ЗАФИКСИРОВАТЬ и ОТПРАВИТЬ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Шаблон/Истории</x:String>
|
||||
|
||||
@@ -241,7 +241,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">இடமாற்று</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">தொடரியல் சிறப்பம்சமாக்கல்</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">வரி சொல் மடக்கு</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">தடுப்பு-வழிசெலுத்தலை இயக்கு</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">ஒன்றிணை கருவியில் திற</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">அனைத்து வரிகளையும் காட்டு</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">தெரியும் வரிகளின் எண்ணிக்கையைக் குறை</x:String>
|
||||
|
||||
@@ -246,7 +246,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Поміняти місцями</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Підсвітка синтаксису</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Перенос слів</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">Увімкнути навігацію блоками</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Відкрити в інструменті злиття</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">Показати всі рядки</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Зменшити кількість видимих рядків</x:String>
|
||||
|
||||
@@ -332,7 +332,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">交换比对双方</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">语法高亮</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">自动换行</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">启用基于变更块的跳转</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合并工具查看</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">显示完整文件</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">减少可见的行数</x:String>
|
||||
@@ -540,7 +539,6 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外观配置</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">缺省字体</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">编辑器制表符宽度</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EnableCompactFolders" xml:space="preserve">在变更列表树中启用紧凑文件夹模式</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">字体大小</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">默认</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">代码编辑器</x:String>
|
||||
@@ -557,9 +555,11 @@
|
||||
<x:String x:Key="Text.Preferences.General" xml:space="preserve">通用配置</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Check4UpdatesOnStartup" xml:space="preserve">启动时检测软件更新</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">日期时间格式</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.EnableCompactFolders" xml:space="preserve">在变更列表树中启用紧凑文件夹模式</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">显示语言</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">最大历史提交数</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">在提交路线图中显示修改时间而非提交时间</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChangesPageByDefault" xml:space="preserve">默认显示【本地更改】页</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">在提交详情页中显示子提交列表</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">在提交路线图中显示标签</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">SUBJECT字数检测</x:String>
|
||||
@@ -843,6 +843,8 @@
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">忽略本文件</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修补</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">现在您已可将其加入暂存区中</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories" xml:space="preserve">清空历史提交信息</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories.Confirm" xml:space="preserve">您确定要清空所有的历史提交信息记录吗(执行操作后无法撤回)?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">提交并推送</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">历史输入/模板</x:String>
|
||||
|
||||
@@ -332,7 +332,6 @@
|
||||
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">交換比對雙方</x:String>
|
||||
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">語法上色</x:String>
|
||||
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">自動換行</x:String>
|
||||
<x:String x:Key="Text.Diff.UseBlockNavigation" xml:space="preserve">區塊切換上/下一個差異</x:String>
|
||||
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">使用外部合併工具檢視</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.All" xml:space="preserve">顯示檔案的全部內容</x:String>
|
||||
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">減少可見的行數</x:String>
|
||||
@@ -540,7 +539,6 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外觀設定</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">預設字型</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">編輯器 Tab 寬度</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EnableCompactFolders" xml:space="preserve">在變更樹中啟用精簡文件夾顯示模式</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">字型大小</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">預設</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">程式碼</x:String>
|
||||
@@ -557,9 +555,11 @@
|
||||
<x:String x:Key="Text.Preferences.General" xml:space="preserve">一般設定</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Check4UpdatesOnStartup" xml:space="preserve">啟動時檢查軟體更新</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">日期時間格式</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.EnableCompactFolders" xml:space="preserve">在變更樹中啟用精簡文件夾顯示模式</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">顯示語言</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">最大歷史提交數</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">在提交路線圖中顯示修改時間而非提交時間</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChangesPageByDefault" xml:space="preserve">預設顯示「本機變更」頁面</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">在提交詳細資訊中顯示後續提交</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">在路線圖中顯示標籤</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">提交標題字數偵測</x:String>
|
||||
@@ -843,6 +843,8 @@
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">忽略本檔案</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修補</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">現在您已可將其加入暫存區中</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories" xml:space="preserve">清除提交訊息歷史</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories.Confirm" xml:space="preserve">您確定要清除所有提交訊息記錄嗎 (動作無法撤銷) ?</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提 交</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">提交並推送</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">歷史輸入/範本</x:String>
|
||||
|
||||
@@ -740,6 +740,7 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="ContextMenu">
|
||||
<Setter Property="MaxWidth" Value="1024"/>
|
||||
<Setter Property="HorizontalOffset" Value="-4"/>
|
||||
<Setter Property="VerticalOffset" Value="-4"/>
|
||||
<Setter Property="Template">
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.4" Condition="'$(Configuration)' == 'Debug'" />
|
||||
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.3.0" />
|
||||
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.3.0" />
|
||||
<PackageReference Include="Azure.AI.OpenAI" Version="2.2.0-beta.5" />
|
||||
<PackageReference Include="Azure.AI.OpenAI" Version="2.3.0-beta.1" />
|
||||
<PackageReference Include="BitMiracle.LibTiff.NET" Version="2.4.660" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc5.4" />
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace SourceGit.ViewModels
|
||||
var file = StorageFile.GetFullPath(_repo.FullPath, _repo.GitDir);
|
||||
if (!File.Exists(file))
|
||||
{
|
||||
await File.WriteAllLinesAsync(file, [_pattern]);
|
||||
await File.WriteAllLinesAsync(file!, [_pattern]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,63 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using Avalonia.Collections;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class BlockNavigation : ObservableObject
|
||||
{
|
||||
public class Block
|
||||
public record Block(int Start, int End)
|
||||
{
|
||||
public int Start { get; set; } = 0;
|
||||
public int End { get; set; } = 0;
|
||||
|
||||
public Block(int start, int end)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
}
|
||||
|
||||
public bool IsInRange(int line)
|
||||
{
|
||||
return line >= Start && line <= End;
|
||||
}
|
||||
}
|
||||
|
||||
public AvaloniaList<Block> Blocks
|
||||
{
|
||||
get;
|
||||
} = [];
|
||||
|
||||
public int Current
|
||||
{
|
||||
get => _current;
|
||||
private set => SetProperty(ref _current, value);
|
||||
}
|
||||
|
||||
public string Indicator
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Blocks.Count == 0)
|
||||
if (_blocks.Count == 0)
|
||||
return "-/-";
|
||||
|
||||
if (_current >= 0 && _current < Blocks.Count)
|
||||
return $"{_current + 1}/{Blocks.Count}";
|
||||
if (_current >= 0 && _current < _blocks.Count)
|
||||
return $"{_current + 1}/{_blocks.Count}";
|
||||
|
||||
return $"-/{Blocks.Count}";
|
||||
return $"-/{_blocks.Count}";
|
||||
}
|
||||
}
|
||||
|
||||
public BlockNavigation(object context)
|
||||
public BlockNavigation(List<Models.TextDiffLine> lines)
|
||||
{
|
||||
Blocks.Clear();
|
||||
Current = -1;
|
||||
|
||||
var lines = new List<Models.TextDiffLine>();
|
||||
if (context is Models.TextDiff combined)
|
||||
lines = combined.Lines;
|
||||
else if (context is TwoSideTextDiff twoSide)
|
||||
lines = twoSide.Old;
|
||||
_blocks.Clear();
|
||||
_current = -1;
|
||||
|
||||
if (lines.Count == 0)
|
||||
return;
|
||||
@@ -91,54 +64,89 @@ namespace SourceGit.ViewModels
|
||||
if (!isNewBlock)
|
||||
blocks.Add(new Block(blockStartIdx, lines.Count - 1));
|
||||
|
||||
Blocks.AddRange(blocks);
|
||||
_blocks.AddRange(blocks);
|
||||
}
|
||||
|
||||
public Block GetCurrentBlock()
|
||||
{
|
||||
return (_current >= 0 && _current < Blocks.Count) ? Blocks[_current] : null;
|
||||
if (_current >= 0 && _current < _blocks.Count)
|
||||
return _blocks[_current];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Block GotoFirst()
|
||||
{
|
||||
if (Blocks.Count == 0)
|
||||
if (_blocks.Count == 0)
|
||||
return null;
|
||||
|
||||
Current = 0;
|
||||
return Blocks[_current];
|
||||
_current = 0;
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return _blocks[_current];
|
||||
}
|
||||
|
||||
public Block GotoPrev()
|
||||
{
|
||||
if (Blocks.Count == 0)
|
||||
if (_blocks.Count == 0)
|
||||
return null;
|
||||
|
||||
if (_current == -1)
|
||||
Current = 0;
|
||||
_current = 0;
|
||||
else if (_current > 0)
|
||||
Current = _current - 1;
|
||||
return Blocks[_current];
|
||||
_current--;
|
||||
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return _blocks[_current];
|
||||
}
|
||||
|
||||
public Block GotoNext()
|
||||
{
|
||||
if (Blocks.Count == 0)
|
||||
if (_blocks.Count == 0)
|
||||
return null;
|
||||
|
||||
if (_current < Blocks.Count - 1)
|
||||
Current = _current + 1;
|
||||
return Blocks[_current];
|
||||
if (_current < _blocks.Count - 1)
|
||||
_current++;
|
||||
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return _blocks[_current];
|
||||
}
|
||||
|
||||
public Block GotoLast()
|
||||
{
|
||||
if (Blocks.Count == 0)
|
||||
if (_blocks.Count == 0)
|
||||
return null;
|
||||
|
||||
Current = Blocks.Count - 1;
|
||||
return Blocks[_current];
|
||||
_current = _blocks.Count - 1;
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return _blocks[_current];
|
||||
}
|
||||
|
||||
private int _current = -1;
|
||||
public void UpdateByCaretPosition(int caretLine)
|
||||
{
|
||||
if (_current >= 0 && _current < _blocks.Count)
|
||||
{
|
||||
var block = _blocks[_current];
|
||||
if (block.IsInRange(caretLine))
|
||||
return;
|
||||
}
|
||||
|
||||
_current = -1;
|
||||
|
||||
for (var i = 0; i < _blocks.Count; i++)
|
||||
{
|
||||
var block = _blocks[i];
|
||||
if (block.Start > caretLine)
|
||||
break;
|
||||
|
||||
_current = i;
|
||||
if (block.End >= caretLine)
|
||||
break;
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
}
|
||||
|
||||
private int _current;
|
||||
private readonly List<Block> _blocks = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,8 +252,8 @@ namespace SourceGit.ViewModels
|
||||
SortNodesByTime(node.Children);
|
||||
}
|
||||
|
||||
private readonly Models.BranchSortMode _localSortMode = Models.BranchSortMode.Name;
|
||||
private readonly Models.BranchSortMode _remoteSortMode = Models.BranchSortMode.Name;
|
||||
private readonly Models.BranchSortMode _localSortMode;
|
||||
private readonly Models.BranchSortMode _remoteSortMode;
|
||||
private readonly HashSet<string> _expanded = new HashSet<string>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Threading;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
@@ -24,7 +22,42 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
Preferences.Instance.IgnoreWhitespaceChangesInDiff = value;
|
||||
OnPropertyChanged();
|
||||
LoadDiffContent();
|
||||
LoadContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowEntireFile
|
||||
{
|
||||
get => Preferences.Instance.UseFullTextDiff;
|
||||
set
|
||||
{
|
||||
if (value != Preferences.Instance.UseFullTextDiff)
|
||||
{
|
||||
Preferences.Instance.UseFullTextDiff = value;
|
||||
OnPropertyChanged();
|
||||
|
||||
if (Content is TextDiffContext ctx)
|
||||
{
|
||||
ctx.Data.File = string.Empty; // Just to ignore both previous `ScrollOffset` and `BlockNavigation`
|
||||
LoadContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseSideBySide
|
||||
{
|
||||
get => Preferences.Instance.UseSideBySideDiff;
|
||||
set
|
||||
{
|
||||
if (value != Preferences.Instance.UseSideBySideDiff)
|
||||
{
|
||||
Preferences.Instance.UseSideBySideDiff = value;
|
||||
OnPropertyChanged();
|
||||
|
||||
if (Content is TextDiffContext ctx && ctx.IsSideBySide() != value)
|
||||
Content = ctx.SwitchMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,25 +105,19 @@ namespace SourceGit.ViewModels
|
||||
else
|
||||
Title = $"{_option.OrgPath} → {_option.Path}";
|
||||
|
||||
LoadDiffContent();
|
||||
}
|
||||
|
||||
public void ToggleFullTextDiff()
|
||||
{
|
||||
Preferences.Instance.UseFullTextDiff = !Preferences.Instance.UseFullTextDiff;
|
||||
LoadDiffContent();
|
||||
LoadContent();
|
||||
}
|
||||
|
||||
public void IncrUnified()
|
||||
{
|
||||
UnifiedLines = _unifiedLines + 1;
|
||||
LoadDiffContent();
|
||||
LoadContent();
|
||||
}
|
||||
|
||||
public void DecrUnified()
|
||||
{
|
||||
UnifiedLines = Math.Max(4, _unifiedLines - 1);
|
||||
LoadDiffContent();
|
||||
LoadContent();
|
||||
}
|
||||
|
||||
public void OpenExternalMergeTool()
|
||||
@@ -98,7 +125,27 @@ namespace SourceGit.ViewModels
|
||||
new Commands.DiffTool(_repo, _option).Open();
|
||||
}
|
||||
|
||||
private void LoadDiffContent()
|
||||
public void CheckSettings()
|
||||
{
|
||||
if (Content is TextDiffContext ctx)
|
||||
{
|
||||
if ((ShowEntireFile && _info.UnifiedLines != _entireFileLine) ||
|
||||
(!ShowEntireFile && _info.UnifiedLines == _entireFileLine) ||
|
||||
(IgnoreWhitespace != _info.IgnoreWhitespace))
|
||||
{
|
||||
LoadContent();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.IsSideBySide() != UseSideBySide)
|
||||
{
|
||||
ctx = ctx.SwitchMode();
|
||||
Content = ctx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadContent()
|
||||
{
|
||||
if (_option.Path.EndsWith('/'))
|
||||
{
|
||||
@@ -109,7 +156,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
|
||||
var numLines = Preferences.Instance.UseFullTextDiff ? _entireFileLine : _unifiedLines;
|
||||
var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
|
||||
|
||||
var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace)
|
||||
@@ -228,12 +275,22 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (_content is Models.TextDiff old && rs is Models.TextDiff cur && old.File == cur.File)
|
||||
cur.ScrollOffset = old.ScrollOffset;
|
||||
|
||||
FileModeChange = latest.FileModeChange;
|
||||
Content = rs;
|
||||
IsTextDiff = rs is Models.TextDiff;
|
||||
|
||||
if (rs is Models.TextDiff cur)
|
||||
{
|
||||
IsTextDiff = true;
|
||||
|
||||
if (Preferences.Instance.UseSideBySideDiff)
|
||||
Content = new TwoSideTextDiff(cur, _content as TwoSideTextDiff);
|
||||
else
|
||||
Content = new CombinedTextDiff(cur, _content as CombinedTextDiff);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsTextDiff = false;
|
||||
Content = rs;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -279,6 +336,7 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private readonly int _entireFileLine = 999999999;
|
||||
private readonly string _repo;
|
||||
private readonly Models.DiffOption _option = null;
|
||||
private string _fileModeChange = string.Empty;
|
||||
|
||||
@@ -38,7 +38,6 @@ namespace SourceGit.ViewModels
|
||||
public CommitDetail Detail
|
||||
{
|
||||
get => _detail;
|
||||
private set => SetProperty(ref _detail, value);
|
||||
}
|
||||
|
||||
public DirHistories(Repository repo, string dir, string revision = null)
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public class CustomActionControlTextBox : ICustomActionControlParameter
|
||||
{
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public string Placeholder { get; set; } = string.Empty;
|
||||
public string Text { get; set; } = string.Empty;
|
||||
public string Label { get; set; }
|
||||
public string Placeholder { get; set; }
|
||||
public string Text { get; set; }
|
||||
|
||||
public CustomActionControlTextBox(string label, string placeholder, string defaultValue)
|
||||
{
|
||||
@@ -31,9 +31,9 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public class CustomActionControlPathSelector : ObservableObject, ICustomActionControlParameter
|
||||
{
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public string Placeholder { get; set; } = string.Empty;
|
||||
public bool IsFolder { get; set; } = false;
|
||||
public string Label { get; set; }
|
||||
public string Placeholder { get; set; }
|
||||
public bool IsFolder { get; set; }
|
||||
|
||||
public string Path
|
||||
{
|
||||
@@ -51,14 +51,14 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public string GetValue() => _path;
|
||||
|
||||
private string _path = string.Empty;
|
||||
private string _path;
|
||||
}
|
||||
|
||||
public class CustomActionControlCheckBox : ICustomActionControlParameter
|
||||
{
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public string ToolTip { get; set; } = string.Empty;
|
||||
public string CheckedValue { get; set; } = string.Empty;
|
||||
public string Label { get; set; }
|
||||
public string ToolTip { get; set; }
|
||||
public string CheckedValue { get; set; }
|
||||
public bool IsChecked { get; set; }
|
||||
|
||||
public CustomActionControlCheckBox(string label, string tooltip, string checkedValue, bool isChecked)
|
||||
@@ -74,8 +74,8 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public class CustomActionControlComboBox : ObservableObject, ICustomActionControlParameter
|
||||
{
|
||||
public string Label { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public string Label { get; set; }
|
||||
public string Description { get; set; }
|
||||
public List<string> Options { get; set; } = [];
|
||||
|
||||
public string Value
|
||||
@@ -227,8 +227,8 @@ namespace SourceGit.ViewModels
|
||||
start.StandardErrorEncoding = Encoding.UTF8;
|
||||
start.WorkingDirectory = _repo.FullPath;
|
||||
|
||||
using var proc = new Process() { StartInfo = start };
|
||||
var builder = new StringBuilder();
|
||||
using var proc = new Process();
|
||||
proc.StartInfo = start;
|
||||
|
||||
proc.OutputDataReceived += (_, e) =>
|
||||
{
|
||||
@@ -236,6 +236,7 @@ namespace SourceGit.ViewModels
|
||||
log?.AppendLine(e.Data);
|
||||
};
|
||||
|
||||
var builder = new StringBuilder();
|
||||
proc.ErrorDataReceived += (_, e) =>
|
||||
{
|
||||
if (e.Data != null)
|
||||
|
||||
@@ -13,8 +13,7 @@ namespace SourceGit.ViewModels
|
||||
public bool IsFetchAllRemoteVisible
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = true;
|
||||
}
|
||||
|
||||
public bool FetchAllRemotes
|
||||
{
|
||||
|
||||
@@ -11,18 +11,13 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public record InteractiveRebasePrefill(string sha, Models.InteractiveRebaseAction action)
|
||||
{
|
||||
public string SHA { get; } = sha;
|
||||
public Models.InteractiveRebaseAction Action { get; } = action;
|
||||
}
|
||||
public record InteractiveRebasePrefill(string SHA, Models.InteractiveRebaseAction Action);
|
||||
|
||||
public class InteractiveRebaseItem : ObservableObject
|
||||
{
|
||||
public Models.Commit Commit
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool CanSquashOrFixup
|
||||
@@ -88,7 +83,6 @@ namespace SourceGit.ViewModels
|
||||
public Models.Commit On
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool AutoStash
|
||||
@@ -111,7 +105,6 @@ namespace SourceGit.ViewModels
|
||||
public AvaloniaList<InteractiveRebaseItem> Items
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = [];
|
||||
|
||||
public InteractiveRebaseItem SelectedItem
|
||||
@@ -127,7 +120,6 @@ namespace SourceGit.ViewModels
|
||||
public CommitDetail DetailContext
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public InteractiveRebase(Repository repo, Models.Commit on, InteractiveRebasePrefill prefill = null)
|
||||
@@ -151,7 +143,7 @@ namespace SourceGit.ViewModels
|
||||
list.Add(new InteractiveRebaseItem(c.Commit, c.Message, i < commits.Count - 1));
|
||||
}
|
||||
|
||||
InteractiveRebaseItem selected = list.Count > 0 ? list[0] : null;
|
||||
var selected = list.Count > 0 ? list[0] : null;
|
||||
if (prefill != null)
|
||||
{
|
||||
var item = list.Find(x => x.Commit.SHA.Equals(prefill.SHA, StringComparison.Ordinal));
|
||||
|
||||
@@ -119,6 +119,12 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _layout, value);
|
||||
}
|
||||
|
||||
public bool ShowLocalChangesByDefault
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = false;
|
||||
|
||||
public int MaxHistoryCommits
|
||||
{
|
||||
get => _maxHistoryCommits;
|
||||
@@ -255,12 +261,6 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _useFullTextDiff, value);
|
||||
}
|
||||
|
||||
public bool UseBlockNavigationInDiffView
|
||||
{
|
||||
get => _useBlockNavigationInDiffView;
|
||||
set => SetProperty(ref _useBlockNavigationInDiffView, value);
|
||||
}
|
||||
|
||||
public int LFSImageActiveIdx
|
||||
{
|
||||
get => _lfsImageActiveIdx;
|
||||
@@ -701,7 +701,7 @@ namespace SourceGit.ViewModels
|
||||
private double _defaultFontSize = 13;
|
||||
private double _editorFontSize = 13;
|
||||
private int _editorTabWidth = 4;
|
||||
private LayoutInfo _layout = new LayoutInfo();
|
||||
private LayoutInfo _layout = new();
|
||||
|
||||
private int _maxHistoryCommits = 20000;
|
||||
private int _subjectGuideLength = 50;
|
||||
@@ -722,7 +722,6 @@ namespace SourceGit.ViewModels
|
||||
private bool _enableDiffViewWordWrap = false;
|
||||
private bool _showHiddenSymbolsInDiffView = false;
|
||||
private bool _useFullTextDiff = false;
|
||||
private bool _useBlockNavigationInDiffView = false;
|
||||
private int _lfsImageActiveIdx = 0;
|
||||
private bool _enableCompactFoldersInChangesTree = false;
|
||||
|
||||
|
||||
@@ -22,25 +22,12 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public string FullPath
|
||||
{
|
||||
get => _fullpath;
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
var normalized = value.Replace('\\', '/').TrimEnd('/');
|
||||
SetProperty(ref _fullpath, normalized);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetProperty(ref _fullpath, null);
|
||||
}
|
||||
}
|
||||
get;
|
||||
}
|
||||
|
||||
public string GitDir
|
||||
{
|
||||
get => _gitDir;
|
||||
set => SetProperty(ref _gitDir, value);
|
||||
get;
|
||||
}
|
||||
|
||||
public Models.RepositorySettings Settings
|
||||
@@ -52,7 +39,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = new Models.GitFlow();
|
||||
} = new();
|
||||
|
||||
public Models.FilterMode HistoriesFilterMode
|
||||
{
|
||||
@@ -104,7 +91,7 @@ namespace SourceGit.ViewModels
|
||||
public Models.HistoryShowFlags HistoryShowFlags
|
||||
{
|
||||
get => _settings.HistoryShowFlags;
|
||||
set
|
||||
private set
|
||||
{
|
||||
if (value != _settings.HistoryShowFlags)
|
||||
{
|
||||
@@ -494,36 +481,34 @@ namespace SourceGit.ViewModels
|
||||
public AvaloniaList<Models.IssueTracker> IssueTrackers
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new AvaloniaList<Models.IssueTracker>();
|
||||
} = [];
|
||||
|
||||
public AvaloniaList<CommandLog> Logs
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new AvaloniaList<CommandLog>();
|
||||
} = [];
|
||||
|
||||
public Repository(bool isBare, string path, string gitDir)
|
||||
{
|
||||
IsBare = isBare;
|
||||
FullPath = path;
|
||||
GitDir = gitDir;
|
||||
FullPath = path.Replace('\\', '/').TrimEnd('/');
|
||||
GitDir = gitDir.Replace('\\', '/').TrimEnd('/');
|
||||
|
||||
var commonDirFile = Path.Combine(_gitDir, "commondir");
|
||||
_isWorktree = _gitDir.Replace('\\', '/').IndexOf("/worktrees/", StringComparison.Ordinal) > 0 &&
|
||||
File.Exists(commonDirFile);
|
||||
var commonDirFile = Path.Combine(GitDir, "commondir");
|
||||
_isWorktree = GitDir.IndexOf("/worktrees/", StringComparison.Ordinal) > 0 &&
|
||||
File.Exists(commonDirFile);
|
||||
|
||||
if (_isWorktree)
|
||||
{
|
||||
var commonDir = File.ReadAllText(commonDirFile).Trim();
|
||||
if (!Path.IsPathRooted(commonDir))
|
||||
commonDir = new DirectoryInfo(Path.Combine(_gitDir, commonDir)).FullName;
|
||||
commonDir = new DirectoryInfo(Path.Combine(GitDir, commonDir)).FullName;
|
||||
|
||||
_gitCommonDir = commonDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
_gitCommonDir = _gitDir;
|
||||
_gitCommonDir = GitDir;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,11 +534,11 @@ namespace SourceGit.ViewModels
|
||||
|
||||
try
|
||||
{
|
||||
_watcher = new Models.Watcher(this, _fullpath, _gitCommonDir);
|
||||
_watcher = new Models.Watcher(this, FullPath, _gitCommonDir);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.RaiseException(string.Empty, $"Failed to start watcher for repository: '{_fullpath}'. You may need to press 'F5' to refresh repository manually!\n\nReason: {ex.Message}");
|
||||
App.RaiseException(string.Empty, $"Failed to start watcher for repository: '{FullPath}'. You may need to press 'F5' to refresh repository manually!\n\nReason: {ex.Message}");
|
||||
}
|
||||
|
||||
if (_settings.HistoriesFilters.Count > 0)
|
||||
@@ -562,14 +547,22 @@ namespace SourceGit.ViewModels
|
||||
_historiesFilterMode = Models.FilterMode.None;
|
||||
|
||||
_histories = new Histories(this);
|
||||
_workingCopy = new WorkingCopy(this);
|
||||
_workingCopy = new WorkingCopy(this) { CommitMessage = _settings.LastCommitMessage };
|
||||
_stashesPage = new StashesPage(this);
|
||||
_selectedView = _histories;
|
||||
_selectedViewIndex = 0;
|
||||
|
||||
_workingCopy.CommitMessage = _settings.LastCommitMessage;
|
||||
if (Preferences.Instance.ShowLocalChangesByDefault)
|
||||
{
|
||||
_selectedView = _workingCopy;
|
||||
_selectedViewIndex = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedView = _histories;
|
||||
_selectedViewIndex = 0;
|
||||
}
|
||||
|
||||
_lastFetchTime = DateTime.Now;
|
||||
_autoFetchTimer = new Timer(AutoFetchInBackground, null, 5000, 5000);
|
||||
_autoFetchTimer = new Timer(FetchInBackground, null, 5000, 5000);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
@@ -585,6 +578,17 @@ namespace SourceGit.ViewModels
|
||||
JsonSerializer.Serialize(stream, _settings, JsonCodeGen.Default.RepositorySettings);
|
||||
}
|
||||
|
||||
if (_cancellationRefreshBranches is { IsCancellationRequested: false })
|
||||
_cancellationRefreshBranches.Cancel();
|
||||
if (_cancellationRefreshTags is { IsCancellationRequested: false })
|
||||
_cancellationRefreshTags.Cancel();
|
||||
if (_cancellationRefreshWorkingCopyChanges is { IsCancellationRequested: false })
|
||||
_cancellationRefreshWorkingCopyChanges.Cancel();
|
||||
if (_cancellationRefreshCommits is { IsCancellationRequested: false })
|
||||
_cancellationRefreshCommits.Cancel();
|
||||
if (_cancellationRefreshStashes is { IsCancellationRequested: false })
|
||||
_cancellationRefreshStashes.Cancel();
|
||||
|
||||
_autoFetchTimer.Dispose();
|
||||
_autoFetchTimer = null;
|
||||
|
||||
@@ -669,7 +673,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public bool IsLFSEnabled()
|
||||
{
|
||||
var path = Path.Combine(_fullpath, ".git", "hooks", "pre-push");
|
||||
var path = Path.Combine(FullPath, ".git", "hooks", "pre-push");
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
|
||||
@@ -680,9 +684,9 @@ namespace SourceGit.ViewModels
|
||||
public async Task InstallLFSAsync()
|
||||
{
|
||||
var log = CreateLog("Install LFS");
|
||||
var succ = await new Commands.LFS(_fullpath).Use(log).InstallAsync();
|
||||
var succ = await new Commands.LFS(FullPath).Use(log).InstallAsync();
|
||||
if (succ)
|
||||
App.SendNotification(_fullpath, "LFS enabled successfully!");
|
||||
App.SendNotification(FullPath, "LFS enabled successfully!");
|
||||
|
||||
log.Complete();
|
||||
}
|
||||
@@ -690,12 +694,12 @@ namespace SourceGit.ViewModels
|
||||
public async Task<bool> TrackLFSFileAsync(string pattern, bool isFilenameMode)
|
||||
{
|
||||
var log = CreateLog("Track LFS");
|
||||
var succ = await new Commands.LFS(_fullpath)
|
||||
var succ = await new Commands.LFS(FullPath)
|
||||
.Use(log)
|
||||
.TrackAsync(pattern, isFilenameMode);
|
||||
|
||||
if (succ)
|
||||
App.SendNotification(_fullpath, $"Tracking successfully! Pattern: {pattern}");
|
||||
App.SendNotification(FullPath, $"Tracking successfully! Pattern: {pattern}");
|
||||
|
||||
log.Complete();
|
||||
return succ;
|
||||
@@ -704,12 +708,12 @@ namespace SourceGit.ViewModels
|
||||
public async Task<bool> LockLFSFileAsync(string remote, string path)
|
||||
{
|
||||
var log = CreateLog("Lock LFS File");
|
||||
var succ = await new Commands.LFS(_fullpath)
|
||||
var succ = await new Commands.LFS(FullPath)
|
||||
.Use(log)
|
||||
.LockAsync(remote, path);
|
||||
|
||||
if (succ)
|
||||
App.SendNotification(_fullpath, $"Lock file successfully! File: {path}");
|
||||
App.SendNotification(FullPath, $"Lock file successfully! File: {path}");
|
||||
|
||||
log.Complete();
|
||||
return succ;
|
||||
@@ -718,12 +722,12 @@ namespace SourceGit.ViewModels
|
||||
public async Task<bool> UnlockLFSFileAsync(string remote, string path, bool force, bool notify)
|
||||
{
|
||||
var log = CreateLog("Unlock LFS File");
|
||||
var succ = await new Commands.LFS(_fullpath)
|
||||
var succ = await new Commands.LFS(FullPath)
|
||||
.Use(log)
|
||||
.UnlockAsync(remote, path, force);
|
||||
|
||||
if (succ && notify)
|
||||
App.SendNotification(_fullpath, $"Unlock file successfully! File: {path}");
|
||||
App.SendNotification(FullPath, $"Unlock file successfully! File: {path}");
|
||||
|
||||
log.Complete();
|
||||
return succ;
|
||||
@@ -790,7 +794,7 @@ namespace SourceGit.ViewModels
|
||||
IssueTrackers.AddRange(issuetrackers);
|
||||
});
|
||||
|
||||
var config = await new Commands.Config(_fullpath).ReadAllAsync().ConfigureAwait(false);
|
||||
var config = await new Commands.Config(FullPath).ReadAllAsync().ConfigureAwait(false);
|
||||
_hasAllowedSignersFile = config.TryGetValue("gpg.ssh.allowedSignersFile", out var allowedSignersFile) && !string.IsNullOrEmpty(allowedSignersFile);
|
||||
|
||||
if (config.TryGetValue("gitflow.branch.master", out var masterName))
|
||||
@@ -813,7 +817,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (_remotes.Count == 0)
|
||||
{
|
||||
App.RaiseException(_fullpath, "No remotes added to this repository!!!");
|
||||
App.RaiseException(FullPath, "No remotes added to this repository!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -830,13 +834,13 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (_remotes.Count == 0)
|
||||
{
|
||||
App.RaiseException(_fullpath, "No remotes added to this repository!!!");
|
||||
App.RaiseException(FullPath, "No remotes added to this repository!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentBranch == null)
|
||||
{
|
||||
App.RaiseException(_fullpath, "Can NOT find current branch!!!");
|
||||
App.RaiseException(FullPath, "Can NOT find current branch!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -854,13 +858,13 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (_remotes.Count == 0)
|
||||
{
|
||||
App.RaiseException(_fullpath, "No remotes added to this repository!!!");
|
||||
App.RaiseException(FullPath, "No remotes added to this repository!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentBranch == null)
|
||||
{
|
||||
App.RaiseException(_fullpath, "Can NOT find current branch!!!");
|
||||
App.RaiseException(FullPath, "Can NOT find current branch!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -925,13 +929,13 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (method == Models.CommitSearchMethod.BySHA)
|
||||
{
|
||||
var isCommitSHA = await new Commands.IsCommitSHA(_fullpath, _searchCommitFilter)
|
||||
var isCommitSHA = await new Commands.IsCommitSHA(FullPath, _searchCommitFilter)
|
||||
.GetResultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (isCommitSHA)
|
||||
{
|
||||
var commit = await new Commands.QuerySingleCommit(_fullpath, _searchCommitFilter)
|
||||
var commit = await new Commands.QuerySingleCommit(FullPath, _searchCommitFilter)
|
||||
.GetResultAsync()
|
||||
.ConfigureAwait(false);
|
||||
visible.Add(commit);
|
||||
@@ -939,7 +943,7 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
visible = await new Commands.QueryCommits(_fullpath, _searchCommitFilter, method, _onlySearchCommitsInCurrentBranch)
|
||||
visible = await new Commands.QueryCommits(FullPath, _searchCommitFilter, method, _onlySearchCommitsInCurrentBranch)
|
||||
.GetResultAsync()
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
@@ -959,38 +963,24 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void MarkBranchesDirtyManually()
|
||||
{
|
||||
if (_watcher == null)
|
||||
{
|
||||
RefreshBranches();
|
||||
RefreshCommits();
|
||||
RefreshWorkingCopyChanges();
|
||||
RefreshWorktrees();
|
||||
}
|
||||
else
|
||||
{
|
||||
_watcher.MarkBranchDirtyManually();
|
||||
}
|
||||
_watcher?.MarkBranchUpdated();
|
||||
RefreshBranches();
|
||||
RefreshCommits();
|
||||
RefreshWorkingCopyChanges();
|
||||
RefreshWorktrees();
|
||||
}
|
||||
|
||||
public void MarkTagsDirtyManually()
|
||||
{
|
||||
if (_watcher == null)
|
||||
{
|
||||
RefreshTags();
|
||||
RefreshCommits();
|
||||
}
|
||||
else
|
||||
{
|
||||
_watcher.MarkTagDirtyManually();
|
||||
}
|
||||
_watcher?.MarkTagUpdated();
|
||||
RefreshTags();
|
||||
RefreshCommits();
|
||||
}
|
||||
|
||||
public void MarkWorkingCopyDirtyManually()
|
||||
{
|
||||
if (_watcher == null)
|
||||
RefreshWorkingCopyChanges();
|
||||
else
|
||||
_watcher.MarkWorkingCopyDirtyManually();
|
||||
_watcher?.MarkWorkingCopyUpdated();
|
||||
RefreshWorkingCopyChanges();
|
||||
}
|
||||
|
||||
public void MarkFetched()
|
||||
@@ -1125,17 +1115,20 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public async Task StashAllAsync(bool autoStart)
|
||||
{
|
||||
await _workingCopy?.StashAllAsync(autoStart);
|
||||
if (_workingCopy != null)
|
||||
await _workingCopy.StashAllAsync(autoStart);
|
||||
}
|
||||
|
||||
public async Task SkipMergeAsync()
|
||||
{
|
||||
await _workingCopy?.SkipMergeAsync();
|
||||
if (_workingCopy != null)
|
||||
await _workingCopy.SkipMergeAsync();
|
||||
}
|
||||
|
||||
public async Task AbortMergeAsync()
|
||||
{
|
||||
await _workingCopy?.AbortMergeAsync();
|
||||
if (_workingCopy != null)
|
||||
await _workingCopy.AbortMergeAsync();
|
||||
}
|
||||
|
||||
public List<(Models.CustomAction, CustomActionContextMenuLabel)> GetCustomActions(Models.CustomActionScope scope)
|
||||
@@ -1164,14 +1157,14 @@ namespace SourceGit.ViewModels
|
||||
|
||||
var log = CreateLog($"Bisect({subcmd})");
|
||||
|
||||
var succ = await new Commands.Bisect(_fullpath, subcmd).Use(log).ExecAsync();
|
||||
var succ = await new Commands.Bisect(FullPath, subcmd).Use(log).ExecAsync();
|
||||
log.Complete();
|
||||
|
||||
var head = await new Commands.QueryRevisionByRefName(_fullpath, "HEAD").GetResultAsync();
|
||||
var head = await new Commands.QueryRevisionByRefName(FullPath, "HEAD").GetResultAsync();
|
||||
if (!succ)
|
||||
App.RaiseException(_fullpath, log.Content.Substring(log.Content.IndexOf('\n')).Trim());
|
||||
App.RaiseException(FullPath, log.Content.Substring(log.Content.IndexOf('\n')).Trim());
|
||||
else if (log.Content.Contains("is the first bad commit"))
|
||||
App.SendNotification(_fullpath, log.Content.Substring(log.Content.IndexOf('\n')).Trim());
|
||||
App.SendNotification(FullPath, log.Content.Substring(log.Content.IndexOf('\n')).Trim());
|
||||
|
||||
MarkBranchesDirtyManually();
|
||||
NavigateToCommit(head, true);
|
||||
@@ -1181,21 +1174,30 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public bool MayHaveSubmodules()
|
||||
{
|
||||
var modulesFile = Path.Combine(_fullpath, ".gitmodules");
|
||||
var modulesFile = Path.Combine(FullPath, ".gitmodules");
|
||||
var info = new FileInfo(modulesFile);
|
||||
return info.Exists && info.Length > 20;
|
||||
}
|
||||
|
||||
public void RefreshBranches()
|
||||
{
|
||||
if (_cancellationRefreshBranches is { IsCancellationRequested: false })
|
||||
_cancellationRefreshBranches.Cancel();
|
||||
|
||||
_cancellationRefreshBranches = new CancellationTokenSource();
|
||||
var token = _cancellationRefreshBranches.Token;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var branches = await new Commands.QueryBranches(_fullpath).GetResultAsync().ConfigureAwait(false);
|
||||
var remotes = await new Commands.QueryRemotes(_fullpath).GetResultAsync().ConfigureAwait(false);
|
||||
var branches = await new Commands.QueryBranches(FullPath).GetResultAsync().ConfigureAwait(false);
|
||||
var remotes = await new Commands.QueryRemotes(FullPath).GetResultAsync().ConfigureAwait(false);
|
||||
var builder = BuildBranchTree(branches, remotes);
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
Remotes = remotes;
|
||||
Branches = branches;
|
||||
CurrentBranch = branches.Find(x => x.IsCurrent);
|
||||
@@ -1216,58 +1218,64 @@ namespace SourceGit.ViewModels
|
||||
var hasPendingPullOrPush = CurrentBranch?.TrackStatus.IsVisible ?? false;
|
||||
GetOwnerPage()?.ChangeDirtyState(Models.DirtyState.HasPendingPullOrPush, !hasPendingPullOrPush);
|
||||
});
|
||||
});
|
||||
}, token);
|
||||
}
|
||||
|
||||
public void RefreshWorktrees()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var worktrees = await new Commands.Worktree(_fullpath).ReadAllAsync().ConfigureAwait(false);
|
||||
if (worktrees.Count > 0)
|
||||
var worktrees = await new Commands.Worktree(FullPath).ReadAllAsync().ConfigureAwait(false);
|
||||
if (worktrees.Count == 0)
|
||||
{
|
||||
var cleaned = new List<Models.Worktree>();
|
||||
var normalizedGitDir = _gitDir.Replace('\\', '/');
|
||||
|
||||
foreach (var worktree in worktrees)
|
||||
{
|
||||
if (worktree.FullPath.Equals(_fullpath, StringComparison.Ordinal) ||
|
||||
worktree.FullPath.Equals(normalizedGitDir, StringComparison.Ordinal))
|
||||
continue;
|
||||
|
||||
cleaned.Add(worktree);
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
Worktrees = cleaned;
|
||||
});
|
||||
Dispatcher.UIThread.Invoke(() => Worktrees = worktrees);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
var cleaned = new List<Models.Worktree>();
|
||||
foreach (var worktree in worktrees)
|
||||
{
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
Worktrees = worktrees;
|
||||
});
|
||||
if (worktree.FullPath.Equals(FullPath, StringComparison.Ordinal) ||
|
||||
worktree.FullPath.Equals(GitDir, StringComparison.Ordinal))
|
||||
continue;
|
||||
|
||||
cleaned.Add(worktree);
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.Invoke(() => Worktrees = cleaned);
|
||||
});
|
||||
}
|
||||
|
||||
public void RefreshTags()
|
||||
{
|
||||
if (_cancellationRefreshTags is { IsCancellationRequested: false })
|
||||
_cancellationRefreshTags.Cancel();
|
||||
|
||||
_cancellationRefreshTags = new CancellationTokenSource();
|
||||
var token = _cancellationRefreshTags.Token;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var tags = await new Commands.QueryTags(_fullpath).GetResultAsync().ConfigureAwait(false);
|
||||
var tags = await new Commands.QueryTags(FullPath).GetResultAsync().ConfigureAwait(false);
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
Tags = tags;
|
||||
VisibleTags = BuildVisibleTags();
|
||||
});
|
||||
});
|
||||
}, token);
|
||||
}
|
||||
|
||||
public void RefreshCommits()
|
||||
{
|
||||
if (_cancellationRefreshCommits is { IsCancellationRequested: false })
|
||||
_cancellationRefreshCommits.Cancel();
|
||||
|
||||
_cancellationRefreshCommits = new CancellationTokenSource();
|
||||
var token = _cancellationRefreshCommits.Token;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Dispatcher.UIThread.InvokeAsync(() => _histories.IsLoading = true);
|
||||
@@ -1295,11 +1303,14 @@ namespace SourceGit.ViewModels
|
||||
else
|
||||
builder.Append(filters);
|
||||
|
||||
var commits = await new Commands.QueryCommits(_fullpath, builder.ToString()).GetResultAsync().ConfigureAwait(false);
|
||||
var commits = await new Commands.QueryCommits(FullPath, builder.ToString()).GetResultAsync().ConfigureAwait(false);
|
||||
var graph = Models.CommitGraph.Parse(commits, _settings.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.FirstParentOnly));
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
if (_histories != null)
|
||||
{
|
||||
_histories.IsLoading = false;
|
||||
@@ -1314,7 +1325,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
_navigateToCommitDelayed = string.Empty;
|
||||
});
|
||||
});
|
||||
}, token);
|
||||
}
|
||||
|
||||
public void RefreshSubmodules()
|
||||
@@ -1335,7 +1346,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var submodules = await new Commands.QuerySubmodules(_fullpath).GetResultAsync().ConfigureAwait(false);
|
||||
var submodules = await new Commands.QuerySubmodules(FullPath).GetResultAsync().ConfigureAwait(false);
|
||||
_watcher?.SetSubmodules(submodules);
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
@@ -1379,25 +1390,34 @@ namespace SourceGit.ViewModels
|
||||
if (IsBare)
|
||||
return;
|
||||
|
||||
if (_cancellationRefreshWorkingCopyChanges is { IsCancellationRequested: false })
|
||||
_cancellationRefreshWorkingCopyChanges.Cancel();
|
||||
|
||||
_cancellationRefreshWorkingCopyChanges = new CancellationTokenSource();
|
||||
var token = _cancellationRefreshWorkingCopyChanges.Token;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var changes = await new Commands.QueryLocalChanges(_fullpath, _settings.IncludeUntrackedInLocalChanges)
|
||||
var changes = await new Commands.QueryLocalChanges(FullPath, _settings.IncludeUntrackedInLocalChanges)
|
||||
.GetResultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (_workingCopy == null)
|
||||
if (_workingCopy == null || token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path));
|
||||
_workingCopy.SetData(changes);
|
||||
_workingCopy.SetData(changes, token);
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
LocalChangesCount = changes.Count;
|
||||
OnPropertyChanged(nameof(InProgressContext));
|
||||
GetOwnerPage()?.ChangeDirtyState(Models.DirtyState.HasLocalChanges, changes.Count == 0);
|
||||
});
|
||||
});
|
||||
}, token);
|
||||
}
|
||||
|
||||
public void RefreshStashes()
|
||||
@@ -1405,17 +1425,26 @@ namespace SourceGit.ViewModels
|
||||
if (IsBare)
|
||||
return;
|
||||
|
||||
if (_cancellationRefreshStashes is { IsCancellationRequested: false })
|
||||
_cancellationRefreshStashes.Cancel();
|
||||
|
||||
_cancellationRefreshStashes = new CancellationTokenSource();
|
||||
var token = _cancellationRefreshStashes.Token;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var stashes = await new Commands.QueryStashes(_fullpath).GetResultAsync().ConfigureAwait(false);
|
||||
var stashes = await new Commands.QueryStashes(FullPath).GetResultAsync().ConfigureAwait(false);
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
if (_stashesPage != null)
|
||||
_stashesPage.Stashes = stashes;
|
||||
|
||||
StashesCount = stashes.Count;
|
||||
});
|
||||
});
|
||||
}, token);
|
||||
}
|
||||
|
||||
public void ToggleHistoryShowFlag(Models.HistoryShowFlags flag)
|
||||
@@ -1430,7 +1459,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (_currentBranch == null)
|
||||
{
|
||||
App.RaiseException(_fullpath, "Git cannot create a branch before your first commit.");
|
||||
App.RaiseException(FullPath, "Git cannot create a branch before your first commit.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1486,9 +1515,9 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public async Task CheckoutTagAsync(Models.Tag tag)
|
||||
{
|
||||
var c = await new Commands.QuerySingleCommit(_fullpath, tag.SHA).GetResultAsync();
|
||||
if (c != null)
|
||||
await _histories?.CheckoutBranchByCommitAsync(c);
|
||||
var c = await new Commands.QuerySingleCommit(FullPath, tag.SHA).GetResultAsync();
|
||||
if (c != null && _histories != null)
|
||||
await _histories.CheckoutBranchByCommitAsync(c);
|
||||
}
|
||||
|
||||
public async Task CompareBranchWithWorktreeAsync(Models.Branch branch)
|
||||
@@ -1497,9 +1526,9 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
SelectedSearchedCommit = null;
|
||||
|
||||
var target = await new Commands.QuerySingleCommit(_fullpath, branch.Head).GetResultAsync();
|
||||
var target = await new Commands.QuerySingleCommit(FullPath, branch.Head).GetResultAsync();
|
||||
_histories.AutoSelectedCommit = null;
|
||||
_histories.DetailContext = new RevisionCompare(_fullpath, target, null);
|
||||
_histories.DetailContext = new RevisionCompare(FullPath, target, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1525,7 +1554,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (_currentBranch == null)
|
||||
{
|
||||
App.RaiseException(_fullpath, "Git cannot create a branch before your first commit.");
|
||||
App.RaiseException(FullPath, "Git cannot create a branch before your first commit.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1569,7 +1598,7 @@ namespace SourceGit.ViewModels
|
||||
if (selfPage == null)
|
||||
return;
|
||||
|
||||
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
|
||||
var root = Path.GetFullPath(Path.Combine(FullPath, submodule));
|
||||
var normalizedPath = root.Replace('\\', '/').TrimEnd('/');
|
||||
|
||||
var node = Preferences.Instance.FindNode(normalizedPath) ??
|
||||
@@ -1614,7 +1643,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
SetWatcherEnabled(false);
|
||||
var log = CreateLog("Lock Worktree");
|
||||
var succ = await new Commands.Worktree(_fullpath).Use(log).LockAsync(worktree.FullPath);
|
||||
var succ = await new Commands.Worktree(FullPath).Use(log).LockAsync(worktree.FullPath);
|
||||
if (succ)
|
||||
worktree.IsLocked = true;
|
||||
log.Complete();
|
||||
@@ -1625,7 +1654,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
SetWatcherEnabled(false);
|
||||
var log = CreateLog("Unlock Worktree");
|
||||
var succ = await new Commands.Worktree(_fullpath).Use(log).UnlockAsync(worktree.FullPath);
|
||||
var succ = await new Commands.Worktree(FullPath).Use(log).UnlockAsync(worktree.FullPath);
|
||||
if (succ)
|
||||
worktree.IsLocked = false;
|
||||
log.Complete();
|
||||
@@ -1668,7 +1697,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public async Task<bool> SaveCommitAsPatchAsync(Models.Commit commit, string folder, int index = 0)
|
||||
{
|
||||
var ignore_chars = new HashSet<char> { '/', '\\', ':', ',', '*', '?', '\"', '<', '>', '|', '`', '$', '^', '%', '[', ']', '+', '-' };
|
||||
var ignoredChars = new HashSet<char> { '/', '\\', ':', ',', '*', '?', '\"', '<', '>', '|', '`', '$', '^', '%', '[', ']', '+', '-' };
|
||||
var builder = new StringBuilder();
|
||||
builder.Append(index.ToString("D4"));
|
||||
builder.Append('-');
|
||||
@@ -1677,7 +1706,7 @@ namespace SourceGit.ViewModels
|
||||
var len = 0;
|
||||
foreach (var c in chars)
|
||||
{
|
||||
if (!ignore_chars.Contains(c))
|
||||
if (!ignoredChars.Contains(c))
|
||||
{
|
||||
if (c == ' ' || c == '\t')
|
||||
builder.Append('-');
|
||||
@@ -1694,7 +1723,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
var saveTo = Path.Combine(folder, builder.ToString());
|
||||
var log = CreateLog("Save Commit as Patch");
|
||||
var succ = await new Commands.FormatPatch(_fullpath, commit.SHA, saveTo).Use(log).ExecAsync();
|
||||
var succ = await new Commands.FormatPatch(FullPath, commit.SHA, saveTo).Use(log).ExecAsync();
|
||||
log.Complete();
|
||||
return succ;
|
||||
}
|
||||
@@ -1707,7 +1736,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
foreach (var page in launcher.Pages)
|
||||
{
|
||||
if (page.Node.Id.Equals(_fullpath))
|
||||
if (page.Node.Id.Equals(FullPath))
|
||||
return page;
|
||||
}
|
||||
|
||||
@@ -1716,7 +1745,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
private Commands.IssueTracker CreateIssueTrackerCommand(bool shared)
|
||||
{
|
||||
return new Commands.IssueTracker(_fullpath, shared ? $"{_fullpath}/.issuetracker" : null);
|
||||
return new Commands.IssueTracker(FullPath, shared ? $"{FullPath}/.issuetracker" : null);
|
||||
}
|
||||
|
||||
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
|
||||
@@ -1884,6 +1913,9 @@ namespace SourceGit.ViewModels
|
||||
|
||||
private BranchTreeNode FindBranchNode(List<BranchTreeNode> nodes, string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return null;
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
if (node.Path.Equals(path, StringComparison.Ordinal))
|
||||
@@ -1923,7 +1955,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
_worktreeFiles = await new Commands.QueryRevisionFileNames(_fullpath, "HEAD")
|
||||
_worktreeFiles = await new Commands.QueryRevisionFileNames(FullPath, "HEAD")
|
||||
.GetResultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@@ -1959,11 +1991,11 @@ namespace SourceGit.ViewModels
|
||||
MatchedFilesForSearching = matched;
|
||||
}
|
||||
|
||||
private void AutoFetchInBackground(object sender)
|
||||
private void FetchInBackground(object sender)
|
||||
{
|
||||
Dispatcher.UIThread.Post(async () =>
|
||||
Dispatcher.UIThread.Invoke(async Task () =>
|
||||
{
|
||||
if (_settings == null || !_settings.EnableAutoFetch)
|
||||
if (_settings is not { EnableAutoFetch: true })
|
||||
return;
|
||||
|
||||
if (!CanCreatePopup())
|
||||
@@ -1972,7 +2004,7 @@ namespace SourceGit.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
var lockFile = Path.Combine(_gitDir, "index.lock");
|
||||
var lockFile = Path.Combine(GitDir, "index.lock");
|
||||
if (File.Exists(lockFile))
|
||||
return;
|
||||
|
||||
@@ -1981,16 +2013,16 @@ namespace SourceGit.ViewModels
|
||||
if (desire > now)
|
||||
return;
|
||||
|
||||
IsAutoFetching = true;
|
||||
|
||||
var remotes = new List<string>();
|
||||
foreach (var r in _remotes)
|
||||
remotes.Add(r.Name);
|
||||
|
||||
IsAutoFetching = true;
|
||||
|
||||
if (_settings.FetchAllRemotes)
|
||||
{
|
||||
foreach (var remote in remotes)
|
||||
await new Commands.Fetch(_fullpath, remote, false, false) { RaiseError = false }.RunAsync();
|
||||
await new Commands.Fetch(FullPath, remote, false, false) { RaiseError = false }.RunAsync();
|
||||
}
|
||||
else if (remotes.Count > 0)
|
||||
{
|
||||
@@ -1998,7 +2030,7 @@ namespace SourceGit.ViewModels
|
||||
remotes.Find(x => x.Equals(_settings.DefaultRemote, StringComparison.Ordinal)) :
|
||||
remotes[0];
|
||||
|
||||
await new Commands.Fetch(_fullpath, remote, false, false) { RaiseError = false }.RunAsync();
|
||||
await new Commands.Fetch(FullPath, remote, false, false) { RaiseError = false }.RunAsync();
|
||||
}
|
||||
|
||||
_lastFetchTime = DateTime.Now;
|
||||
@@ -2006,10 +2038,8 @@ namespace SourceGit.ViewModels
|
||||
});
|
||||
}
|
||||
|
||||
private string _fullpath = string.Empty;
|
||||
private string _gitDir = string.Empty;
|
||||
private string _gitCommonDir = string.Empty;
|
||||
private bool _isWorktree = false;
|
||||
private readonly bool _isWorktree = false;
|
||||
private readonly string _gitCommonDir = null;
|
||||
private Models.RepositorySettings _settings = null;
|
||||
private Models.FilterMode _historiesFilterMode = Models.FilterMode.None;
|
||||
private bool _hasAllowedSignersFile = false;
|
||||
@@ -2030,23 +2060,24 @@ namespace SourceGit.ViewModels
|
||||
private int _searchCommitFilterType = (int)Models.CommitSearchMethod.ByMessage;
|
||||
private bool _onlySearchCommitsInCurrentBranch = false;
|
||||
private string _searchCommitFilter = string.Empty;
|
||||
private List<Models.Commit> _searchedCommits = new List<Models.Commit>();
|
||||
private List<Models.Commit> _searchedCommits = [];
|
||||
private Models.Commit _selectedSearchedCommit = null;
|
||||
private bool _requestingWorktreeFiles = false;
|
||||
private List<string> _worktreeFiles = null;
|
||||
private List<string> _matchedFilesForSearching = null;
|
||||
|
||||
private string _filter = string.Empty;
|
||||
private List<Models.Remote> _remotes = new List<Models.Remote>();
|
||||
private List<Models.Branch> _branches = new List<Models.Branch>();
|
||||
private List<Models.Remote> _remotes = [];
|
||||
private List<Models.Branch> _branches = [];
|
||||
private Models.Branch _currentBranch = null;
|
||||
private List<BranchTreeNode> _localBranchTrees = new List<BranchTreeNode>();
|
||||
private List<BranchTreeNode> _remoteBranchTrees = new List<BranchTreeNode>();
|
||||
private List<Models.Worktree> _worktrees = new List<Models.Worktree>();
|
||||
private List<Models.Tag> _tags = new List<Models.Tag>();
|
||||
private List<BranchTreeNode> _localBranchTrees = [];
|
||||
private List<BranchTreeNode> _remoteBranchTrees = [];
|
||||
private List<Models.Worktree> _worktrees = [];
|
||||
private List<Models.Tag> _tags = [];
|
||||
private object _visibleTags = null;
|
||||
private List<Models.Submodule> _submodules = new List<Models.Submodule>();
|
||||
private List<Models.Submodule> _submodules = [];
|
||||
private object _visibleSubmodules = null;
|
||||
private string _navigateToCommitDelayed = string.Empty;
|
||||
|
||||
private bool _isAutoFetching = false;
|
||||
private Timer _autoFetchTimer = null;
|
||||
@@ -2055,6 +2086,10 @@ namespace SourceGit.ViewModels
|
||||
private Models.BisectState _bisectState = Models.BisectState.None;
|
||||
private bool _isBisectCommandRunning = false;
|
||||
|
||||
private string _navigateToCommitDelayed = string.Empty;
|
||||
private CancellationTokenSource _cancellationRefreshBranches = null;
|
||||
private CancellationTokenSource _cancellationRefreshTags = null;
|
||||
private CancellationTokenSource _cancellationRefreshWorkingCopyChanges = null;
|
||||
private CancellationTokenSource _cancellationRefreshCommits = null;
|
||||
private CancellationTokenSource _cancellationRefreshStashes = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,6 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
public class RevisionCompare : ObservableObject, IDisposable
|
||||
{
|
||||
public string RepositoryPath
|
||||
{
|
||||
get => _repo;
|
||||
}
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get => _isLoading;
|
||||
@@ -127,6 +122,11 @@ namespace SourceGit.ViewModels
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public string GetAbsPath(string path)
|
||||
{
|
||||
return Native.OS.GetAbsPath(_repo, path);
|
||||
}
|
||||
|
||||
public void SaveAsPatch(string saveTo)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
|
||||
@@ -9,11 +9,6 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
public class StashesPage : ObservableObject, IDisposable
|
||||
{
|
||||
public string RepositoryPath
|
||||
{
|
||||
get => _repo.FullPath;
|
||||
}
|
||||
|
||||
public List<Models.Stash> Stashes
|
||||
{
|
||||
get => _stashes;
|
||||
@@ -146,6 +141,11 @@ namespace SourceGit.ViewModels
|
||||
SearchFilter = string.Empty;
|
||||
}
|
||||
|
||||
public string GetAbsPath(string path)
|
||||
{
|
||||
return Native.OS.GetAbsPath(_repo.FullPath, path);
|
||||
}
|
||||
|
||||
public void Apply(Models.Stash stash)
|
||||
{
|
||||
if (_repo.CanCreatePopup())
|
||||
|
||||
261
src/ViewModels/TextDiffContext.cs
Normal file
261
src/ViewModels/TextDiffContext.cs
Normal file
@@ -0,0 +1,261 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public record TextDiffSelectedChunk(double Y, double Height, int StartIdx, int EndIdx, bool Combined, bool IsOldSide)
|
||||
{
|
||||
public static bool IsChanged(TextDiffSelectedChunk oldValue, TextDiffSelectedChunk newValue)
|
||||
{
|
||||
if (newValue == null)
|
||||
return oldValue != null;
|
||||
|
||||
if (oldValue == null)
|
||||
return true;
|
||||
|
||||
return Math.Abs(newValue.Y - oldValue.Y) > 0.001 ||
|
||||
Math.Abs(newValue.Height - oldValue.Height) > 0.001 ||
|
||||
newValue.StartIdx != oldValue.StartIdx ||
|
||||
newValue.EndIdx != oldValue.EndIdx ||
|
||||
newValue.Combined != oldValue.Combined ||
|
||||
newValue.IsOldSide != oldValue.IsOldSide;
|
||||
}
|
||||
}
|
||||
|
||||
public record TextDiffDisplayRange(int Start, int End)
|
||||
{
|
||||
}
|
||||
|
||||
public class TextDiffContext : ObservableObject
|
||||
{
|
||||
public Models.TextDiff Data => _data;
|
||||
public string File => _data.File;
|
||||
public bool IsUnstaged => _data.Option.IsUnstaged;
|
||||
public bool EnableChunkOption => _data.Option.WorkingCopyChange != null;
|
||||
|
||||
public Vector ScrollOffset
|
||||
{
|
||||
get => _scrollOffset;
|
||||
set => SetProperty(ref _scrollOffset, value);
|
||||
}
|
||||
|
||||
public BlockNavigation BlockNavigation
|
||||
{
|
||||
get => _blockNavigation;
|
||||
set => SetProperty(ref _blockNavigation, value);
|
||||
}
|
||||
|
||||
public TextDiffDisplayRange DisplayRange
|
||||
{
|
||||
get => _displayRange;
|
||||
set => SetProperty(ref _displayRange, value);
|
||||
}
|
||||
|
||||
public TextDiffSelectedChunk SelectedChunk
|
||||
{
|
||||
get => _selectedChunk;
|
||||
set => SetProperty(ref _selectedChunk, value);
|
||||
}
|
||||
|
||||
public (int, int) FindRangeByIndex(List<Models.TextDiffLine> lines, int lineIdx)
|
||||
{
|
||||
var startIdx = -1;
|
||||
var endIdx = -1;
|
||||
|
||||
var normalLineCount = 0;
|
||||
var modifiedLineCount = 0;
|
||||
|
||||
for (int i = lineIdx; i >= 0; i--)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (line.Type == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
startIdx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.Type == Models.TextDiffLineType.Normal)
|
||||
{
|
||||
normalLineCount++;
|
||||
if (normalLineCount >= 2)
|
||||
{
|
||||
startIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
normalLineCount = 0;
|
||||
modifiedLineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
normalLineCount = lines[lineIdx].Type == Models.TextDiffLineType.Normal ? 1 : 0;
|
||||
for (int i = lineIdx + 1; i < lines.Count; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (line.Type == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
endIdx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.Type == Models.TextDiffLineType.Normal)
|
||||
{
|
||||
normalLineCount++;
|
||||
if (normalLineCount >= 2)
|
||||
{
|
||||
endIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
normalLineCount = 0;
|
||||
modifiedLineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (endIdx == -1)
|
||||
endIdx = lines.Count - 1;
|
||||
|
||||
return modifiedLineCount > 0 ? (startIdx, endIdx) : (-1, -1);
|
||||
}
|
||||
|
||||
public virtual bool IsSideBySide()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual TextDiffContext SwitchMode()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Models.TextDiff _data = null;
|
||||
protected Vector _scrollOffset = Vector.Zero;
|
||||
protected BlockNavigation _blockNavigation = null;
|
||||
|
||||
private TextDiffDisplayRange _displayRange = null;
|
||||
private TextDiffSelectedChunk _selectedChunk = null;
|
||||
}
|
||||
|
||||
public class CombinedTextDiff : TextDiffContext
|
||||
{
|
||||
public CombinedTextDiff(Models.TextDiff diff, CombinedTextDiff previous = null)
|
||||
{
|
||||
_data = diff;
|
||||
_blockNavigation = new BlockNavigation(_data.Lines);
|
||||
|
||||
if (previous != null && previous.File.Equals(File, StringComparison.Ordinal))
|
||||
_scrollOffset = previous.ScrollOffset;
|
||||
}
|
||||
|
||||
public override TextDiffContext SwitchMode()
|
||||
{
|
||||
return new TwoSideTextDiff(_data);
|
||||
}
|
||||
}
|
||||
|
||||
public class TwoSideTextDiff : TextDiffContext
|
||||
{
|
||||
public List<Models.TextDiffLine> Old { get; } = [];
|
||||
public List<Models.TextDiffLine> New { get; } = [];
|
||||
|
||||
public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
|
||||
{
|
||||
_data = diff;
|
||||
|
||||
foreach (var line in diff.Lines)
|
||||
{
|
||||
switch (line.Type)
|
||||
{
|
||||
case Models.TextDiffLineType.Added:
|
||||
New.Add(line);
|
||||
break;
|
||||
case Models.TextDiffLineType.Deleted:
|
||||
Old.Add(line);
|
||||
break;
|
||||
default:
|
||||
FillEmptyLines();
|
||||
Old.Add(line);
|
||||
New.Add(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FillEmptyLines();
|
||||
_blockNavigation = new BlockNavigation(Old);
|
||||
|
||||
if (previous != null && previous.File.Equals(File, StringComparison.Ordinal))
|
||||
_scrollOffset = previous._scrollOffset;
|
||||
}
|
||||
|
||||
public override bool IsSideBySide()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override TextDiffContext SwitchMode()
|
||||
{
|
||||
return new CombinedTextDiff(_data);
|
||||
}
|
||||
|
||||
public void ConvertsToCombinedRange(ref int startLine, ref int endLine, bool isOldSide)
|
||||
{
|
||||
endLine = Math.Min(endLine, _data.Lines.Count - 1);
|
||||
|
||||
var oneSide = isOldSide ? Old : New;
|
||||
var firstContentLine = -1;
|
||||
for (int i = startLine; i <= endLine; i++)
|
||||
{
|
||||
var line = oneSide[i];
|
||||
if (line.Type != Models.TextDiffLineType.None)
|
||||
{
|
||||
firstContentLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstContentLine < 0)
|
||||
return;
|
||||
|
||||
var endContentLine = -1;
|
||||
for (int i = Math.Min(endLine, oneSide.Count - 1); i >= startLine; i--)
|
||||
{
|
||||
var line = oneSide[i];
|
||||
if (line.Type != Models.TextDiffLineType.None)
|
||||
{
|
||||
endContentLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endContentLine < 0)
|
||||
return;
|
||||
|
||||
var firstContent = oneSide[firstContentLine];
|
||||
var endContent = oneSide[endContentLine];
|
||||
startLine = _data.Lines.IndexOf(firstContent);
|
||||
endLine = _data.Lines.IndexOf(endContent);
|
||||
}
|
||||
|
||||
private void FillEmptyLines()
|
||||
{
|
||||
if (Old.Count < New.Count)
|
||||
{
|
||||
int diff = New.Count - Old.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
Old.Add(new Models.TextDiffLine());
|
||||
}
|
||||
else if (Old.Count > New.Count)
|
||||
{
|
||||
int diff = Old.Count - New.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
New.Add(new Models.TextDiffLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Avalonia;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class TwoSideTextDiff : ObservableObject
|
||||
{
|
||||
public string File { get; set; }
|
||||
public List<Models.TextDiffLine> Old { get; set; } = new List<Models.TextDiffLine>();
|
||||
public List<Models.TextDiffLine> New { get; set; } = new List<Models.TextDiffLine>();
|
||||
public int MaxLineNumber = 0;
|
||||
|
||||
public Vector SyncScrollOffset
|
||||
{
|
||||
get => _syncScrollOffset;
|
||||
set => SetProperty(ref _syncScrollOffset, value);
|
||||
}
|
||||
|
||||
public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
|
||||
{
|
||||
File = diff.File;
|
||||
MaxLineNumber = diff.MaxLineNumber;
|
||||
|
||||
foreach (var line in diff.Lines)
|
||||
{
|
||||
switch (line.Type)
|
||||
{
|
||||
case Models.TextDiffLineType.Added:
|
||||
New.Add(line);
|
||||
break;
|
||||
case Models.TextDiffLineType.Deleted:
|
||||
Old.Add(line);
|
||||
break;
|
||||
default:
|
||||
FillEmptyLines();
|
||||
Old.Add(line);
|
||||
New.Add(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FillEmptyLines();
|
||||
|
||||
if (previous != null && previous.File == File)
|
||||
_syncScrollOffset = previous._syncScrollOffset;
|
||||
}
|
||||
|
||||
public void ConvertsToCombinedRange(Models.TextDiff combined, ref int startLine, ref int endLine, bool isOldSide)
|
||||
{
|
||||
endLine = Math.Min(endLine, combined.Lines.Count - 1);
|
||||
|
||||
var oneSide = isOldSide ? Old : New;
|
||||
var firstContentLine = -1;
|
||||
for (int i = startLine; i <= endLine; i++)
|
||||
{
|
||||
var line = oneSide[i];
|
||||
if (line.Type != Models.TextDiffLineType.None)
|
||||
{
|
||||
firstContentLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstContentLine < 0)
|
||||
return;
|
||||
|
||||
var endContentLine = -1;
|
||||
for (int i = Math.Min(endLine, oneSide.Count - 1); i >= startLine; i--)
|
||||
{
|
||||
var line = oneSide[i];
|
||||
if (line.Type != Models.TextDiffLineType.None)
|
||||
{
|
||||
endContentLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endContentLine < 0)
|
||||
return;
|
||||
|
||||
var firstContent = oneSide[firstContentLine];
|
||||
var endContent = oneSide[endContentLine];
|
||||
startLine = combined.Lines.IndexOf(firstContent);
|
||||
endLine = combined.Lines.IndexOf(endContent);
|
||||
}
|
||||
|
||||
private void FillEmptyLines()
|
||||
{
|
||||
if (Old.Count < New.Count)
|
||||
{
|
||||
int diff = New.Count - Old.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
Old.Add(new Models.TextDiffLine());
|
||||
}
|
||||
else if (Old.Count > New.Count)
|
||||
{
|
||||
int diff = Old.Count - New.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
New.Add(new Models.TextDiffLine());
|
||||
}
|
||||
}
|
||||
|
||||
private Vector _syncScrollOffset = Vector.Zero;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Threading;
|
||||
@@ -246,15 +247,17 @@ namespace SourceGit.ViewModels
|
||||
_commitMessage = string.Empty;
|
||||
}
|
||||
|
||||
public void SetData(List<Models.Change> changes)
|
||||
public void SetData(List<Models.Change> changes, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!IsChanged(_cached, changes))
|
||||
{
|
||||
// Just force refresh selected changes.
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
HasUnsolvedConflicts = _cached.Find(x => x.IsConflicted) != null;
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
HasUnsolvedConflicts = _cached.Find(x => x.IsConflicted) != null;
|
||||
UpdateDetail();
|
||||
UpdateInProgressState();
|
||||
});
|
||||
@@ -308,6 +311,9 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
_isLoadingData = true;
|
||||
HasUnsolvedConflicts = hasConflict;
|
||||
VisibleUnstaged = visibleUnstaged;
|
||||
@@ -417,7 +423,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public async Task SaveChangesToPatchAsync(List<Models.Change> changes, bool isUnstaged, string saveTo)
|
||||
{
|
||||
var succ = await Commands.SaveChangesAsPatch.ProcessLocalChangesAsync(_repo.FullPath, _selectedUnstaged, isUnstaged, saveTo);
|
||||
var succ = await Commands.SaveChangesAsPatch.ProcessLocalChangesAsync(_repo.FullPath, changes, isUnstaged, saveTo);
|
||||
if (succ)
|
||||
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
|
||||
}
|
||||
@@ -606,6 +612,13 @@ namespace SourceGit.ViewModels
|
||||
CommitMessage = tmpl.Apply(_repo.CurrentBranch, _staged);
|
||||
}
|
||||
|
||||
public async Task ClearCommitMessageHistoryAsync()
|
||||
{
|
||||
var sure = await App.AskConfirmAsync(App.Text("WorkingCopy.ClearCommitHistories.Confirm"));
|
||||
if (sure)
|
||||
_repo.Settings.CommitMessages.Clear();
|
||||
}
|
||||
|
||||
public async Task CommitAsync(bool autoStage, bool autoPush, Models.CommitCheckPassed checkPassed = Models.CommitCheckPassed.None)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_commitMessage))
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding RemoteBranches}"
|
||||
IsTextSearchEnabled="True"
|
||||
SelectedItem="{Binding SelectedTrackingBranch, Mode=TwoWay}"
|
||||
IsVisible="{Binding SetTrackingBranch, Mode=OneWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
@@ -128,7 +128,8 @@
|
||||
EnableCompactFolders="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableCompactFoldersInChangesTree}"
|
||||
Changes="{Binding VisibleChanges}"
|
||||
SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}"
|
||||
ContextRequested="OnChangeContextRequested"/>
|
||||
ContextRequested="OnChangeContextRequested"
|
||||
KeyDown="OnChangeCollectionViewKeyDown"/>
|
||||
</Border>
|
||||
|
||||
<!-- Loading Status Icon -->
|
||||
|
||||
@@ -64,10 +64,10 @@ namespace SourceGit.Views
|
||||
copyFullPath.Header = App.Text("CopyFullPath");
|
||||
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||
copyFullPath.Tag = OperatingSystem.IsMacOS() ? "⌘+⇧+C" : "Ctrl+Shift+C";
|
||||
copyFullPath.Click += async (_, e) =>
|
||||
copyFullPath.Click += async (_, ev) =>
|
||||
{
|
||||
await App.CopyTextAsync(Native.OS.GetAbsPath(repo, change.Path));
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(copyFullPath);
|
||||
menu.Open(view);
|
||||
@@ -83,5 +83,25 @@ namespace SourceGit.Views
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnChangeCollectionViewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.BranchCompare vm)
|
||||
return;
|
||||
|
||||
if (sender is not ChangeCollectionView { SelectedChanges: { Count: 1 } selectedChanges })
|
||||
return;
|
||||
|
||||
var change = selectedChanges[0];
|
||||
if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control) && e.Key == Key.C)
|
||||
{
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
await App.CopyTextAsync(vm.GetAbsPath(change.Path));
|
||||
else
|
||||
await App.CopyTextAsync(change.Path);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
IsChecked="{Binding IsExpanded, Mode=OneWay}"
|
||||
IsVisible="{Binding !IsBranch}"/>
|
||||
|
||||
<!-- Content Area (allows double-click) -->
|
||||
<!-- Content Area (allows double-clicking) -->
|
||||
<Grid Grid.Column="1"
|
||||
Background="Transparent"
|
||||
ColumnDefinitions="18,*,Auto,Auto"
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace SourceGit.Views
|
||||
{
|
||||
protected override Type StyleKeyOverride => typeof(ListBox);
|
||||
|
||||
protected override async void OnKeyDown(KeyEventArgs e)
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
if (SelectedItems is [ViewModels.ChangeTreeNode node])
|
||||
{
|
||||
@@ -43,36 +43,6 @@ namespace SourceGit.Views
|
||||
this.FindAncestorOfType<ChangeCollectionView>()?.ToggleNodeIsExpanded(node);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.C &&
|
||||
e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
|
||||
{
|
||||
var path = node.FullPath;
|
||||
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
{
|
||||
do
|
||||
{
|
||||
var repoView = this.FindAncestorOfType<Repository>();
|
||||
if (repoView is { DataContext: ViewModels.Repository repo })
|
||||
{
|
||||
path = Native.OS.GetAbsPath(repo.FullPath, path);
|
||||
break;
|
||||
}
|
||||
|
||||
var branchCompareView = this.FindAncestorOfType<BranchCompare>();
|
||||
if (branchCompareView is { DataContext: ViewModels.BranchCompare branchCompare })
|
||||
{
|
||||
path = branchCompare.GetAbsPath(path);
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: if there is another window uses ChangeCollectionView, add it here!
|
||||
} while (false);
|
||||
}
|
||||
|
||||
await App.CopyTextAsync(path);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!e.Handled && e.Key != Key.Space && e.Key != Key.Enter)
|
||||
@@ -110,7 +80,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> EnableCompactFoldersProperty =
|
||||
AvaloniaProperty.Register<ChangeCollectionView, bool>(nameof(EnableCompactFolders), false);
|
||||
AvaloniaProperty.Register<ChangeCollectionView, bool>(nameof(EnableCompactFolders));
|
||||
|
||||
public bool EnableCompactFolders
|
||||
{
|
||||
|
||||
@@ -30,12 +30,7 @@ namespace SourceGit.Views
|
||||
public void BeginMoveWindow(object _, PointerPressedEventArgs e)
|
||||
{
|
||||
if (e.ClickCount == 1)
|
||||
{
|
||||
if (OperatingSystem.IsMacOS())
|
||||
e.Pointer.Capture(this);
|
||||
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.CommitChanges"
|
||||
x:DataType="vm:CommitDetail">
|
||||
@@ -51,7 +50,8 @@
|
||||
EnableCompactFolders="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableCompactFoldersInChangesTree}"
|
||||
Changes="{Binding VisibleChanges}"
|
||||
SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}"
|
||||
ContextRequested="OnChangeContextRequested"/>
|
||||
ContextRequested="OnChangeContextRequested"
|
||||
KeyDown="OnChangeCollectionViewKeyDown"/>
|
||||
</Border>
|
||||
|
||||
<!-- Summary -->
|
||||
@@ -59,7 +59,7 @@
|
||||
<TextBlock Margin="4,0,0,0"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Center">
|
||||
<Run Text="{Binding Changes, Converter={x:Static c:ListConverters.Count}, Mode=OneWay}" FontWeight="Bold"/>
|
||||
<Run Text="{Binding Changes.Count, Mode=OneWay}" FontWeight="Bold"/>
|
||||
<Run Text="{DynamicResource Text.CommitDetail.Changes.Count}"/>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace SourceGit.Views
|
||||
@@ -14,7 +17,7 @@ namespace SourceGit.Views
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
if (sender is not ChangeCollectionView view || DataContext is not ViewModels.CommitDetail vm)
|
||||
if (sender is not ChangeCollectionView view)
|
||||
return;
|
||||
|
||||
var detailView = this.FindAncestorOfType<CommitDetail>();
|
||||
@@ -36,5 +39,26 @@ namespace SourceGit.Views
|
||||
menu.Open(view);
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnChangeCollectionViewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.CommitDetail vm)
|
||||
return;
|
||||
|
||||
if (sender is not ChangeCollectionView { SelectedChanges: { Count: 1 } selectedChanges })
|
||||
return;
|
||||
|
||||
var change = selectedChanges[0];
|
||||
if (e.Key == Key.C &&
|
||||
e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
|
||||
{
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
await App.CopyTextAsync(vm.GetAbsPath(change.Path));
|
||||
else
|
||||
await App.CopyTextAsync(change.Path);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace SourceGit.Views
|
||||
|
||||
public ContextMenu CreateChangeContextMenuByFolder(ChangeTreeNode node, List<Models.Change> changes)
|
||||
{
|
||||
if (DataContext is not ViewModels.CommitDetail { Repository: ViewModels.Repository repo, Commit: Models.Commit commit } vm)
|
||||
if (DataContext is not ViewModels.CommitDetail { Repository: { } repo, Commit: { } commit } vm)
|
||||
return null;
|
||||
|
||||
var fullPath = Native.OS.GetAbsPath(repo.FullPath, node.FullPath);
|
||||
@@ -98,7 +98,7 @@ namespace SourceGit.Views
|
||||
|
||||
public ContextMenu CreateChangeContextMenu(Models.Change change)
|
||||
{
|
||||
if (DataContext is not ViewModels.CommitDetail { Repository: ViewModels.Repository repo, Commit: Models.Commit commit } vm)
|
||||
if (DataContext is not ViewModels.CommitDetail { Repository: { } repo, Commit: { } commit } vm)
|
||||
return null;
|
||||
|
||||
var openWithMerger = new MenuItem();
|
||||
@@ -111,6 +111,16 @@ namespace SourceGit.Views
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var openWith = new MenuItem();
|
||||
openWith.Header = App.Text("OpenWith");
|
||||
openWith.Icon = App.CreateMenuIcon("Icons.OpenWith");
|
||||
openWith.IsEnabled = change.Index != Models.ChangeState.Deleted;
|
||||
openWith.Click += async (_, ev) =>
|
||||
{
|
||||
await vm.OpenRevisionFileWithDefaultEditorAsync(change.Path);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var fullPath = Native.OS.GetAbsPath(repo.FullPath, change.Path);
|
||||
var explore = new MenuItem();
|
||||
explore.Header = App.Text("RevealFile");
|
||||
@@ -167,6 +177,7 @@ namespace SourceGit.Views
|
||||
|
||||
var menu = new ContextMenu();
|
||||
menu.Items.Add(openWithMerger);
|
||||
menu.Items.Add(openWith);
|
||||
menu.Items.Add(explore);
|
||||
menu.Items.Add(new MenuItem { Header = "-" });
|
||||
menu.Items.Add(history);
|
||||
@@ -293,24 +304,30 @@ namespace SourceGit.Views
|
||||
|
||||
private async void OnCommitListKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.CommitDetail detail &&
|
||||
sender is ListBox { SelectedItem: Models.Change change } &&
|
||||
if (DataContext is not ViewModels.CommitDetail vm)
|
||||
return;
|
||||
|
||||
if (sender is not ListBox { SelectedItem: Models.Change change })
|
||||
return;
|
||||
|
||||
if (e.Key == Key.C &&
|
||||
e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
|
||||
{
|
||||
if (e.Key == Key.C)
|
||||
{
|
||||
var path = change.Path;
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
path = detail.GetAbsPath(path);
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
await App.CopyTextAsync(vm.GetAbsPath(change.Path));
|
||||
else
|
||||
await App.CopyTextAsync(change.Path);
|
||||
|
||||
await App.CopyTextAsync(path);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.D && e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
{
|
||||
detail.OpenChangeInMergeTool(change);
|
||||
e.Handled = true;
|
||||
}
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Key == Key.D &&
|
||||
e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control) &&
|
||||
e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
{
|
||||
vm.OpenChangeInMergeTool(change);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +344,7 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.CommitDetail detail && sender is Grid { DataContext: Models.Change change } grid)
|
||||
if (sender is Grid { DataContext: Models.Change change } grid)
|
||||
CreateChangeContextMenu(change)?.Open(grid);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
@@ -179,6 +179,7 @@ namespace SourceGit.Views
|
||||
{
|
||||
var repo = vm.Repository;
|
||||
var menu = new ContextMenu();
|
||||
menu.MaxWidth = 480;
|
||||
|
||||
var gitTemplate = await new Commands.Config(repo.FullPath).GetAsync("commit.template");
|
||||
var templateCount = repo.Settings.CommitTemplates.Count;
|
||||
@@ -199,10 +200,10 @@ namespace SourceGit.Views
|
||||
var item = new MenuItem();
|
||||
item.Header = App.Text("WorkingCopy.UseCommitTemplate", template.Name);
|
||||
item.Icon = App.CreateMenuIcon("Icons.Code");
|
||||
item.Click += (_, e) =>
|
||||
item.Click += (_, ev) =>
|
||||
{
|
||||
vm.ApplyCommitMessageTemplate(template);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(item);
|
||||
}
|
||||
@@ -224,11 +225,11 @@ namespace SourceGit.Views
|
||||
var gitTemplateItem = new MenuItem();
|
||||
gitTemplateItem.Header = App.Text("WorkingCopy.UseCommitTemplate", friendlyName);
|
||||
gitTemplateItem.Icon = App.CreateMenuIcon("Icons.Code");
|
||||
gitTemplateItem.Click += (_, e) =>
|
||||
gitTemplateItem.Click += (_, ev) =>
|
||||
{
|
||||
if (File.Exists(gitTemplate))
|
||||
vm.CommitMessage = File.ReadAllText(gitTemplate);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(gitTemplateItem);
|
||||
}
|
||||
@@ -261,14 +262,27 @@ namespace SourceGit.Views
|
||||
var item = new MenuItem();
|
||||
item.Header = header;
|
||||
item.Icon = App.CreateMenuIcon("Icons.Histories");
|
||||
item.Click += (_, e) =>
|
||||
item.Click += (_, ev) =>
|
||||
{
|
||||
vm.CommitMessage = dup;
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(item);
|
||||
}
|
||||
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
|
||||
var clearHistoryItem = new MenuItem();
|
||||
clearHistoryItem.Header = App.Text("WorkingCopy.ClearCommitHistories");
|
||||
clearHistoryItem.Icon = App.CreateMenuIcon("Icons.Clear");
|
||||
clearHistoryItem.Click += async (_, ev) =>
|
||||
{
|
||||
await vm.ClearCommitMessageHistoryAsync();
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(clearHistoryItem);
|
||||
}
|
||||
|
||||
menu.Placement = PlacementMode.TopEdgeAlignedLeft;
|
||||
@@ -309,10 +323,10 @@ namespace SourceGit.Views
|
||||
var dup = service;
|
||||
var item = new MenuItem();
|
||||
item.Header = service.Name;
|
||||
item.Click += async (_, e) =>
|
||||
item.Click += async (_, ev) =>
|
||||
{
|
||||
await App.ShowDialog(new ViewModels.AIAssistant(repo, dup, vm.Staged, t => vm.CommitMessage = t));
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(item);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
Click="OnGotoFirstChange"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
HotKey="{OnPlatform Ctrl+Alt+Home, macOS=⌘+Alt+Home}">
|
||||
<ToolTip.Tip>
|
||||
<TextBlock>
|
||||
@@ -45,12 +46,6 @@
|
||||
<Run Text="{OnPlatform Ctrl+Alt+Home, macOS=⌘+⌥+Home}" FontSize="11" Foreground="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForeground}"/>
|
||||
</TextBlock>
|
||||
</ToolTip.Tip>
|
||||
<Button.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="IsTextDiff"/>
|
||||
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseBlockNavigationInDiffView" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</Button.IsVisible>
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Top}"/>
|
||||
</Button>
|
||||
|
||||
@@ -69,16 +64,13 @@
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
|
||||
</Button>
|
||||
|
||||
<Border>
|
||||
<Border.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="IsTextDiff"/>
|
||||
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseBlockNavigationInDiffView" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</Border.IsVisible>
|
||||
|
||||
<TextBlock x:Name="BlockNavigationIndicator" Classes="primary" Margin="0,0,0,0" FontSize="11" Text="-/-"/>
|
||||
</Border>
|
||||
<ContentControl Content="{Binding Content, Mode=OneWay}" IsVisible="{Binding IsTextDiff}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="vm:TextDiffContext">
|
||||
<TextBlock Classes="primary" Margin="0,0,0,0" FontSize="11" Text="{Binding BlockNavigation.Indicator}"/>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
@@ -98,6 +90,7 @@
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
Click="OnGotoLastChange"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
HotKey="{OnPlatform Ctrl+Alt+End, macOS=⌘+Alt+End}">
|
||||
<ToolTip.Tip>
|
||||
<TextBlock>
|
||||
@@ -106,31 +99,15 @@
|
||||
<Run Text="{OnPlatform Ctrl+Alt+End, macOS=⌘+⌥+End}" FontSize="11" Foreground="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForeground}"/>
|
||||
</TextBlock>
|
||||
</ToolTip.Tip>
|
||||
<Button.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="IsTextDiff"/>
|
||||
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseBlockNavigationInDiffView" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</Button.IsVisible>
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Bottom}"/>
|
||||
</Button>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="28"
|
||||
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=TwoWay}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.UseBlockNavigation}">
|
||||
<Path Width="13" Height="13" Data="{StaticResource Icons.CodeBlock}" Margin="0,3,0,0"/>
|
||||
</ToggleButton>
|
||||
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
Command="{Binding IncrUnified}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
IsEnabled="{Binding ShowEntireFile, Mode=OneWay, Converter={x:Static BoolConverters.Not}}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
|
||||
<Button.IsEnabled>
|
||||
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
|
||||
</Button.IsEnabled>
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Incr}"/>
|
||||
</Button>
|
||||
|
||||
@@ -142,7 +119,7 @@
|
||||
<Button.IsEnabled>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="UnifiedLines" Mode="OneWay" Converter="{x:Static c:IntConverters.IsGreaterThanFour}"/>
|
||||
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseFullTextDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
|
||||
<Binding Path="ShowEntireFile" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
|
||||
</MultiBinding>
|
||||
</Button.IsEnabled>
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/>
|
||||
@@ -150,8 +127,7 @@
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="28"
|
||||
Click="OnUseFullTextDiffClicked"
|
||||
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
|
||||
IsChecked="{Binding ShowEntireFile, Mode=TwoWay}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.All}">
|
||||
<Path Width="13" Height="13" Data="{StaticResource Icons.Lines.All}" Margin="0,3,0,0"/>
|
||||
@@ -172,8 +148,8 @@
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.ToggleWordWrap}">
|
||||
<ToggleButton.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="IsTextDiff"/>
|
||||
<Binding Source="{x:Static vm:Preferences.Instance}" Path="UseSideBySideDiff" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
|
||||
<Binding Path="IsTextDiff" Mode="OneWay"/>
|
||||
<Binding Path="UseSideBySide" Mode="OneWay" Converter="{x:Static BoolConverters.Not}"/>
|
||||
</MultiBinding>
|
||||
</ToggleButton.IsVisible>
|
||||
|
||||
@@ -197,7 +173,7 @@
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="28" Height="18"
|
||||
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSideBySideDiff, Mode=TwoWay}"
|
||||
IsChecked="{Binding UseSideBySide, Mode=TwoWay}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.SideBySide}">
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Layout}" Margin="0,2,0,0"/>
|
||||
@@ -361,10 +337,8 @@
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Text Diff -->
|
||||
<DataTemplate DataType="m:TextDiff">
|
||||
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
|
||||
UseBlockNavigation="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseBlockNavigationInDiffView, Mode=OneWay}"
|
||||
BlockNavigationChanged="OnBlockNavigationChanged"/>
|
||||
<DataTemplate DataType="vm:TextDiffContext">
|
||||
<v:TextDiffView SelectedChunk="{Binding SelectedChunk, Mode=OneWay}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Empty or only EOL changes -->
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
@@ -12,50 +11,35 @@ namespace SourceGit.Views
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
if (DataContext is ViewModels.DiffContext vm)
|
||||
vm.CheckSettings();
|
||||
}
|
||||
|
||||
private void OnGotoFirstChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
this.FindDescendantOfType<TextDiffView>()?.GotoFirstChange();
|
||||
this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoFirstChange();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnGotoPrevChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
this.FindDescendantOfType<TextDiffView>()?.GotoPrevChange();
|
||||
this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoPrevChange();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnGotoNextChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
this.FindDescendantOfType<TextDiffView>()?.GotoNextChange();
|
||||
this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoNextChange();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnGotoLastChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
this.FindDescendantOfType<TextDiffView>()?.GotoLastChange();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnBlockNavigationChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TextDiffView textDiff)
|
||||
BlockNavigationIndicator.Text = textDiff.BlockNavigation?.Indicator ?? string.Empty;
|
||||
}
|
||||
|
||||
private void OnUseFullTextDiffClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var textDiffView = this.FindDescendantOfType<TextDiffView>();
|
||||
|
||||
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();
|
||||
this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoLastChange();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +188,9 @@ namespace SourceGit.Views
|
||||
SetCurrentValue(IsScrollToTopVisibleProperty, startY >= rowHeight);
|
||||
|
||||
var clipWidth = dataGrid.Columns[0].ActualWidth - 4;
|
||||
if (_lastGraphStartY != startY ||
|
||||
_lastGraphClipWidth != clipWidth ||
|
||||
_lastGraphRowHeight != rowHeight)
|
||||
if (Math.Abs(_lastGraphStartY - startY) > 0.01 ||
|
||||
Math.Abs(_lastGraphClipWidth - clipWidth) > 0.01 ||
|
||||
Math.Abs(_lastGraphRowHeight - rowHeight) > 0.01)
|
||||
{
|
||||
_lastGraphStartY = startY;
|
||||
_lastGraphClipWidth = clipWidth;
|
||||
@@ -292,8 +292,6 @@ namespace SourceGit.Views
|
||||
repo.ShowPopup(new ViewModels.CreateTag(repo, commit));
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -775,7 +773,7 @@ namespace SourceGit.Views
|
||||
{
|
||||
var folder = selected[0];
|
||||
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder.Path.ToString();
|
||||
await repo.SaveCommitAsPatchAsync(commit, folderPath, 0);
|
||||
await repo.SaveCommitAsPatchAsync(commit, folderPath);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
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:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
|
||||
@@ -169,9 +169,6 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnButtonActionClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.InteractiveRebase vm)
|
||||
return;
|
||||
|
||||
if (sender is not Button { DataContext: ViewModels.InteractiveRebaseItem item } button)
|
||||
return;
|
||||
|
||||
|
||||
@@ -328,12 +328,12 @@ namespace SourceGit.Views
|
||||
var item = new MenuItem();
|
||||
item.Header = workspace.Name;
|
||||
item.Icon = icon;
|
||||
item.Click += (_, e) =>
|
||||
item.Click += (_, ev) =>
|
||||
{
|
||||
if (!workspace.IsActive)
|
||||
launcher.SwitchWorkspace(workspace);
|
||||
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
menu.Items.Add(item);
|
||||
@@ -343,10 +343,10 @@ namespace SourceGit.Views
|
||||
|
||||
var configure = new MenuItem();
|
||||
configure.Header = App.Text("Workspace.Configure");
|
||||
configure.Click += async (_, e) =>
|
||||
configure.Click += async (_, ev) =>
|
||||
{
|
||||
await App.ShowDialog(new ViewModels.ConfigureWorkspace());
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(configure);
|
||||
menu.Open(btn);
|
||||
|
||||
@@ -261,28 +261,28 @@ namespace SourceGit.Views
|
||||
var close = new MenuItem();
|
||||
close.Header = App.Text("PageTabBar.Tab.Close");
|
||||
close.Tag = OperatingSystem.IsMacOS() ? "⌘+W" : "Ctrl+W";
|
||||
close.Click += (_, e) =>
|
||||
close.Click += (_, ev) =>
|
||||
{
|
||||
vm.CloseTab(page);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(close);
|
||||
|
||||
var closeOthers = new MenuItem();
|
||||
closeOthers.Header = App.Text("PageTabBar.Tab.CloseOther");
|
||||
closeOthers.Click += (_, e) =>
|
||||
closeOthers.Click += (_, ev) =>
|
||||
{
|
||||
vm.CloseOtherTabs();
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(closeOthers);
|
||||
|
||||
var closeRight = new MenuItem();
|
||||
closeRight.Header = App.Text("PageTabBar.Tab.CloseRight");
|
||||
closeRight.Click += (_, e) =>
|
||||
closeRight.Click += (_, ev) =>
|
||||
{
|
||||
vm.CloseRightTabs();
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(closeRight);
|
||||
|
||||
@@ -302,10 +302,10 @@ namespace SourceGit.Views
|
||||
var dupIdx = i;
|
||||
var setter = new MenuItem();
|
||||
setter.Header = icon;
|
||||
setter.Click += (_, e) =>
|
||||
setter.Click += (_, ev) =>
|
||||
{
|
||||
page.Node.Bookmark = dupIdx;
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
bookmark.Items.Add(setter);
|
||||
}
|
||||
@@ -315,10 +315,10 @@ namespace SourceGit.Views
|
||||
var copyPath = new MenuItem();
|
||||
copyPath.Header = App.Text("PageTabBar.Tab.CopyPath");
|
||||
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||
copyPath.Click += async (_, e) =>
|
||||
copyPath.Click += async (_, ev) =>
|
||||
{
|
||||
await page.CopyPathAsync();
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
menu.Items.Add(copyPath);
|
||||
@@ -429,7 +429,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
|
||||
private bool _pressedTab = false;
|
||||
private Point _pressedTabPosition = new Point();
|
||||
private Point _pressedTabPosition = new();
|
||||
private bool _startDragTab = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<TabItem.Header>
|
||||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preferences.General}"/>
|
||||
</TabItem.Header>
|
||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
|
||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preferences.General.Locale}"
|
||||
HorizontalAlignment="Right"
|
||||
@@ -133,21 +133,31 @@
|
||||
</Grid>
|
||||
|
||||
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.General.ShowChangesPageByDefault}"
|
||||
IsChecked="{Binding ShowLocalChangesByDefault, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="6" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.General.ShowAuthorTime}"
|
||||
IsChecked="{Binding ShowAuthorTimeInGraph, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="6" Grid.Column="1"
|
||||
<CheckBox Grid.Row="7" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.General.ShowTagsInGraph}"
|
||||
IsChecked="{Binding ShowTagsInGraph, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="7" Grid.Column="1"
|
||||
<CheckBox Grid.Row="8" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.General.ShowChildren}"
|
||||
IsChecked="{Binding ShowChildren, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="8" Grid.Column="1"
|
||||
<CheckBox Grid.Row="9" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.General.EnableCompactFolders}"
|
||||
IsChecked="{Binding EnableCompactFoldersInChangesTree, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="10" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.General.Check4UpdatesOnStartup}"
|
||||
IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}"
|
||||
@@ -159,7 +169,7 @@
|
||||
<TabItem.Header>
|
||||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preferences.Appearance}"/>
|
||||
</TabItem.Header>
|
||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
|
||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preferences.Appearance.Theme}"
|
||||
HorizontalAlignment="Right"
|
||||
@@ -266,11 +276,6 @@
|
||||
IsChecked="{Binding UseFixedTabWidth, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="8" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.Appearance.EnableCompactFolders}"
|
||||
IsChecked="{Binding EnableCompactFoldersInChangesTree, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="9" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.Appearance.UseNativeWindowFrame}"
|
||||
IsChecked="{Binding UseSystemWindowFrame, Mode=OneTime}"
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Pull.Branch}"/>
|
||||
<ComboBox Grid.Row="1" Grid.Column="1"
|
||||
x:Name="RemoteBranchesComboBox"
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding RemoteBranches}"
|
||||
@@ -60,12 +61,6 @@
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
|
||||
<ComboBox.ItemContainerTheme>
|
||||
<ControlTheme TargetType="ComboBoxItem" x:DataType="m:Branch" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
|
||||
<Setter Property="TextSearch.Text" Value="{Binding Name}"/>
|
||||
</ControlTheme>
|
||||
</ComboBox.ItemContainerTheme>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
@@ -7,6 +9,7 @@ namespace SourceGit.Views
|
||||
public Pull()
|
||||
{
|
||||
InitializeComponent();
|
||||
TextSearch.SetTextBinding(RemoteBranchesComboBox, new Binding("Name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Push.Local}"/>
|
||||
<ComboBox Grid.Row="0" Grid.Column="1"
|
||||
x:Name="LocalBranchesComboBox"
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding LocalBranches}"
|
||||
@@ -32,12 +33,6 @@
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
|
||||
<ComboBox.ItemContainerTheme>
|
||||
<ControlTheme TargetType="ComboBoxItem" x:DataType="m:Branch" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
|
||||
<Setter Property="TextSearch.Text" Value="{Binding Name}"/>
|
||||
</ControlTheme>
|
||||
</ComboBox.ItemContainerTheme>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
@@ -64,6 +59,7 @@
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Push.To}"/>
|
||||
<ComboBox Grid.Row="2" Grid.Column="1"
|
||||
x:Name="RemoteBranchesComboBox"
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding RemoteBranches}"
|
||||
@@ -85,12 +81,6 @@
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
|
||||
<ComboBox.ItemContainerTheme>
|
||||
<ControlTheme TargetType="ComboBoxItem" x:DataType="m:Branch" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
|
||||
<Setter Property="TextSearch.Text" Value="{Binding Name}"/>
|
||||
</ControlTheme>
|
||||
</ComboBox.ItemContainerTheme>
|
||||
</ComboBox>
|
||||
|
||||
<CheckBox Grid.Row="3" Grid.Column="1"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
@@ -7,6 +9,8 @@ namespace SourceGit.Views
|
||||
public Push()
|
||||
{
|
||||
InitializeComponent();
|
||||
TextSearch.SetTextBinding(LocalBranchesComboBox, new Binding("Name"));
|
||||
TextSearch.SetTextBinding(RemoteBranchesComboBox, new Binding("Name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,10 +229,10 @@ namespace SourceGit.Views
|
||||
var copy = new MenuItem();
|
||||
copy.Header = App.Text("Worktree.CopyPath");
|
||||
copy.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||
copy.Click += async (_, e) =>
|
||||
copy.Click += async (_, ev) =>
|
||||
{
|
||||
await App.CopyTextAsync(worktree.FullPath);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
menu.Items.Add(copy);
|
||||
@@ -459,10 +459,10 @@ namespace SourceGit.Views
|
||||
reflog.Tag = "--reflog";
|
||||
if (repo.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.Reflog))
|
||||
reflog.Icon = App.CreateMenuIcon("Icons.Check");
|
||||
reflog.Click += (_, e) =>
|
||||
reflog.Click += (_, ev) =>
|
||||
{
|
||||
repo.ToggleHistoryShowFlag(Models.HistoryShowFlags.Reflog);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var firstParentOnly = new MenuItem();
|
||||
@@ -470,10 +470,10 @@ namespace SourceGit.Views
|
||||
firstParentOnly.Tag = "--first-parent";
|
||||
if (repo.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.FirstParentOnly))
|
||||
firstParentOnly.Icon = App.CreateMenuIcon("Icons.Check");
|
||||
firstParentOnly.Click += (_, e) =>
|
||||
firstParentOnly.Click += (_, ev) =>
|
||||
{
|
||||
repo.ToggleHistoryShowFlag(Models.HistoryShowFlags.FirstParentOnly);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var simplifyByDecoration = new MenuItem();
|
||||
@@ -481,10 +481,10 @@ namespace SourceGit.Views
|
||||
simplifyByDecoration.Tag = "--simplify-by-decoration";
|
||||
if (repo.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.SimplifyByDecoration))
|
||||
simplifyByDecoration.Icon = App.CreateMenuIcon("Icons.Check");
|
||||
simplifyByDecoration.Click += (_, e) =>
|
||||
simplifyByDecoration.Click += (_, ev) =>
|
||||
{
|
||||
repo.ToggleHistoryShowFlag(Models.HistoryShowFlags.SimplifyByDecoration);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var order = new MenuItem();
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace SourceGit.Views
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OpenWithExternalTools(object sender, RoutedEventArgs e)
|
||||
private void OpenWithExternalTools(object sender, RoutedEventArgs ev)
|
||||
{
|
||||
if (sender is Button button && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
@@ -100,7 +100,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
|
||||
menu.Open(button);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenGitFlowMenu(object sender, RoutedEventArgs e)
|
||||
private void OpenGitFlowMenu(object sender, RoutedEventArgs ev)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo && sender is Control control)
|
||||
{
|
||||
@@ -248,10 +248,10 @@ namespace SourceGit.Views
|
||||
menu.Open(control);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
}
|
||||
|
||||
private void OpenGitLFSMenu(object sender, RoutedEventArgs e)
|
||||
private void OpenGitLFSMenu(object sender, RoutedEventArgs ev)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo && sender is Control control)
|
||||
{
|
||||
@@ -387,7 +387,7 @@ namespace SourceGit.Views
|
||||
menu.Open(control);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
}
|
||||
|
||||
private async void StartBisect(object sender, RoutedEventArgs e)
|
||||
@@ -415,7 +415,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenCustomActionMenu(object sender, RoutedEventArgs e)
|
||||
private void OpenCustomActionMenu(object sender, RoutedEventArgs ev)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo && sender is Control control)
|
||||
{
|
||||
@@ -448,7 +448,7 @@ namespace SourceGit.Views
|
||||
menu.Open(control);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
}
|
||||
|
||||
private async void OpenGitLogs(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -100,7 +100,8 @@
|
||||
EnableCompactFolders="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableCompactFoldersInChangesTree}"
|
||||
Changes="{Binding VisibleChanges}"
|
||||
SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}"
|
||||
ContextRequested="OnChangeContextRequested"/>
|
||||
ContextRequested="OnChangeContextRequested"
|
||||
KeyDown="OnChangeCollectionViewKeyDown"/>
|
||||
</Border>
|
||||
|
||||
<!-- Loading Status Icon -->
|
||||
|
||||
@@ -20,9 +20,8 @@ namespace SourceGit.Views
|
||||
if (DataContext is ViewModels.RevisionCompare { SelectedChanges: { Count: 1 } selected } vm &&
|
||||
sender is ChangeCollectionView view)
|
||||
{
|
||||
var repo = vm.RepositoryPath;
|
||||
var change = selected[0];
|
||||
var changeFullPath = Native.OS.GetAbsPath(repo, change.Path);
|
||||
var changeFullPath = vm.GetAbsPath(change.Path);
|
||||
var menu = new ContextMenu();
|
||||
|
||||
var openWithMerger = new MenuItem();
|
||||
@@ -65,13 +64,13 @@ namespace SourceGit.Views
|
||||
copyFullPath.Header = App.Text("CopyFullPath");
|
||||
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||
copyFullPath.Tag = OperatingSystem.IsMacOS() ? "⌘+⇧+C" : "Ctrl+Shift+C";
|
||||
copyFullPath.Click += async (_, e) =>
|
||||
copyFullPath.Click += async (_, ev) =>
|
||||
{
|
||||
await App.CopyTextAsync(changeFullPath);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(copyFullPath);
|
||||
menu?.Open(view);
|
||||
menu.Open(view);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
@@ -105,5 +104,25 @@ namespace SourceGit.Views
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnChangeCollectionViewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.RevisionCompare vm)
|
||||
return;
|
||||
|
||||
if (sender is not ChangeCollectionView { SelectedChanges: { Count: 1 } selectedChanges })
|
||||
return;
|
||||
|
||||
var change = selectedChanges[0];
|
||||
if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control) && e.Key == Key.C)
|
||||
{
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
await App.CopyTextAsync(vm.GetAbsPath(change.Path));
|
||||
else
|
||||
await App.CopyTextAsync(change.Path);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
@@ -24,7 +25,8 @@ namespace SourceGit.Views
|
||||
DataContext is ViewModels.RevisionFileTreeNode { IsFolder: true } node)
|
||||
{
|
||||
var tree = this.FindAncestorOfType<RevisionFileTreeView>();
|
||||
await tree?.ToggleNodeIsExpandedAsync(node);
|
||||
if (tree != null)
|
||||
await tree.ToggleNodeIsExpandedAsync(node);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
@@ -117,7 +119,8 @@ namespace SourceGit.Views
|
||||
(node.IsExpanded && e.Key == Key.Left) || (!node.IsExpanded && e.Key == Key.Right))
|
||||
{
|
||||
var tree = this.FindAncestorOfType<RevisionFileTreeView>();
|
||||
await tree?.ToggleNodeIsExpandedAsync(node);
|
||||
if (tree != null)
|
||||
await tree.ToggleNodeIsExpandedAsync(node);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.C &&
|
||||
@@ -330,7 +333,7 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnTreeNodeContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.CommitDetail { Repository: ViewModels.Repository repo, Commit: Models.Commit commit } vm &&
|
||||
if (DataContext is ViewModels.CommitDetail { Repository: { } repo, Commit: { } commit } vm &&
|
||||
sender is Grid { DataContext: ViewModels.RevisionFileTreeNode { Backend: { } obj } } grid)
|
||||
{
|
||||
var menu = obj.Type switch
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.SetUpstream.Upstream}"/>
|
||||
<ComboBox Grid.Row="1" Grid.Column="1"
|
||||
x:Name="RemoteBranchesComboBox"
|
||||
Height="28" Padding="8,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding RemoteBranches}"
|
||||
@@ -40,12 +41,6 @@
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
|
||||
<ComboBox.ItemContainerTheme>
|
||||
<ControlTheme TargetType="ComboBoxItem" x:DataType="m:Branch" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
|
||||
<Setter Property="TextSearch.Text" Value="{Binding Name}"/>
|
||||
</ControlTheme>
|
||||
</ComboBox.ItemContainerTheme>
|
||||
</ComboBox>
|
||||
|
||||
<CheckBox Grid.Row="2" Grid.Column="1"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
@@ -7,6 +9,7 @@ namespace SourceGit.Views
|
||||
public SetUpstream()
|
||||
{
|
||||
InitializeComponent();
|
||||
TextSearch.SetTextBinding(RemoteBranchesComboBox, new Binding("Name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,8 @@
|
||||
EnableCompactFolders="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableCompactFoldersInChangesTree}"
|
||||
Changes="{Binding Changes}"
|
||||
SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}"
|
||||
ContextRequested="OnChangeContextRequested"/>
|
||||
ContextRequested="OnChangeContextRequested"
|
||||
KeyDown="OnChangeCollectionViewKeyDown"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace SourceGit.Views
|
||||
var patch = new MenuItem();
|
||||
patch.Header = App.Text("StashCM.SaveAsPatch");
|
||||
patch.Icon = App.CreateMenuIcon("Icons.Diff");
|
||||
patch.Click += async (_, e) =>
|
||||
patch.Click += async (_, ev) =>
|
||||
{
|
||||
var storageProvider = TopLevel.GetTopLevel(this)?.StorageProvider;
|
||||
if (storageProvider == null)
|
||||
@@ -86,7 +86,7 @@ namespace SourceGit.Views
|
||||
if (storageFile != null)
|
||||
await vm.SaveStashAsPathAsync(stash, storageFile.Path.LocalPath);
|
||||
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var copy = new MenuItem();
|
||||
@@ -126,8 +126,8 @@ namespace SourceGit.Views
|
||||
if (DataContext is ViewModels.StashesPage { SelectedChanges: { Count: 1 } selected } vm &&
|
||||
sender is ChangeCollectionView view)
|
||||
{
|
||||
var repo = vm.RepositoryPath;
|
||||
var change = selected[0];
|
||||
var fullPath = vm.GetAbsPath(change.Path);
|
||||
|
||||
var openWithMerger = new MenuItem();
|
||||
openWithMerger.Header = App.Text("OpenInExternalMergeTool");
|
||||
@@ -139,7 +139,6 @@ namespace SourceGit.Views
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var fullPath = Native.OS.GetAbsPath(repo, change.Path);
|
||||
var explore = new MenuItem();
|
||||
explore.Header = App.Text("RevealFile");
|
||||
explore.Icon = App.CreateMenuIcon("Icons.Explore");
|
||||
@@ -173,10 +172,10 @@ namespace SourceGit.Views
|
||||
copyFullPath.Header = App.Text("CopyFullPath");
|
||||
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||
copyFullPath.Tag = OperatingSystem.IsMacOS() ? "⌘+⇧+C" : "Ctrl+Shift+C";
|
||||
copyFullPath.Click += async (_, e) =>
|
||||
copyFullPath.Click += async (_, ev) =>
|
||||
{
|
||||
await App.CopyTextAsync(fullPath);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var menu = new ContextMenu();
|
||||
@@ -192,5 +191,25 @@ namespace SourceGit.Views
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnChangeCollectionViewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.StashesPage vm)
|
||||
return;
|
||||
|
||||
if (sender is not ChangeCollectionView { SelectedChanges: { Count: 1 } selectedChanges })
|
||||
return;
|
||||
|
||||
var change = selectedChanges[0];
|
||||
if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control) && e.Key == Key.C)
|
||||
{
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
await App.CopyTextAsync(vm.GetAbsPath(change.Path));
|
||||
else
|
||||
await App.CopyTextAsync(change.Path);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,10 +280,10 @@ namespace SourceGit.Views
|
||||
var item = new MenuItem();
|
||||
item.Icon = App.CreateMenuIcon("Icons.Action");
|
||||
item.Header = label;
|
||||
item.Click += async (_, e) =>
|
||||
item.Click += async (_, ev) =>
|
||||
{
|
||||
await repo.ExecCustomActionAsync(dup, tag);
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
custom.Items.Add(item);
|
||||
@@ -340,12 +340,12 @@ namespace SourceGit.Views
|
||||
var deleteMultiple = new MenuItem();
|
||||
deleteMultiple.Header = App.Text("TagCM.DeleteMultiple", selected.Count);
|
||||
deleteMultiple.Icon = App.CreateMenuIcon("Icons.Clear");
|
||||
deleteMultiple.Click += (_, e) =>
|
||||
deleteMultiple.Click += (_, ev) =>
|
||||
{
|
||||
if (repo.CanCreatePopup())
|
||||
repo.ShowPopup(new ViewModels.DeleteMultipleTags(repo, selected));
|
||||
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
var menu = new ContextMenu();
|
||||
|
||||
@@ -2,20 +2,18 @@
|
||||
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:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.TextDiffView"
|
||||
x:Name="ThisControl"
|
||||
x:DataType="vm:TextDiffContext"
|
||||
Background="{DynamicResource Brush.Contents}">
|
||||
<Grid>
|
||||
<ContentControl x:Name="Editor">
|
||||
<ContentControl Content="{Binding}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="m:TextDiff">
|
||||
<DataTemplate DataType="vm:CombinedTextDiff">
|
||||
<Grid ColumnDefinitions="*,1,8">
|
||||
<v:CombinedTextDiffPresenter Grid.Column="0"
|
||||
x:Name="CombinedPresenter"
|
||||
FileName="{Binding File}"
|
||||
Foreground="{DynamicResource Brush.FG1}"
|
||||
LineBrush="{DynamicResource Brush.Border2}"
|
||||
@@ -31,14 +29,14 @@
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableDiffViewWordWrap}"
|
||||
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
|
||||
EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}"
|
||||
SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"
|
||||
BlockNavigation="{Binding #ThisControl.BlockNavigation, Mode=TwoWay}"/>
|
||||
EnableChunkSelection="{Binding EnableChunkOption}"
|
||||
SelectedChunk="{Binding SelectedChunk, Mode=TwoWay}"
|
||||
BlockNavigation="{Binding BlockNavigation, Mode=OneWay}"/>
|
||||
|
||||
<Rectangle Grid.Column="1" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
|
||||
|
||||
<v:TextDiffViewMinimap Grid.Column="2"
|
||||
DisplayRange="{Binding #CombinedPresenter.DisplayRange}"
|
||||
DisplayRange="{Binding DisplayRange, Mode=OneWay}"
|
||||
AddedLineBrush="{DynamicResource Brush.Diff.AddedBG}"
|
||||
DeletedLineBrush="{DynamicResource Brush.Diff.DeletedBG}"/>
|
||||
</Grid>
|
||||
@@ -47,7 +45,6 @@
|
||||
<DataTemplate DataType="vm:TwoSideTextDiff">
|
||||
<Grid ColumnDefinitions="*,1,*,1,12">
|
||||
<v:SingleSideTextDiffPresenter Grid.Column="0"
|
||||
x:Name="LeftSidePresenter"
|
||||
IsOld="True"
|
||||
FileName="{Binding File}"
|
||||
Foreground="{DynamicResource Brush.FG1}"
|
||||
@@ -64,9 +61,9 @@
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="False"
|
||||
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
|
||||
EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}"
|
||||
SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"
|
||||
BlockNavigation="{Binding #ThisControl.BlockNavigation, Mode=TwoWay}"/>
|
||||
EnableChunkSelection="{Binding EnableChunkOption, Mode=OneWay}"
|
||||
SelectedChunk="{Binding SelectedChunk, Mode=TwoWay}"
|
||||
BlockNavigation="{Binding BlockNavigation, Mode=OneWay}"/>
|
||||
|
||||
<Rectangle Grid.Column="1" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
|
||||
|
||||
@@ -87,14 +84,14 @@
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="False"
|
||||
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
|
||||
EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}"
|
||||
SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"
|
||||
BlockNavigation="{Binding #ThisControl.BlockNavigation, Mode=TwoWay}"/>
|
||||
EnableChunkSelection="{Binding EnableChunkOption, Mode=OneWay}"
|
||||
SelectedChunk="{Binding SelectedChunk, Mode=TwoWay}"
|
||||
BlockNavigation="{Binding BlockNavigation, Mode=OneWay}"/>
|
||||
|
||||
<Rectangle Grid.Column="3" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
|
||||
|
||||
<v:TextDiffViewMinimap Grid.Column="4"
|
||||
DisplayRange="{Binding #LeftSidePresenter.DisplayRange}"
|
||||
DisplayRange="{Binding DisplayRange, Mode=OneWay}"
|
||||
AddedLineBrush="{DynamicResource Brush.Diff.AddedBG}"
|
||||
DeletedLineBrush="{DynamicResource Brush.Diff.DeletedBG}"/>
|
||||
</Grid>
|
||||
@@ -103,7 +100,7 @@
|
||||
</ContentControl>
|
||||
|
||||
<StackPanel x:Name="Popup" IsVisible="False" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right" Effect="drop-shadow(0 0 8 #80000000)">
|
||||
<Button Classes="flat" Click="OnStageChunk" HotKey="{OnPlatform Ctrl+S, macOS=⌘+S}" IsVisible="{Binding #ThisControl.IsUnstagedChange}">
|
||||
<Button Classes="flat" Click="OnStageChunk" HotKey="{OnPlatform Ctrl+S, macOS=⌘+S}" IsVisible="{Binding IsUnstaged}">
|
||||
<TextBlock>
|
||||
<Run Text="{DynamicResource Text.Hunk.Stage}"/>
|
||||
<Run Text=" "/>
|
||||
@@ -114,7 +111,7 @@
|
||||
</TextBlock>
|
||||
</Button>
|
||||
|
||||
<Button Classes="flat" Click="OnUnstageChunk" HotKey="{OnPlatform Ctrl+U, macOS=⌘+U}" IsVisible="{Binding #ThisControl.IsUnstagedChange, Converter={x:Static BoolConverters.Not}}">
|
||||
<Button Classes="flat" Click="OnUnstageChunk" HotKey="{OnPlatform Ctrl+U, macOS=⌘+U}" IsVisible="{Binding IsUnstaged, Converter={x:Static BoolConverters.Not}}">
|
||||
<TextBlock>
|
||||
<Run Text="{DynamicResource Text.Hunk.Unstage}"/>
|
||||
<Run Text=" "/>
|
||||
@@ -125,7 +122,7 @@
|
||||
</TextBlock>
|
||||
</Button>
|
||||
|
||||
<Button Classes="flat" Margin="8,0,0,0" HotKey="{OnPlatform Ctrl+D, macOS=⌘+D}" Click="OnDiscardChunk" IsVisible="{Binding #ThisControl.IsUnstagedChange}">
|
||||
<Button Classes="flat" Margin="8,0,0,0" HotKey="{OnPlatform Ctrl+D, macOS=⌘+D}" Click="OnDiscardChunk" IsVisible="{Binding IsUnstaged}">
|
||||
<TextBlock>
|
||||
<Run Text="{DynamicResource Text.Hunk.Discard}"/>
|
||||
<Run Text=" "/>
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
@@ -23,41 +24,6 @@ using AvaloniaEdit.Utils;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class TextDiffViewChunk
|
||||
{
|
||||
public double Y { get; set; } = 0.0;
|
||||
public double Height { get; set; } = 0.0;
|
||||
public int StartIdx { get; set; } = 0;
|
||||
public int EndIdx { get; set; } = 0;
|
||||
public bool Combined { get; set; } = true;
|
||||
public bool IsOldSide { get; set; } = false;
|
||||
|
||||
public bool ShouldReplace(TextDiffViewChunk old)
|
||||
{
|
||||
if (old == null)
|
||||
return true;
|
||||
|
||||
return Math.Abs(Y - old.Y) > 0.001 ||
|
||||
Math.Abs(Height - old.Height) > 0.001 ||
|
||||
StartIdx != old.StartIdx ||
|
||||
EndIdx != old.EndIdx ||
|
||||
Combined != old.Combined ||
|
||||
IsOldSide != old.IsOldSide;
|
||||
}
|
||||
}
|
||||
|
||||
public record TextDiffViewRange
|
||||
{
|
||||
public int StartIdx { get; set; } = 0;
|
||||
public int EndIdx { get; set; } = 0;
|
||||
|
||||
public TextDiffViewRange(int startIdx, int endIdx)
|
||||
{
|
||||
StartIdx = startIdx;
|
||||
EndIdx = endIdx;
|
||||
}
|
||||
}
|
||||
|
||||
public class ThemedTextDiffPresenter : TextEditor
|
||||
{
|
||||
public class VerticalSeparatorMargin : AbstractMargin
|
||||
@@ -134,13 +100,12 @@ namespace SourceGit.Views
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
var presenter = this.FindAncestorOfType<ThemedTextDiffPresenter>();
|
||||
if (presenter == null)
|
||||
if (presenter is not { DataContext: ViewModels.TextDiffContext ctx })
|
||||
return new Size(32, 0);
|
||||
|
||||
var maxLineNumber = presenter.GetMaxLineNumber();
|
||||
var typeface = TextView.CreateTypeface();
|
||||
var test = new FormattedText(
|
||||
$"{maxLineNumber}",
|
||||
$"{ctx.Data.MaxLineNumber}",
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
@@ -155,8 +120,8 @@ namespace SourceGit.Views
|
||||
InvalidateMeasure();
|
||||
}
|
||||
|
||||
private bool _usePresenter = false;
|
||||
private bool _isOld = false;
|
||||
private readonly bool _usePresenter = false;
|
||||
private readonly bool _isOld = false;
|
||||
}
|
||||
|
||||
public class LineModifyTypeMargin : AbstractMargin
|
||||
@@ -256,8 +221,8 @@ namespace SourceGit.Views
|
||||
return;
|
||||
|
||||
var changeBlock = _presenter.BlockNavigation?.GetCurrentBlock();
|
||||
Brush changeBlockBG = new SolidColorBrush(Colors.Gray, 0.25);
|
||||
Pen changeBlockFG = new Pen(Brushes.Gray);
|
||||
var changeBlockBG = new SolidColorBrush(Colors.Gray, 0.25);
|
||||
var changeBlockFG = new Pen(Brushes.Gray);
|
||||
|
||||
var lines = _presenter.GetLines();
|
||||
var width = textView.Bounds.Width;
|
||||
@@ -341,7 +306,7 @@ namespace SourceGit.Views
|
||||
};
|
||||
}
|
||||
|
||||
private ThemedTextDiffPresenter _presenter = null;
|
||||
private readonly ThemedTextDiffPresenter _presenter = null;
|
||||
}
|
||||
|
||||
public class LineStyleTransformer(ThemedTextDiffPresenter presenter) : DocumentColorizingTransformer
|
||||
@@ -482,24 +447,15 @@ namespace SourceGit.Views
|
||||
set => SetValue(EnableChunkSelectionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<TextDiffViewChunk> SelectedChunkProperty =
|
||||
AvaloniaProperty.Register<ThemedTextDiffPresenter, TextDiffViewChunk>(nameof(SelectedChunk));
|
||||
public static readonly StyledProperty<ViewModels.TextDiffSelectedChunk> SelectedChunkProperty =
|
||||
AvaloniaProperty.Register<ThemedTextDiffPresenter, ViewModels.TextDiffSelectedChunk>(nameof(SelectedChunk));
|
||||
|
||||
public TextDiffViewChunk SelectedChunk
|
||||
public ViewModels.TextDiffSelectedChunk SelectedChunk
|
||||
{
|
||||
get => GetValue(SelectedChunkProperty);
|
||||
set => SetValue(SelectedChunkProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<TextDiffViewRange> DisplayRangeProperty =
|
||||
AvaloniaProperty.Register<ThemedTextDiffPresenter, TextDiffViewRange>(nameof(DisplayRange), new TextDiffViewRange(0, 0));
|
||||
|
||||
public TextDiffViewRange DisplayRange
|
||||
{
|
||||
get => GetValue(DisplayRangeProperty);
|
||||
set => SetValue(DisplayRangeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<ViewModels.BlockNavigation> BlockNavigationProperty =
|
||||
AvaloniaProperty.Register<ThemedTextDiffPresenter, ViewModels.BlockNavigation>(nameof(BlockNavigation));
|
||||
|
||||
@@ -534,19 +490,23 @@ namespace SourceGit.Views
|
||||
return [];
|
||||
}
|
||||
|
||||
public virtual int GetMaxLineNumber()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual void UpdateSelectedChunk(double y)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void GotoFirstChange()
|
||||
{
|
||||
var blockNavigation = BlockNavigation;
|
||||
var prev = blockNavigation?.GotoFirst();
|
||||
var first = BlockNavigation?.GotoFirst();
|
||||
if (first != null)
|
||||
{
|
||||
TextArea.Caret.Line = first.Start;
|
||||
ScrollToLine(first.Start);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void GotoPrevChange()
|
||||
{
|
||||
var prev = BlockNavigation?.GotoPrev();
|
||||
if (prev != null)
|
||||
{
|
||||
TextArea.Caret.Line = prev.Start;
|
||||
@@ -554,106 +514,19 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void GotoPrevChange()
|
||||
{
|
||||
var blockNavigation = BlockNavigation;
|
||||
if (blockNavigation != null)
|
||||
{
|
||||
var prev = blockNavigation.GotoPrev();
|
||||
if (prev != null)
|
||||
{
|
||||
TextArea.Caret.Line = prev.Start;
|
||||
ScrollToLine(prev.Start);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var firstLineIdx = DisplayRange.StartIdx;
|
||||
if (firstLineIdx <= 1)
|
||||
return;
|
||||
|
||||
var lines = GetLines();
|
||||
var firstLineType = lines[firstLineIdx].Type;
|
||||
var prevLineType = lines[firstLineIdx - 1].Type;
|
||||
var isChangeFirstLine = firstLineType != Models.TextDiffLineType.Normal && firstLineType != Models.TextDiffLineType.Indicator;
|
||||
var isChangePrevLine = prevLineType != Models.TextDiffLineType.Normal && prevLineType != Models.TextDiffLineType.Indicator;
|
||||
if (isChangeFirstLine && isChangePrevLine)
|
||||
{
|
||||
for (var i = firstLineIdx - 2; i >= 0; i--)
|
||||
{
|
||||
var prevType = lines[i].Type;
|
||||
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
ScrollToLine(i + 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var findChange = false;
|
||||
for (var i = firstLineIdx - 1; i >= 0; i--)
|
||||
{
|
||||
var prevType = lines[i].Type;
|
||||
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
if (findChange)
|
||||
{
|
||||
ScrollToLine(i + 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!findChange)
|
||||
{
|
||||
findChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void GotoNextChange()
|
||||
{
|
||||
var blockNavigation = BlockNavigation;
|
||||
if (blockNavigation != null)
|
||||
var next = BlockNavigation?.GotoNext();
|
||||
if (next != null)
|
||||
{
|
||||
var next = blockNavigation.GotoNext();
|
||||
if (next != null)
|
||||
{
|
||||
TextArea.Caret.Line = next.Start;
|
||||
ScrollToLine(next.Start);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var lines = GetLines();
|
||||
var lastLineIdx = DisplayRange.EndIdx;
|
||||
if (lastLineIdx >= lines.Count - 1)
|
||||
return;
|
||||
|
||||
var lastLineType = lines[lastLineIdx].Type;
|
||||
var findNormalLine = lastLineType == Models.TextDiffLineType.Normal || lastLineType == Models.TextDiffLineType.Indicator;
|
||||
for (var idx = lastLineIdx + 1; idx < lines.Count; idx++)
|
||||
{
|
||||
var nextType = lines[idx].Type;
|
||||
if (nextType is Models.TextDiffLineType.None or Models.TextDiffLineType.Added or Models.TextDiffLineType.Deleted)
|
||||
{
|
||||
if (findNormalLine)
|
||||
{
|
||||
ScrollToLine(idx + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!findNormalLine)
|
||||
{
|
||||
findNormalLine = true;
|
||||
}
|
||||
TextArea.Caret.Line = next.Start;
|
||||
ScrollToLine(next.Start);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void GotoLastChange()
|
||||
{
|
||||
var blockNavigation = BlockNavigation;
|
||||
var next = blockNavigation?.GotoLast();
|
||||
var next = BlockNavigation?.GotoLast();
|
||||
if (next != null)
|
||||
{
|
||||
TextArea.Caret.Line = next.Start;
|
||||
@@ -683,6 +556,7 @@ namespace SourceGit.Views
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
TextArea.Caret.PositionChanged += OnTextAreaCaretPositionChanged;
|
||||
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
||||
TextArea.TextView.PointerEntered += OnTextViewPointerChanged;
|
||||
TextArea.TextView.PointerMoved += OnTextViewPointerChanged;
|
||||
@@ -701,6 +575,7 @@ namespace SourceGit.Views
|
||||
|
||||
TextArea.RemoveHandler(KeyDownEvent, OnTextAreaKeyDown);
|
||||
|
||||
TextArea.Caret.PositionChanged -= OnTextAreaCaretPositionChanged;
|
||||
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
||||
TextArea.TextView.PointerEntered -= OnTextViewPointerChanged;
|
||||
TextArea.TextView.PointerMoved -= OnTextViewPointerChanged;
|
||||
@@ -746,12 +621,6 @@ namespace SourceGit.Views
|
||||
}
|
||||
else if (change.Property == BlockNavigationProperty)
|
||||
{
|
||||
if (change.OldValue is ViewModels.BlockNavigation oldValue)
|
||||
oldValue.PropertyChanged -= OnBlockNavigationPropertyChanged;
|
||||
|
||||
if (change.NewValue is ViewModels.BlockNavigation newValue)
|
||||
newValue.PropertyChanged += OnBlockNavigationPropertyChanged;
|
||||
|
||||
TextArea?.TextView?.Redraw();
|
||||
}
|
||||
}
|
||||
@@ -771,10 +640,9 @@ namespace SourceGit.Views
|
||||
base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
private void OnBlockNavigationPropertyChanged(object _1, PropertyChangedEventArgs e)
|
||||
private void OnTextAreaCaretPositionChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Current")
|
||||
TextArea?.TextView?.Redraw();
|
||||
BlockNavigation?.UpdateByCaretPosition(TextArea?.Caret?.Line ?? 0);
|
||||
}
|
||||
|
||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
@@ -850,9 +718,15 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnTextViewVisualLinesChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.TextDiffContext ctx)
|
||||
return;
|
||||
|
||||
if (ctx.IsSideBySide() && !IsOld)
|
||||
return;
|
||||
|
||||
if (!TextArea.TextView.VisualLinesValid)
|
||||
{
|
||||
SetCurrentValue(DisplayRangeProperty, new TextDiffViewRange(0, 0));
|
||||
ctx.DisplayRange = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -873,89 +747,15 @@ namespace SourceGit.Views
|
||||
start = index;
|
||||
}
|
||||
|
||||
SetCurrentValue(DisplayRangeProperty, new TextDiffViewRange(start, start + count));
|
||||
ctx.DisplayRange = new ViewModels.TextDiffDisplayRange(start, start + count);
|
||||
}
|
||||
|
||||
protected void TrySetChunk(TextDiffViewChunk chunk)
|
||||
protected void TrySetChunk(ViewModels.TextDiffSelectedChunk chunk)
|
||||
{
|
||||
var old = SelectedChunk;
|
||||
if (chunk == null)
|
||||
{
|
||||
if (old != null)
|
||||
SetCurrentValue(SelectedChunkProperty, null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (chunk.ShouldReplace(old))
|
||||
if (ViewModels.TextDiffSelectedChunk.IsChanged(SelectedChunk, chunk))
|
||||
SetCurrentValue(SelectedChunkProperty, chunk);
|
||||
}
|
||||
|
||||
protected (int, int) FindRangeByIndex(List<Models.TextDiffLine> lines, int lineIdx)
|
||||
{
|
||||
var startIdx = -1;
|
||||
var endIdx = -1;
|
||||
|
||||
var normalLineCount = 0;
|
||||
var modifiedLineCount = 0;
|
||||
|
||||
for (int i = lineIdx; i >= 0; i--)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (line.Type == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
startIdx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.Type == Models.TextDiffLineType.Normal)
|
||||
{
|
||||
normalLineCount++;
|
||||
if (normalLineCount >= 2)
|
||||
{
|
||||
startIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
normalLineCount = 0;
|
||||
modifiedLineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
normalLineCount = lines[lineIdx].Type == Models.TextDiffLineType.Normal ? 1 : 0;
|
||||
for (int i = lineIdx + 1; i < lines.Count; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (line.Type == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
endIdx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.Type == Models.TextDiffLineType.Normal)
|
||||
{
|
||||
normalLineCount++;
|
||||
if (normalLineCount >= 2)
|
||||
{
|
||||
endIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
normalLineCount = 0;
|
||||
modifiedLineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (endIdx == -1)
|
||||
endIdx = lines.Count - 1;
|
||||
|
||||
return modifiedLineCount > 0 ? (startIdx, endIdx) : (-1, -1);
|
||||
}
|
||||
|
||||
private void UpdateTextMate()
|
||||
{
|
||||
if (UseSyntaxHighlighting)
|
||||
@@ -1072,21 +872,14 @@ namespace SourceGit.Views
|
||||
|
||||
public override List<Models.TextDiffLine> GetLines()
|
||||
{
|
||||
if (DataContext is Models.TextDiff diff)
|
||||
if (DataContext is ViewModels.CombinedTextDiff { Data: { } diff })
|
||||
return diff.Lines;
|
||||
return [];
|
||||
}
|
||||
|
||||
public override int GetMaxLineNumber()
|
||||
{
|
||||
if (DataContext is Models.TextDiff diff)
|
||||
return diff.MaxLineNumber;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void UpdateSelectedChunk(double y)
|
||||
{
|
||||
if (DataContext is not Models.TextDiff diff)
|
||||
if (DataContext is not ViewModels.CombinedTextDiff { Data: { } diff } combined)
|
||||
return;
|
||||
|
||||
var view = TextArea.TextView;
|
||||
@@ -1134,15 +927,7 @@ namespace SourceGit.Views
|
||||
endLine.GetTextLineVisualYPosition(endLine.TextLines[^1], VisualYPosition.TextBottom) - view.VerticalOffset :
|
||||
view.Bounds.Height;
|
||||
|
||||
TrySetChunk(new TextDiffViewChunk()
|
||||
{
|
||||
Y = rectStartY,
|
||||
Height = rectEndY - rectStartY,
|
||||
StartIdx = startIdx,
|
||||
EndIdx = endIdx,
|
||||
Combined = true,
|
||||
IsOldSide = false,
|
||||
});
|
||||
TrySetChunk(new(rectStartY, rectEndY - rectStartY, startIdx, endIdx, true, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1170,7 +955,7 @@ namespace SourceGit.Views
|
||||
return;
|
||||
}
|
||||
|
||||
var (startIdx, endIdx) = FindRangeByIndex(diff.Lines, lineIdx);
|
||||
var (startIdx, endIdx) = combined.FindRangeByIndex(diff.Lines, lineIdx);
|
||||
if (startIdx == -1)
|
||||
{
|
||||
TrySetChunk(null);
|
||||
@@ -1187,15 +972,7 @@ namespace SourceGit.Views
|
||||
endLine.GetTextLineVisualYPosition(endLine.TextLines[^1], VisualYPosition.TextBottom) - view.VerticalOffset :
|
||||
view.Bounds.Height;
|
||||
|
||||
TrySetChunk(new TextDiffViewChunk()
|
||||
{
|
||||
Y = rectStartY,
|
||||
Height = rectEndY - rectStartY,
|
||||
StartIdx = startIdx,
|
||||
EndIdx = endIdx,
|
||||
Combined = true,
|
||||
IsOldSide = false,
|
||||
});
|
||||
TrySetChunk(new(rectStartY, rectEndY - rectStartY, startIdx, endIdx, true, false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1223,10 +1000,10 @@ namespace SourceGit.Views
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
|
||||
if (DataContext is Models.TextDiff textDiff)
|
||||
if (DataContext is ViewModels.CombinedTextDiff { Data: { } diff })
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
foreach (var line in textDiff.Lines)
|
||||
foreach (var line in diff.Lines)
|
||||
{
|
||||
if (line.Content.Length > 10000)
|
||||
{
|
||||
@@ -1279,35 +1056,28 @@ namespace SourceGit.Views
|
||||
return [];
|
||||
}
|
||||
|
||||
public override int GetMaxLineNumber()
|
||||
{
|
||||
if (DataContext is ViewModels.TwoSideTextDiff diff)
|
||||
return diff.MaxLineNumber;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void GotoFirstChange()
|
||||
{
|
||||
base.GotoFirstChange();
|
||||
DirectSyncScrollOffset();
|
||||
SyncScrollOffset();
|
||||
}
|
||||
|
||||
public override void GotoPrevChange()
|
||||
{
|
||||
base.GotoPrevChange();
|
||||
DirectSyncScrollOffset();
|
||||
SyncScrollOffset();
|
||||
}
|
||||
|
||||
public override void GotoNextChange()
|
||||
{
|
||||
base.GotoNextChange();
|
||||
DirectSyncScrollOffset();
|
||||
SyncScrollOffset();
|
||||
}
|
||||
|
||||
public override void GotoLastChange()
|
||||
{
|
||||
base.GotoLastChange();
|
||||
DirectSyncScrollOffset();
|
||||
SyncScrollOffset();
|
||||
}
|
||||
|
||||
public override void UpdateSelectedChunk(double y)
|
||||
@@ -1315,10 +1085,6 @@ namespace SourceGit.Views
|
||||
if (DataContext is not ViewModels.TwoSideTextDiff diff)
|
||||
return;
|
||||
|
||||
var parent = this.FindAncestorOfType<TextDiffView>();
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
var view = TextArea.TextView;
|
||||
var lines = IsOld ? diff.Old : diff.New;
|
||||
var selection = TextArea.Selection;
|
||||
@@ -1365,22 +1131,10 @@ namespace SourceGit.Views
|
||||
endLine.GetTextLineVisualYPosition(endLine.TextLines[^1], VisualYPosition.TextBottom) - view.VerticalOffset :
|
||||
view.Bounds.Height;
|
||||
|
||||
diff.ConvertsToCombinedRange(parent.DataContext as Models.TextDiff, ref startIdx, ref endIdx, IsOld);
|
||||
|
||||
TrySetChunk(new TextDiffViewChunk()
|
||||
{
|
||||
Y = rectStartY,
|
||||
Height = rectEndY - rectStartY,
|
||||
StartIdx = startIdx,
|
||||
EndIdx = endIdx,
|
||||
Combined = false,
|
||||
IsOldSide = IsOld,
|
||||
});
|
||||
|
||||
return;
|
||||
diff.ConvertsToCombinedRange(ref startIdx, ref endIdx, IsOld);
|
||||
TrySetChunk(new(rectStartY, rectEndY - rectStartY, startIdx, endIdx, false, IsOld));
|
||||
}
|
||||
|
||||
if (this.FindAncestorOfType<TextDiffView>()?.DataContext is Models.TextDiff textDiff)
|
||||
else
|
||||
{
|
||||
var lineIdx = -1;
|
||||
foreach (var line in view.VisualLines)
|
||||
@@ -1406,7 +1160,7 @@ namespace SourceGit.Views
|
||||
return;
|
||||
}
|
||||
|
||||
var (startIdx, endIdx) = FindRangeByIndex(lines, lineIdx);
|
||||
var (startIdx, endIdx) = diff.FindRangeByIndex(lines, lineIdx);
|
||||
if (startIdx == -1)
|
||||
{
|
||||
TrySetChunk(null);
|
||||
@@ -1423,15 +1177,21 @@ namespace SourceGit.Views
|
||||
endLine.GetTextLineVisualYPosition(endLine.TextLines[^1], VisualYPosition.TextBottom) - view.VerticalOffset :
|
||||
view.Bounds.Height;
|
||||
|
||||
TrySetChunk(new TextDiffViewChunk()
|
||||
{
|
||||
Y = rectStartY,
|
||||
Height = rectEndY - rectStartY,
|
||||
StartIdx = textDiff.Lines.IndexOf(lines[startIdx]),
|
||||
EndIdx = endIdx == lines.Count - 1 ? textDiff.Lines.Count - 1 : textDiff.Lines.IndexOf(lines[endIdx]),
|
||||
Combined = true,
|
||||
IsOldSide = false,
|
||||
});
|
||||
diff.ConvertsToCombinedRange(ref startIdx, ref endIdx, IsOld);
|
||||
TrySetChunk(new(rectStartY, rectEndY - rectStartY, startIdx, endIdx, true, false));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == BlockNavigationProperty)
|
||||
{
|
||||
if (change.OldValue is ViewModels.BlockNavigation oldValue)
|
||||
oldValue.PropertyChanged -= OnBlockNavigationPropertyChanged;
|
||||
if (change.NewValue is ViewModels.BlockNavigation newValue)
|
||||
newValue.PropertyChanged += OnBlockNavigationPropertyChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1443,7 +1203,7 @@ namespace SourceGit.Views
|
||||
if (_scrollViewer != null)
|
||||
{
|
||||
_scrollViewer.ScrollChanged += OnTextViewScrollChanged;
|
||||
_scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.OneWay));
|
||||
_scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("ScrollOffset", BindingMode.OneWay));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1498,22 +1258,28 @@ namespace SourceGit.Views
|
||||
if (_scrollViewer == null || DataContext is not ViewModels.TwoSideTextDiff diff)
|
||||
return;
|
||||
|
||||
if (diff.SyncScrollOffset.NearlyEquals(_scrollViewer.Offset))
|
||||
if (diff.ScrollOffset.NearlyEquals(_scrollViewer.Offset))
|
||||
return;
|
||||
|
||||
if (IsPointerOver || !e.OffsetDelta.NearlyEquals(Vector.Zero))
|
||||
{
|
||||
diff.SyncScrollOffset = _scrollViewer.Offset;
|
||||
diff.ScrollOffset = _scrollViewer.Offset;
|
||||
|
||||
if (!TextArea.TextView.IsPointerOver)
|
||||
TrySetChunk(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void DirectSyncScrollOffset()
|
||||
private void OnBlockNavigationPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if ("Indicator".Equals(e.PropertyName, StringComparison.Ordinal))
|
||||
TextArea?.TextView?.Redraw();
|
||||
}
|
||||
|
||||
private void SyncScrollOffset()
|
||||
{
|
||||
if (_scrollViewer is not null && DataContext is ViewModels.TwoSideTextDiff diff)
|
||||
diff.SyncScrollOffset = _scrollViewer.Offset;
|
||||
diff.ScrollOffset = _scrollViewer.Offset;
|
||||
}
|
||||
|
||||
private ScrollViewer _scrollViewer = null;
|
||||
@@ -1539,10 +1305,10 @@ namespace SourceGit.Views
|
||||
set => SetValue(DeletedLineBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<TextDiffViewRange> DisplayRangeProperty =
|
||||
AvaloniaProperty.Register<TextDiffViewMinimap, TextDiffViewRange>(nameof(DisplayRange), new TextDiffViewRange(0, 0));
|
||||
public static readonly StyledProperty<ViewModels.TextDiffDisplayRange> DisplayRangeProperty =
|
||||
AvaloniaProperty.Register<TextDiffViewMinimap, ViewModels.TextDiffDisplayRange>(nameof(DisplayRange));
|
||||
|
||||
public TextDiffViewRange DisplayRange
|
||||
public ViewModels.TextDiffDisplayRange DisplayRange
|
||||
{
|
||||
get => GetValue(DisplayRangeProperty);
|
||||
set => SetValue(DisplayRangeProperty, value);
|
||||
@@ -1576,18 +1342,19 @@ namespace SourceGit.Views
|
||||
RenderSingleSide(context, twoSideDiff.Old, 0, halfWidth);
|
||||
RenderSingleSide(context, twoSideDiff.New, halfWidth, halfWidth);
|
||||
}
|
||||
else if (DataContext is Models.TextDiff diff)
|
||||
else if (DataContext is ViewModels.CombinedTextDiff combined)
|
||||
{
|
||||
total = diff.Lines.Count;
|
||||
RenderSingleSide(context, diff.Lines, 0, Bounds.Width);
|
||||
var data = combined.Data;
|
||||
total = data.Lines.Count;
|
||||
RenderSingleSide(context, data.Lines, 0, Bounds.Width);
|
||||
}
|
||||
|
||||
var range = DisplayRange;
|
||||
if (range.EndIdx == 0)
|
||||
if (range == null || range.End == 0)
|
||||
return;
|
||||
|
||||
var startY = range.StartIdx / (total * 1.0) * Bounds.Height;
|
||||
var endY = range.EndIdx / (total * 1.0) * Bounds.Height;
|
||||
var startY = range.Start / (total * 1.0) * Bounds.Height;
|
||||
var endY = range.End / (total * 1.0) * Bounds.Height;
|
||||
var color = DisplayRangeColor;
|
||||
var brush = new SolidColorBrush(color, 0.2);
|
||||
var pen = new Pen(color.ToUInt32());
|
||||
@@ -1639,189 +1406,53 @@ namespace SourceGit.Views
|
||||
|
||||
public partial class TextDiffView : UserControl
|
||||
{
|
||||
public static readonly StyledProperty<bool> UseSideBySideDiffProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseSideBySideDiff));
|
||||
public static readonly StyledProperty<ViewModels.TextDiffSelectedChunk> SelectedChunkProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, ViewModels.TextDiffSelectedChunk>(nameof(SelectedChunk));
|
||||
|
||||
public bool UseSideBySideDiff
|
||||
{
|
||||
get => GetValue(UseSideBySideDiffProperty);
|
||||
set => SetValue(UseSideBySideDiffProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<TextDiffViewChunk> SelectedChunkProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, TextDiffViewChunk>(nameof(SelectedChunk));
|
||||
|
||||
public TextDiffViewChunk SelectedChunk
|
||||
public ViewModels.TextDiffSelectedChunk SelectedChunk
|
||||
{
|
||||
get => GetValue(SelectedChunkProperty);
|
||||
set => SetValue(SelectedChunkProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsUnstagedChangeProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, bool>(nameof(IsUnstagedChange));
|
||||
|
||||
public bool IsUnstagedChange
|
||||
{
|
||||
get => GetValue(IsUnstagedChangeProperty);
|
||||
set => SetValue(IsUnstagedChangeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> EnableChunkSelectionProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, bool>(nameof(EnableChunkSelection));
|
||||
|
||||
public bool EnableChunkSelection
|
||||
{
|
||||
get => GetValue(EnableChunkSelectionProperty);
|
||||
set => SetValue(EnableChunkSelectionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> UseBlockNavigationProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseBlockNavigation));
|
||||
|
||||
public bool UseBlockNavigation
|
||||
{
|
||||
get => GetValue(UseBlockNavigationProperty);
|
||||
set => SetValue(UseBlockNavigationProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<ViewModels.BlockNavigation> BlockNavigationProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, ViewModels.BlockNavigation>(nameof(BlockNavigation));
|
||||
|
||||
public ViewModels.BlockNavigation BlockNavigation
|
||||
{
|
||||
get => GetValue(BlockNavigationProperty);
|
||||
set => SetValue(BlockNavigationProperty, value);
|
||||
}
|
||||
|
||||
public static readonly RoutedEvent<RoutedEventArgs> BlockNavigationChangedEvent =
|
||||
RoutedEvent.Register<TextDiffView, RoutedEventArgs>(nameof(BlockNavigationChanged), RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
|
||||
|
||||
public event EventHandler<RoutedEventArgs> BlockNavigationChanged
|
||||
{
|
||||
add { AddHandler(BlockNavigationChangedEvent, value); }
|
||||
remove { RemoveHandler(BlockNavigationChangedEvent, value); }
|
||||
}
|
||||
|
||||
static TextDiffView()
|
||||
{
|
||||
UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
|
||||
{
|
||||
v.RefreshContent(v.DataContext as Models.TextDiff, false);
|
||||
});
|
||||
|
||||
UseBlockNavigationProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
|
||||
{
|
||||
v.RefreshBlockNavigation();
|
||||
});
|
||||
|
||||
SelectedChunkProperty.Changed.AddClassHandler<TextDiffView>((v, _) =>
|
||||
{
|
||||
var chunk = v.SelectedChunk;
|
||||
if (chunk == null)
|
||||
{
|
||||
v.Popup.IsVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var top = chunk.Y + (chunk.Height >= 36 ? 8 : 2);
|
||||
var right = (chunk.Combined || !chunk.IsOldSide) ? 26 : (v.Bounds.Width * 0.5f) + 26;
|
||||
v.Popup.Margin = new Thickness(0, top, right, 0);
|
||||
v.Popup.IsVisible = true;
|
||||
});
|
||||
}
|
||||
|
||||
public TextDiffView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void GotoFirstChange()
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoFirstChange();
|
||||
TryRaiseBlockNavigationChanged();
|
||||
}
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
public void GotoPrevChange()
|
||||
{
|
||||
this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoPrevChange();
|
||||
TryRaiseBlockNavigationChanged();
|
||||
}
|
||||
|
||||
public void GotoNextChange()
|
||||
{
|
||||
this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoNextChange();
|
||||
TryRaiseBlockNavigationChanged();
|
||||
}
|
||||
|
||||
public void GotoLastChange()
|
||||
{
|
||||
this.FindDescendantOfType<ThemedTextDiffPresenter>()?.GotoLastChange();
|
||||
TryRaiseBlockNavigationChanged();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
RefreshContent(DataContext as Models.TextDiff);
|
||||
if (change.Property == SelectedChunkProperty)
|
||||
{
|
||||
if (SelectedChunk is { } chunk)
|
||||
{
|
||||
var top = chunk.Y + (chunk.Height >= 36 ? 8 : 2);
|
||||
var right = (chunk.Combined || !chunk.IsOldSide) ? 26 : (Bounds.Width * 0.5f) + 26;
|
||||
Popup.Margin = new Thickness(0, top, right, 0);
|
||||
Popup.IsVisible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Popup.IsVisible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerExited(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerExited(e);
|
||||
|
||||
if (SelectedChunk != null)
|
||||
SetCurrentValue(SelectedChunkProperty, null);
|
||||
}
|
||||
|
||||
private void RefreshContent(Models.TextDiff diff, bool keepScrollOffset = true)
|
||||
{
|
||||
if (SelectedChunk != null)
|
||||
SetCurrentValue(SelectedChunkProperty, null);
|
||||
|
||||
if (diff == null)
|
||||
{
|
||||
Editor.Content = null;
|
||||
GC.Collect();
|
||||
return;
|
||||
}
|
||||
|
||||
if (UseSideBySideDiff)
|
||||
{
|
||||
var previousContent = Editor.Content as ViewModels.TwoSideTextDiff;
|
||||
Editor.Content = new ViewModels.TwoSideTextDiff(diff, keepScrollOffset ? previousContent : null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!keepScrollOffset)
|
||||
diff.ScrollOffset = Vector.Zero;
|
||||
Editor.Content = diff;
|
||||
}
|
||||
|
||||
RefreshBlockNavigation();
|
||||
|
||||
IsUnstagedChange = diff.Option.IsUnstaged;
|
||||
EnableChunkSelection = diff.Option.WorkingCopyChange != null;
|
||||
}
|
||||
|
||||
private void RefreshBlockNavigation()
|
||||
{
|
||||
if (UseBlockNavigation)
|
||||
BlockNavigation = new ViewModels.BlockNavigation(Editor.Content);
|
||||
else
|
||||
BlockNavigation = null;
|
||||
|
||||
TryRaiseBlockNavigationChanged();
|
||||
if (DataContext is ViewModels.TextDiffContext ctx)
|
||||
ctx.SelectedChunk = null;
|
||||
}
|
||||
|
||||
private async void OnStageChunk(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
var chunk = SelectedChunk;
|
||||
if (chunk == null)
|
||||
if (DataContext is not ViewModels.TextDiffContext { SelectedChunk: { } chunk, Data: { } diff })
|
||||
return;
|
||||
|
||||
var diff = DataContext as Models.TextDiff;
|
||||
|
||||
var change = diff?.Option.WorkingCopyChange;
|
||||
var change = diff.Option.WorkingCopyChange;
|
||||
if (change == null)
|
||||
return;
|
||||
|
||||
@@ -1830,7 +1461,6 @@ namespace SourceGit.Views
|
||||
return;
|
||||
|
||||
var repoView = this.FindAncestorOfType<Repository>();
|
||||
|
||||
if (repoView?.DataContext is not ViewModels.Repository repo)
|
||||
return;
|
||||
|
||||
@@ -1849,16 +1479,16 @@ namespace SourceGit.Views
|
||||
}
|
||||
else if (chunk.Combined)
|
||||
{
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync();
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync();
|
||||
diff.GeneratePatchFromSelection(change, treeGuid, selection, false, tmpFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync();
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync();
|
||||
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, false, chunk.IsOldSide, tmpFile);
|
||||
}
|
||||
|
||||
await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--cache --index").ExecAsync();
|
||||
await new Commands.Apply(repo.FullPath, tmpFile, true, "nowarn", "--cache --index").ExecAsync();
|
||||
File.Delete(tmpFile);
|
||||
}
|
||||
|
||||
@@ -1868,13 +1498,10 @@ namespace SourceGit.Views
|
||||
|
||||
private async void OnUnstageChunk(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
var chunk = SelectedChunk;
|
||||
if (chunk == null)
|
||||
if (DataContext is not ViewModels.TextDiffContext { SelectedChunk: { } chunk, Data: { } diff })
|
||||
return;
|
||||
|
||||
var diff = DataContext as Models.TextDiff;
|
||||
|
||||
var change = diff?.Option.WorkingCopyChange;
|
||||
var change = diff.Option.WorkingCopyChange;
|
||||
if (change == null)
|
||||
return;
|
||||
|
||||
@@ -1883,7 +1510,6 @@ namespace SourceGit.Views
|
||||
return;
|
||||
|
||||
var repoView = this.FindAncestorOfType<Repository>();
|
||||
|
||||
if (repoView?.DataContext is not ViewModels.Repository repo)
|
||||
return;
|
||||
|
||||
@@ -1898,7 +1524,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync();
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync();
|
||||
var tmpFile = Path.GetTempFileName();
|
||||
if (change.Index == Models.ChangeState.Added)
|
||||
diff.GenerateNewPatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
@@ -1907,7 +1533,7 @@ namespace SourceGit.Views
|
||||
else
|
||||
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
|
||||
|
||||
await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--cache --index --reverse").ExecAsync();
|
||||
await new Commands.Apply(repo.FullPath, tmpFile, true, "nowarn", "--cache --index --reverse").ExecAsync();
|
||||
File.Delete(tmpFile);
|
||||
}
|
||||
|
||||
@@ -1917,13 +1543,10 @@ namespace SourceGit.Views
|
||||
|
||||
private async void OnDiscardChunk(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
var chunk = SelectedChunk;
|
||||
if (chunk == null)
|
||||
if (DataContext is not ViewModels.TextDiffContext { SelectedChunk: { } chunk, Data: { } diff })
|
||||
return;
|
||||
|
||||
var diff = DataContext as Models.TextDiff;
|
||||
|
||||
var change = diff?.Option.WorkingCopyChange;
|
||||
var change = diff.Option.WorkingCopyChange;
|
||||
if (change == null)
|
||||
return;
|
||||
|
||||
@@ -1951,27 +1574,21 @@ namespace SourceGit.Views
|
||||
}
|
||||
else if (chunk.Combined)
|
||||
{
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync();
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync();
|
||||
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync();
|
||||
var treeGuid = await new Commands.QueryStagedFileBlobGuid(repo.FullPath, change.Path).GetResultAsync();
|
||||
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
|
||||
}
|
||||
|
||||
await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--reverse").ExecAsync();
|
||||
await new Commands.Apply(repo.FullPath, tmpFile, true, "nowarn", "--reverse").ExecAsync();
|
||||
File.Delete(tmpFile);
|
||||
}
|
||||
|
||||
repo.MarkWorkingCopyDirtyManually();
|
||||
repo.SetWatcherEnabled(true);
|
||||
}
|
||||
|
||||
private void TryRaiseBlockNavigationChanged()
|
||||
{
|
||||
if (UseBlockNavigation)
|
||||
RaiseEvent(new RoutedEventArgs(BlockNavigationChangedEvent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTreeNodeContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
private void OnTreeNodeContextRequested(object sender, ContextRequestedEventArgs ev)
|
||||
{
|
||||
if (sender is Grid { DataContext: ViewModels.RepositoryNode node } grid)
|
||||
{
|
||||
@@ -204,7 +204,7 @@ namespace SourceGit.Views
|
||||
menu.Open(grid);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
ev.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPointerPressedTreeNode(object sender, PointerPressedEventArgs e)
|
||||
|
||||
@@ -113,6 +113,18 @@ namespace SourceGit.Views
|
||||
vm.OpenWithDefaultEditor(vm.SelectedUnstaged[0]);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key is Key.C &&
|
||||
e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control) &&
|
||||
vm.SelectedUnstaged is { Count: 1 })
|
||||
{
|
||||
var change = vm.SelectedUnstaged[0];
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
await App.CopyTextAsync(Native.OS.GetAbsPath(vm.Repository.FullPath, change.Path));
|
||||
else
|
||||
await App.CopyTextAsync(change.Path);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +146,18 @@ namespace SourceGit.Views
|
||||
vm.OpenWithDefaultEditor(vm.SelectedStaged[0]);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key is Key.C &&
|
||||
e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control) &&
|
||||
vm.SelectedStaged is { Count: 1 })
|
||||
{
|
||||
var change = vm.SelectedStaged[0];
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
await App.CopyTextAsync(Native.OS.GetAbsPath(vm.Repository.FullPath, change.Path));
|
||||
else
|
||||
await App.CopyTextAsync(change.Path);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +439,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
else
|
||||
{
|
||||
var isRooted = change.Path.IndexOf('/') <= 0;
|
||||
var isRooted = change.Path!.IndexOf('/') <= 0;
|
||||
var singleFile = new MenuItem();
|
||||
singleFile.Header = App.Text("WorkingCopy.AddToGitIgnore.SingleFile");
|
||||
singleFile.Click += (_, e) =>
|
||||
@@ -1150,7 +1174,7 @@ namespace SourceGit.Views
|
||||
patch.Icon = App.CreateMenuIcon("Icons.Diff");
|
||||
patch.Click += async (_, e) =>
|
||||
{
|
||||
var storageProvider = TopLevel.GetTopLevel(this).StorageProvider;
|
||||
var storageProvider = TopLevel.GetTopLevel(this)?.StorageProvider;
|
||||
if (storageProvider == null)
|
||||
return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user