mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-24 10:50:52 +08:00
Merge branch 'release/v2025.33'
This commit is contained in:
141
TRANSLATION.md
141
TRANSLATION.md
@@ -6,29 +6,35 @@ This document shows the translation status of each locale file in the repository
|
||||
|
||||
### 
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in de_DE.axaml</summary>
|
||||
|
||||
- Text.BranchCM.SwitchToWorktree
|
||||
- Text.BranchTree.Ahead
|
||||
- Text.BranchTree.AheadBehind
|
||||
- Text.BranchTree.Behind
|
||||
- Text.BranchTree.Status
|
||||
- Text.BranchTree.Worktree
|
||||
- Text.CommitMessageTextBox.PasteAndReplaceAll
|
||||
- Text.DirtyState.HasLocalChanges
|
||||
- Text.DirtyState.HasPendingPullOrPush
|
||||
- Text.DirtyState.UpToDate
|
||||
- Text.Preferences.AI.ReadApiKeyFromEnv
|
||||
- Text.Preferences.Appearance.UseAutoHideScrollBars
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.ScanRepositories.UseCustomDir
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.Worktree.Open
|
||||
|
||||
</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>
|
||||
@@ -48,10 +54,16 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Bisect.Skip
|
||||
- Text.Bisect.WaitingForRange
|
||||
- Text.BranchCM.ResetToSelectedCommit
|
||||
- Text.BranchCM.SwitchToWorktree
|
||||
- Text.BranchTree.Ahead
|
||||
- Text.BranchTree.AheadBehind
|
||||
- Text.BranchTree.Behind
|
||||
- Text.BranchTree.InvalidUpstream
|
||||
- Text.BranchTree.Remote
|
||||
- Text.BranchTree.Status
|
||||
- Text.BranchTree.Tracking
|
||||
- Text.BranchTree.URL
|
||||
- Text.BranchTree.Worktree
|
||||
- Text.ChangeSubmoduleUrl
|
||||
- Text.ChangeSubmoduleUrl.Submodule
|
||||
- Text.ChangeSubmoduleUrl.URL
|
||||
@@ -76,6 +88,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.CommitDetail.Changes.Count
|
||||
- Text.CommitDetail.Info.Key
|
||||
- Text.CommitDetail.Info.Signer
|
||||
- Text.CommitMessageTextBox.PasteAndReplaceAll
|
||||
- Text.CommitMessageTextBox.SubjectCount
|
||||
- Text.Configure.CommitMessageTemplate.BuiltinVars
|
||||
- Text.Configure.CustomAction.Arguments.Tip
|
||||
@@ -116,6 +129,9 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Diff.Old
|
||||
- Text.Diff.Submodule.Deleted
|
||||
- Text.DirHistories
|
||||
- Text.DirtyState.HasLocalChanges
|
||||
- Text.DirtyState.HasPendingPullOrPush
|
||||
- Text.DirtyState.UpToDate
|
||||
- Text.Discard.IncludeUntracked
|
||||
- Text.ExecuteCustomAction.Target
|
||||
- Text.ExecuteCustomAction.Repository
|
||||
@@ -125,12 +141,14 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Global.SwitchTab
|
||||
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
|
||||
- Text.InteractiveRebase.ReorderTip
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Launcher.Pages
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Merge.Edit
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.AI.ReadApiKeyFromEnv
|
||||
- Text.Preferences.Appearance.UseAutoHideScrollBars
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
@@ -160,6 +178,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ResetWithoutCheckout
|
||||
- Text.ResetWithoutCheckout.MoveTo
|
||||
- Text.ResetWithoutCheckout.Target
|
||||
- Text.ScanRepositories.UseCustomDir
|
||||
- Text.SetSubmoduleBranch
|
||||
- Text.SetSubmoduleBranch.Submodule
|
||||
- Text.SetSubmoduleBranch.Current
|
||||
@@ -205,23 +224,40 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
|
||||
- Text.WorkingCopy.Conflicts.UseMine
|
||||
- Text.WorkingCopy.Conflicts.UseTheirs
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.Worktree.Open
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in it_IT.axaml</summary>
|
||||
|
||||
- Text.BranchCM.SwitchToWorktree
|
||||
- Text.BranchTree.Ahead
|
||||
- Text.BranchTree.AheadBehind
|
||||
- Text.BranchTree.Behind
|
||||
- Text.BranchTree.Status
|
||||
- Text.BranchTree.Worktree
|
||||
- Text.CommitMessageTextBox.PasteAndReplaceAll
|
||||
- Text.DirtyState.HasLocalChanges
|
||||
- Text.DirtyState.HasPendingPullOrPush
|
||||
- Text.DirtyState.UpToDate
|
||||
- Text.Preferences.AI.ReadApiKeyFromEnv
|
||||
- Text.Preferences.Appearance.UseAutoHideScrollBars
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.ScanRepositories.UseCustomDir
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.Worktree.Open
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in ja_JP.axaml</summary>
|
||||
@@ -242,10 +278,16 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Bisect.WaitingForRange
|
||||
- Text.BranchCM.CompareWithCurrent
|
||||
- Text.BranchCM.ResetToSelectedCommit
|
||||
- Text.BranchCM.SwitchToWorktree
|
||||
- Text.BranchTree.Ahead
|
||||
- Text.BranchTree.AheadBehind
|
||||
- Text.BranchTree.Behind
|
||||
- Text.BranchTree.InvalidUpstream
|
||||
- Text.BranchTree.Remote
|
||||
- Text.BranchTree.Status
|
||||
- Text.BranchTree.Tracking
|
||||
- Text.BranchTree.URL
|
||||
- Text.BranchTree.Worktree
|
||||
- Text.ChangeSubmoduleUrl
|
||||
- Text.ChangeSubmoduleUrl.Submodule
|
||||
- Text.ChangeSubmoduleUrl.URL
|
||||
@@ -270,6 +312,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.CommitDetail.Changes.Count
|
||||
- Text.CommitDetail.Info.Key
|
||||
- Text.CommitDetail.Info.Signer
|
||||
- Text.CommitMessageTextBox.PasteAndReplaceAll
|
||||
- Text.CommitMessageTextBox.SubjectCount
|
||||
- Text.Configure.CommitMessageTemplate.BuiltinVars
|
||||
- Text.Configure.CustomAction.Arguments.Tip
|
||||
@@ -310,6 +353,9 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Diff.Old
|
||||
- Text.Diff.Submodule.Deleted
|
||||
- Text.DirHistories
|
||||
- Text.DirtyState.HasLocalChanges
|
||||
- Text.DirtyState.HasPendingPullOrPush
|
||||
- Text.DirtyState.UpToDate
|
||||
- Text.Discard.IncludeUntracked
|
||||
- Text.ExecuteCustomAction.Target
|
||||
- Text.ExecuteCustomAction.Repository
|
||||
@@ -319,12 +365,14 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Global.SwitchTab
|
||||
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
|
||||
- Text.InteractiveRebase.ReorderTip
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Launcher.Pages
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Merge.Edit
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.AI.ReadApiKeyFromEnv
|
||||
- Text.Preferences.Appearance.UseAutoHideScrollBars
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
@@ -355,6 +403,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ResetWithoutCheckout
|
||||
- Text.ResetWithoutCheckout.MoveTo
|
||||
- Text.ResetWithoutCheckout.Target
|
||||
- Text.ScanRepositories.UseCustomDir
|
||||
- Text.SetSubmoduleBranch
|
||||
- Text.SetSubmoduleBranch.Submodule
|
||||
- Text.SetSubmoduleBranch.Current
|
||||
@@ -398,11 +447,13 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
|
||||
- Text.WorkingCopy.Conflicts.UseMine
|
||||
- Text.WorkingCopy.Conflicts.UseTheirs
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.Worktree.Open
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in pt_BR.axaml</summary>
|
||||
@@ -430,10 +481,16 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.BranchCM.CustomAction
|
||||
- Text.BranchCM.MergeMultiBranches
|
||||
- Text.BranchCM.ResetToSelectedCommit
|
||||
- Text.BranchCM.SwitchToWorktree
|
||||
- Text.BranchTree.Ahead
|
||||
- Text.BranchTree.AheadBehind
|
||||
- Text.BranchTree.Behind
|
||||
- Text.BranchTree.InvalidUpstream
|
||||
- Text.BranchTree.Remote
|
||||
- Text.BranchTree.Status
|
||||
- Text.BranchTree.Tracking
|
||||
- Text.BranchTree.URL
|
||||
- Text.BranchTree.Worktree
|
||||
- Text.ChangeSubmoduleUrl
|
||||
- Text.ChangeSubmoduleUrl.Submodule
|
||||
- Text.ChangeSubmoduleUrl.URL
|
||||
@@ -463,6 +520,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.CommitDetail.Info.Children
|
||||
- Text.CommitDetail.Info.Key
|
||||
- Text.CommitDetail.Info.Signer
|
||||
- Text.CommitMessageTextBox.PasteAndReplaceAll
|
||||
- Text.CommitMessageTextBox.SubjectCount
|
||||
- Text.Configure.CommitMessageTemplate.BuiltinVars
|
||||
- Text.Configure.CustomAction.Arguments.Tip
|
||||
@@ -494,7 +552,6 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ConfirmRestart.Title
|
||||
- Text.ConfirmRestart.Message
|
||||
- Text.CopyFullPath
|
||||
- Text.CreateBranch.Name.WarnSpace
|
||||
- Text.CreateBranch.OverwriteExisting
|
||||
- Text.DeinitSubmodule
|
||||
- Text.DeinitSubmodule.Force
|
||||
@@ -514,6 +571,9 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Diff.Old
|
||||
- Text.Diff.Submodule.Deleted
|
||||
- Text.DirHistories
|
||||
- Text.DirtyState.HasLocalChanges
|
||||
- Text.DirtyState.HasPendingPullOrPush
|
||||
- Text.DirtyState.UpToDate
|
||||
- Text.Discard.IncludeUntracked
|
||||
- Text.ExecuteCustomAction.Target
|
||||
- Text.ExecuteCustomAction.Repository
|
||||
@@ -530,8 +590,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.InProgress.Rebase.StoppedAt
|
||||
- Text.InProgress.Revert.Head
|
||||
- Text.InteractiveRebase.ReorderTip
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Launcher.Pages
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Merge.Edit
|
||||
- Text.Merge.Source
|
||||
- Text.MergeMultiple
|
||||
@@ -541,8 +601,10 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.AI.ReadApiKeyFromEnv
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.Preferences.Appearance.EditorTabWidth
|
||||
- Text.Preferences.Appearance.UseAutoHideScrollBars
|
||||
- Text.Preferences.General.DateFormat
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
@@ -586,6 +648,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ResetWithoutCheckout
|
||||
- Text.ResetWithoutCheckout.MoveTo
|
||||
- Text.ResetWithoutCheckout.Target
|
||||
- Text.ScanRepositories.UseCustomDir
|
||||
- Text.SetSubmoduleBranch
|
||||
- Text.SetSubmoduleBranch.Submodule
|
||||
- Text.SetSubmoduleBranch.Current
|
||||
@@ -636,14 +699,16 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
|
||||
- Text.WorkingCopy.Conflicts.UseMine
|
||||
- Text.WorkingCopy.Conflicts.UseTheirs
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.WorkingCopy.SignOff
|
||||
- Text.Worktree.Open
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in ta_IN.axaml</summary>
|
||||
@@ -664,10 +729,16 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Bisect.WaitingForRange
|
||||
- Text.BranchCM.CompareWithCurrent
|
||||
- Text.BranchCM.ResetToSelectedCommit
|
||||
- Text.BranchCM.SwitchToWorktree
|
||||
- Text.BranchTree.Ahead
|
||||
- Text.BranchTree.AheadBehind
|
||||
- Text.BranchTree.Behind
|
||||
- Text.BranchTree.InvalidUpstream
|
||||
- Text.BranchTree.Remote
|
||||
- Text.BranchTree.Status
|
||||
- Text.BranchTree.Tracking
|
||||
- Text.BranchTree.URL
|
||||
- Text.BranchTree.Worktree
|
||||
- Text.ChangeSubmoduleUrl
|
||||
- Text.ChangeSubmoduleUrl.Submodule
|
||||
- Text.ChangeSubmoduleUrl.URL
|
||||
@@ -692,6 +763,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.CommitDetail.Changes.Count
|
||||
- Text.CommitDetail.Info.Key
|
||||
- Text.CommitDetail.Info.Signer
|
||||
- Text.CommitMessageTextBox.PasteAndReplaceAll
|
||||
- Text.CommitMessageTextBox.SubjectCount
|
||||
- Text.Configure.CommitMessageTemplate.BuiltinVars
|
||||
- Text.Configure.CustomAction.Arguments.Tip
|
||||
@@ -732,6 +804,9 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Diff.Old
|
||||
- Text.Diff.Submodule.Deleted
|
||||
- Text.DirHistories
|
||||
- Text.DirtyState.HasLocalChanges
|
||||
- Text.DirtyState.HasPendingPullOrPush
|
||||
- Text.DirtyState.UpToDate
|
||||
- Text.Discard.IncludeUntracked
|
||||
- Text.ExecuteCustomAction.Target
|
||||
- Text.ExecuteCustomAction.Repository
|
||||
@@ -741,12 +816,14 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Global.SwitchTab
|
||||
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
|
||||
- Text.InteractiveRebase.ReorderTip
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Launcher.Pages
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Merge.Edit
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.AI.ReadApiKeyFromEnv
|
||||
- Text.Preferences.Appearance.UseAutoHideScrollBars
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
@@ -776,6 +853,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ResetWithoutCheckout
|
||||
- Text.ResetWithoutCheckout.MoveTo
|
||||
- Text.ResetWithoutCheckout.Target
|
||||
- Text.ScanRepositories.UseCustomDir
|
||||
- Text.SetSubmoduleBranch
|
||||
- Text.SetSubmoduleBranch.Submodule
|
||||
- Text.SetSubmoduleBranch.Current
|
||||
@@ -819,11 +897,13 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
|
||||
- Text.WorkingCopy.Conflicts.UseMine
|
||||
- Text.WorkingCopy.Conflicts.UseTheirs
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.Worktree.Open
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in uk_UA.axaml</summary>
|
||||
@@ -843,10 +923,16 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Bisect.Skip
|
||||
- Text.Bisect.WaitingForRange
|
||||
- Text.BranchCM.ResetToSelectedCommit
|
||||
- Text.BranchCM.SwitchToWorktree
|
||||
- Text.BranchTree.Ahead
|
||||
- Text.BranchTree.AheadBehind
|
||||
- Text.BranchTree.Behind
|
||||
- Text.BranchTree.InvalidUpstream
|
||||
- Text.BranchTree.Remote
|
||||
- Text.BranchTree.Status
|
||||
- Text.BranchTree.Tracking
|
||||
- Text.BranchTree.URL
|
||||
- Text.BranchTree.Worktree
|
||||
- Text.ChangeSubmoduleUrl
|
||||
- Text.ChangeSubmoduleUrl.Submodule
|
||||
- Text.ChangeSubmoduleUrl.URL
|
||||
@@ -871,6 +957,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.CommitDetail.Changes.Count
|
||||
- Text.CommitDetail.Info.Key
|
||||
- Text.CommitDetail.Info.Signer
|
||||
- Text.CommitMessageTextBox.PasteAndReplaceAll
|
||||
- Text.CommitMessageTextBox.SubjectCount
|
||||
- Text.Configure.CommitMessageTemplate.BuiltinVars
|
||||
- Text.Configure.CustomAction.Arguments.Tip
|
||||
@@ -907,6 +994,9 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Diff.Old
|
||||
- Text.Diff.Submodule.Deleted
|
||||
- Text.DirHistories
|
||||
- Text.DirtyState.HasLocalChanges
|
||||
- Text.DirtyState.HasPendingPullOrPush
|
||||
- Text.DirtyState.UpToDate
|
||||
- Text.Discard.IncludeUntracked
|
||||
- Text.ExecuteCustomAction.Target
|
||||
- Text.ExecuteCustomAction.Repository
|
||||
@@ -916,12 +1006,14 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Global.SwitchTab
|
||||
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
|
||||
- Text.InteractiveRebase.ReorderTip
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Launcher.Pages
|
||||
- Text.Launcher.Workspaces
|
||||
- Text.Merge.Edit
|
||||
- Text.MoveSubmodule
|
||||
- Text.MoveSubmodule.MoveTo
|
||||
- Text.MoveSubmodule.Submodule
|
||||
- Text.Preferences.AI.ReadApiKeyFromEnv
|
||||
- Text.Preferences.Appearance.UseAutoHideScrollBars
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
@@ -951,6 +1043,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ResetWithoutCheckout
|
||||
- Text.ResetWithoutCheckout.MoveTo
|
||||
- Text.ResetWithoutCheckout.Target
|
||||
- Text.ScanRepositories.UseCustomDir
|
||||
- Text.SetSubmoduleBranch
|
||||
- Text.SetSubmoduleBranch.Submodule
|
||||
- Text.SetSubmoduleBranch.Current
|
||||
@@ -989,7 +1082,9 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.WorkingCopy.ClearCommitHistories
|
||||
- Text.WorkingCopy.ClearCommitHistories.Confirm
|
||||
- Text.WorkingCopy.ConfirmCommitWithDetachedHead
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.Worktree.Open
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -170,6 +170,19 @@ namespace SourceGit
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async Task<Models.ConfirmEmptyCommitResult> AskConfirmEmptyCommitAsync(bool hasLocalChanges)
|
||||
{
|
||||
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
|
||||
{
|
||||
var confirm = new Views.ConfirmEmptyCommit();
|
||||
confirm.TxtMessage.Text = Text(hasLocalChanges ? "ConfirmEmptyCommit.WithLocalChanges" : "ConfirmEmptyCommit.NoLocalChanges");
|
||||
confirm.BtnStageAllAndCommit.IsVisible = hasLocalChanges;
|
||||
return await confirm.ShowDialog<Models.ConfirmEmptyCommitResult>(owner);
|
||||
}
|
||||
|
||||
return Models.ConfirmEmptyCommitResult.Cancel;
|
||||
}
|
||||
|
||||
public static void RaiseException(string context, string message)
|
||||
{
|
||||
if (Current is App { _launcher: not null } app)
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Commands
|
||||
{
|
||||
public class Commit : Command
|
||||
{
|
||||
public Commit(string repo, string message, bool signOff, bool amend, bool resetAuthor)
|
||||
public Commit(string repo, string message, bool signOff, bool noVerify, bool amend, bool resetAuthor)
|
||||
{
|
||||
_tmpFile = Path.GetTempFileName();
|
||||
_message = message;
|
||||
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"commit --allow-empty --file={_tmpFile.Quoted()}";
|
||||
|
||||
var builder = new StringBuilder();
|
||||
builder.Append("commit --allow-empty --file=");
|
||||
builder.Append(_tmpFile.Quoted());
|
||||
builder.Append(' ');
|
||||
|
||||
if (signOff)
|
||||
Args += " --signoff";
|
||||
builder.Append("--signoff ");
|
||||
|
||||
if (noVerify)
|
||||
builder.Append("--no-verify ");
|
||||
|
||||
if (amend)
|
||||
Args += resetAuthor ? " --amend --reset-author --no-edit" : " --amend --no-edit";
|
||||
{
|
||||
builder.Append("--amend ");
|
||||
if (resetAuthor)
|
||||
builder.Append("--reset-author ");
|
||||
builder.Append("--no-edit");
|
||||
}
|
||||
|
||||
Args = builder.ToString();
|
||||
}
|
||||
|
||||
public async Task<bool> RunAsync()
|
||||
|
||||
@@ -17,12 +17,15 @@ namespace SourceGit.Commands
|
||||
var tool = Native.OS.GetDiffMergeTool(true);
|
||||
if (tool == null)
|
||||
{
|
||||
App.RaiseException(Context, "Invalid merge tool in preference setting!");
|
||||
App.RaiseException(Context, "Invalid diff/merge tool in preference setting!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tool.Cmd))
|
||||
{
|
||||
if (!CheckGitConfiguration())
|
||||
return;
|
||||
|
||||
Args = $"difftool -g --no-prompt {_option}";
|
||||
}
|
||||
else
|
||||
@@ -41,6 +44,34 @@ namespace SourceGit.Commands
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckGitConfiguration()
|
||||
{
|
||||
var config = new Config(WorkingDirectory).ReadAll();
|
||||
if (config.TryGetValue("diff.guitool", out var guiTool))
|
||||
return CheckCLIBasedTool(guiTool);
|
||||
if (config.TryGetValue("merge.guitool", out var mergeGuiTool))
|
||||
return CheckCLIBasedTool(mergeGuiTool);
|
||||
if (config.TryGetValue("diff.tool", out var diffTool))
|
||||
return CheckCLIBasedTool(diffTool);
|
||||
if (config.TryGetValue("merge.tool", out var mergeTool))
|
||||
return CheckCLIBasedTool(mergeTool);
|
||||
|
||||
App.RaiseException(Context, "Missing git configuration: diff.guitool");
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CheckCLIBasedTool(string tool)
|
||||
{
|
||||
if (tool.StartsWith("vimdiff", StringComparison.Ordinal) ||
|
||||
tool.StartsWith("nvimdiff", StringComparison.Ordinal))
|
||||
{
|
||||
App.RaiseException(Context, $"CLI based diff tool \"{tool}\" is not supported by this app!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Models.DiffOption _option;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,21 @@ namespace SourceGit.Commands
|
||||
{
|
||||
public class IssueTracker : Command
|
||||
{
|
||||
public IssueTracker(string repo, string storage)
|
||||
public IssueTracker(string repo, bool isShared)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
|
||||
if (string.IsNullOrEmpty(storage))
|
||||
if (isShared)
|
||||
{
|
||||
_isStorageFileExists = true;
|
||||
_baseArg = "config --local";
|
||||
var storage = $"{repo}/.issuetracker";
|
||||
_isStorageFileExists = File.Exists(storage);
|
||||
_baseArg = $"config -f {storage.Quoted()}";
|
||||
}
|
||||
else
|
||||
{
|
||||
_isStorageFileExists = File.Exists(storage);
|
||||
_baseArg = $"config -f {storage.Quoted()}";
|
||||
_isStorageFileExists = true;
|
||||
_baseArg = "config --local";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,12 +80,24 @@ namespace SourceGit.Commands
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> RemoveAsync(Models.IssueTracker rule)
|
||||
public async Task<bool> UpdateRegexAsync(Models.IssueTracker rule)
|
||||
{
|
||||
Args = $"{_baseArg} issuetracker.{rule.Name.Quoted()}.regex {rule.RegexString.Quoted()}";
|
||||
return await ExecAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateURLTemplateAsync(Models.IssueTracker rule)
|
||||
{
|
||||
Args = $"{_baseArg} issuetracker.{rule.Name.Quoted()}.url {rule.URLTemplate.Quoted()}";
|
||||
return await ExecAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> RemoveAsync(string name)
|
||||
{
|
||||
if (!_isStorageFileExists)
|
||||
return true;
|
||||
|
||||
Args = $"{_baseArg} --remove-section issuetracker.{rule.Name.Quoted()}";
|
||||
Args = $"{_baseArg} --remove-section issuetracker.{name.Quoted()}";
|
||||
return await ExecAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Commands
|
||||
{
|
||||
@@ -16,13 +17,17 @@ namespace SourceGit.Commands
|
||||
var tool = Native.OS.GetDiffMergeTool(false);
|
||||
if (tool == null)
|
||||
{
|
||||
App.RaiseException(Context, "Invalid merge tool in preference setting!");
|
||||
App.RaiseException(Context, "Invalid diff/merge tool in preference setting!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tool.Cmd))
|
||||
{
|
||||
Args = $"mergetool {_file}";
|
||||
var ok = await CheckGitConfigurationAsync();
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
Args = $"mergetool -g --no-prompt {_file}";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -33,6 +38,28 @@ namespace SourceGit.Commands
|
||||
return await ExecAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<bool> CheckGitConfigurationAsync()
|
||||
{
|
||||
var tool = await new Config(WorkingDirectory).GetAsync("merge.guitool");
|
||||
if (string.IsNullOrEmpty(tool))
|
||||
tool = await new Config(WorkingDirectory).GetAsync("merge.tool");
|
||||
|
||||
if (string.IsNullOrEmpty(tool))
|
||||
{
|
||||
App.RaiseException(Context, "Missing git configuration: merge.guitool");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tool.StartsWith("vimdiff", StringComparison.Ordinal) ||
|
||||
tool.StartsWith("nvimdiff", StringComparison.Ordinal))
|
||||
{
|
||||
App.RaiseException(Context, $"CLI based merge tool \"{tool}\" is not supported by this app!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string _file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace SourceGit.Commands
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = "branch -l --all -v --format=\"%(refname)%00%(committerdate:unix)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)\"";
|
||||
Args = "branch -l --all -v --format=\"%(refname)%00%(committerdate:unix)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)%00%(worktreepath)\"";
|
||||
}
|
||||
|
||||
public async Task<List<Models.Branch>> GetResultAsync()
|
||||
@@ -26,15 +26,16 @@ namespace SourceGit.Commands
|
||||
return branches;
|
||||
|
||||
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
|
||||
var remoteHeads = new Dictionary<string, string>();
|
||||
var mismatched = new HashSet<string>();
|
||||
var remotes = new Dictionary<string, Models.Branch>();
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var b = ParseLine(line);
|
||||
var b = ParseLine(line, mismatched);
|
||||
if (b != null)
|
||||
{
|
||||
branches.Add(b);
|
||||
if (!b.IsLocal)
|
||||
remoteHeads.Add(b.FullName, b.Head);
|
||||
remotes.Add(b.FullName, b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,15 +43,16 @@ namespace SourceGit.Commands
|
||||
{
|
||||
if (b.IsLocal && !string.IsNullOrEmpty(b.Upstream))
|
||||
{
|
||||
if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead))
|
||||
if (remotes.TryGetValue(b.Upstream, out var upstream))
|
||||
{
|
||||
b.IsUpstreamGone = false;
|
||||
b.TrackStatus ??= await new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).GetResultAsync().ConfigureAwait(false);
|
||||
|
||||
if (mismatched.Contains(b.FullName))
|
||||
await new QueryTrackStatus(WorkingDirectory).GetResultAsync(b, upstream).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
b.IsUpstreamGone = true;
|
||||
b.TrackStatus ??= new Models.BranchTrackStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,10 +60,10 @@ namespace SourceGit.Commands
|
||||
return branches;
|
||||
}
|
||||
|
||||
private Models.Branch ParseLine(string line)
|
||||
private Models.Branch ParseLine(string line, HashSet<string> mismatched)
|
||||
{
|
||||
var parts = line.Split('\0');
|
||||
if (parts.Length != 6)
|
||||
if (parts.Length != 7)
|
||||
return null;
|
||||
|
||||
var branch = new Models.Branch();
|
||||
@@ -103,12 +105,13 @@ namespace SourceGit.Commands
|
||||
branch.Upstream = parts[4];
|
||||
branch.IsUpstreamGone = false;
|
||||
|
||||
if (!branch.IsLocal ||
|
||||
string.IsNullOrEmpty(branch.Upstream) ||
|
||||
string.IsNullOrEmpty(parts[5]) ||
|
||||
parts[5].Equals("=", StringComparison.Ordinal))
|
||||
branch.TrackStatus = new Models.BranchTrackStatus();
|
||||
if (branch.IsLocal &&
|
||||
!string.IsNullOrEmpty(branch.Upstream) &&
|
||||
!string.IsNullOrEmpty(parts[5]) &&
|
||||
!parts[5].Equals("=", StringComparison.Ordinal))
|
||||
mismatched.Add(branch.FullName);
|
||||
|
||||
branch.WorktreePath = parts[6];
|
||||
return branch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace SourceGit.Commands
|
||||
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"log --date-order --no-show-signature --decorate=full --format=\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD";
|
||||
Args = $"log --topo-order --right-only --max-parents=1 --no-show-signature --decorate=full --format=\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD";
|
||||
}
|
||||
|
||||
public async Task<List<Models.InteractiveCommit>> GetResultAsync()
|
||||
|
||||
27
src/Commands/QueryGitCommonDir.cs
Normal file
27
src/Commands/QueryGitCommonDir.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Commands
|
||||
{
|
||||
public class QueryGitCommonDir : Command
|
||||
{
|
||||
public QueryGitCommonDir(string workDir)
|
||||
{
|
||||
WorkingDirectory = workDir;
|
||||
Args = "rev-parse --git-common-dir";
|
||||
RaiseError = false;
|
||||
}
|
||||
|
||||
public async Task<string> GetResultAsync()
|
||||
{
|
||||
var rs = await ReadToEndAsync().ConfigureAwait(false);
|
||||
if (!rs.IsSuccess || string.IsNullOrEmpty(rs.StdOut))
|
||||
return string.Empty;
|
||||
|
||||
var dir = rs.StdOut.Trim();
|
||||
if (Path.IsPathRooted(dir))
|
||||
return dir;
|
||||
return Path.GetFullPath(Path.Combine(WorkingDirectory, dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,31 +5,28 @@ namespace SourceGit.Commands
|
||||
{
|
||||
public class QueryTrackStatus : Command
|
||||
{
|
||||
public QueryTrackStatus(string repo, string local, string upstream)
|
||||
public QueryTrackStatus(string repo)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"rev-list --left-right {local}...{upstream}";
|
||||
}
|
||||
|
||||
public async Task<Models.BranchTrackStatus> GetResultAsync()
|
||||
public async Task GetResultAsync(Models.Branch local, Models.Branch remote)
|
||||
{
|
||||
var status = new Models.BranchTrackStatus();
|
||||
Args = $"rev-list --left-right {local.Head}...{remote.Head}";
|
||||
|
||||
var rs = await ReadToEndAsync().ConfigureAwait(false);
|
||||
if (!rs.IsSuccess)
|
||||
return status;
|
||||
return;
|
||||
|
||||
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line[0] == '>')
|
||||
status.Behind.Add(line.Substring(1));
|
||||
local.Behind.Add(line.Substring(1));
|
||||
else
|
||||
status.Ahead.Add(line.Substring(1));
|
||||
local.Ahead.Add(line.Substring(1));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
src/Converters/DirtyStateConverters.cs
Normal file
28
src/Converters/DirtyStateConverters.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace SourceGit.Converters
|
||||
{
|
||||
public static class DirtyStateConverters
|
||||
{
|
||||
public static readonly FuncValueConverter<Models.DirtyState, IBrush> ToBrush =
|
||||
new FuncValueConverter<Models.DirtyState, IBrush>(v =>
|
||||
{
|
||||
if (v.HasFlag(Models.DirtyState.HasLocalChanges))
|
||||
return Brushes.Gray;
|
||||
if (v.HasFlag(Models.DirtyState.HasPendingPullOrPush))
|
||||
return Brushes.RoyalBlue;
|
||||
return Brushes.Transparent;
|
||||
});
|
||||
|
||||
public static readonly FuncValueConverter<Models.DirtyState, string> ToDesc =
|
||||
new FuncValueConverter<Models.DirtyState, string>(v =>
|
||||
{
|
||||
if (v.HasFlag(Models.DirtyState.HasLocalChanges))
|
||||
return " • " + App.Text("DirtyState.HasLocalChanges");
|
||||
if (v.HasFlag(Models.DirtyState.HasPendingPullOrPush))
|
||||
return " • " + App.Text("DirtyState.HasPendingPullOrPush");
|
||||
return " • " + App.Text("DirtyState.UpToDate");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public class BranchTrackStatus
|
||||
{
|
||||
public List<string> Ahead { get; set; } = new List<string>();
|
||||
public List<string> Behind { get; set; } = new List<string>();
|
||||
|
||||
public bool IsVisible => Ahead.Count > 0 || Behind.Count > 0;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Ahead.Count == 0 && Behind.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var track = "";
|
||||
if (Ahead.Count > 0)
|
||||
track += $"{Ahead.Count}↑";
|
||||
if (Behind.Count > 0)
|
||||
track += $" {Behind.Count}↓";
|
||||
return track.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
public enum BranchSortMode
|
||||
{
|
||||
Name = 0,
|
||||
CommitterDate,
|
||||
}
|
||||
|
||||
public partial class Branch
|
||||
public class Branch
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FullName { get; set; }
|
||||
@@ -40,18 +18,34 @@ namespace SourceGit.Models
|
||||
public bool IsCurrent { get; set; }
|
||||
public bool IsDetachedHead { get; set; }
|
||||
public string Upstream { get; set; }
|
||||
public BranchTrackStatus TrackStatus { get; set; }
|
||||
public List<string> Ahead { get; set; } = [];
|
||||
public List<string> Behind { get; set; } = [];
|
||||
public string Remote { get; set; }
|
||||
public bool IsUpstreamGone { get; set; }
|
||||
public string WorktreePath { get; set; }
|
||||
|
||||
public string FriendlyName => IsLocal ? Name : $"{Remote}/{Name}";
|
||||
|
||||
[GeneratedRegex(@"\s+")]
|
||||
private static partial Regex REG_FIX_NAME();
|
||||
|
||||
public static string FixName(string name)
|
||||
public bool IsTrackStatusVisible
|
||||
{
|
||||
return REG_FIX_NAME().Replace(name, "-");
|
||||
get
|
||||
{
|
||||
return Ahead.Count + Behind.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public string TrackStatusDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
var ahead = Ahead.Count;
|
||||
var behind = Behind.Count;
|
||||
if (ahead > 0)
|
||||
return behind > 0 ? $"{ahead}↑ {behind}↓" : $"{ahead}↑";
|
||||
|
||||
return behind > 0 ? $"{behind}↓" : string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasWorktree => !IsCurrent && !string.IsNullOrEmpty(WorktreePath);
|
||||
public string FriendlyName => IsLocal ? Name : $"{Remote}/{Name}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,6 @@ namespace SourceGit.Models
|
||||
ByContent,
|
||||
}
|
||||
|
||||
public enum CommitCheckPassed
|
||||
{
|
||||
None = 0,
|
||||
DetachedHead,
|
||||
Filter,
|
||||
FileCount,
|
||||
}
|
||||
|
||||
public class Commit
|
||||
{
|
||||
// As retrieved by: git mktree </dev/null
|
||||
|
||||
9
src/Models/ConfirmEmptyCommitResult.cs
Normal file
9
src/Models/ConfirmEmptyCommitResult.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public enum ConfirmEmptyCommitResult
|
||||
{
|
||||
Cancel = 0,
|
||||
StageAllAndCommit,
|
||||
CreateEmptyCommit,
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,11 @@ namespace SourceGit.Models
|
||||
{
|
||||
try
|
||||
{
|
||||
_regex = null;
|
||||
_regex = new Regex(_regexString, RegexOptions.Multiline);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore errors.
|
||||
_regex = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,12 @@ namespace SourceGit.Models
|
||||
set => SetProperty(ref _apiKey, value);
|
||||
}
|
||||
|
||||
public bool ReadApiKeyFromEnv
|
||||
{
|
||||
get => _readApiKeyFromEnv;
|
||||
set => SetProperty(ref _readApiKeyFromEnv, value);
|
||||
}
|
||||
|
||||
public string Model
|
||||
{
|
||||
get => _model;
|
||||
@@ -176,15 +182,19 @@ namespace SourceGit.Models
|
||||
|
||||
public async Task ChatAsync(string prompt, string question, CancellationToken cancellation, Action<string> onUpdate)
|
||||
{
|
||||
var server = new Uri(_server);
|
||||
var key = new ApiKeyCredential(_apiKey);
|
||||
var oaiClient = _server.Contains("openai.azure.com/", StringComparison.Ordinal)
|
||||
? new AzureOpenAIClient(server, key)
|
||||
: new OpenAIClient(key, new() { Endpoint = server });
|
||||
var client = oaiClient.GetChatClient(_model);
|
||||
var messages = new List<ChatMessage>();
|
||||
messages.Add(_model.Equals("o1-mini", StringComparison.Ordinal) ? new UserChatMessage(prompt) : new SystemChatMessage(prompt));
|
||||
messages.Add(new UserChatMessage(question));
|
||||
var key = _readApiKeyFromEnv ? Environment.GetEnvironmentVariable(_apiKey) : _apiKey;
|
||||
var endPoint = new Uri(_server);
|
||||
var credential = new ApiKeyCredential(key);
|
||||
var client = _server.Contains("openai.azure.com/", StringComparison.Ordinal)
|
||||
? new AzureOpenAIClient(endPoint, credential)
|
||||
: new OpenAIClient(credential, new() { Endpoint = endPoint });
|
||||
|
||||
var chatClient = client.GetChatClient(_model);
|
||||
var messages = new List<ChatMessage>()
|
||||
{
|
||||
_model.Equals("o1-mini", StringComparison.Ordinal) ? new UserChatMessage(prompt) : new SystemChatMessage(prompt),
|
||||
new UserChatMessage(question),
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
@@ -192,7 +202,7 @@ namespace SourceGit.Models
|
||||
|
||||
if (_streaming)
|
||||
{
|
||||
var updates = client.CompleteChatStreamingAsync(messages, null, cancellation);
|
||||
var updates = chatClient.CompleteChatStreamingAsync(messages, null, cancellation);
|
||||
|
||||
await foreach (var update in updates)
|
||||
{
|
||||
@@ -202,7 +212,7 @@ namespace SourceGit.Models
|
||||
}
|
||||
else
|
||||
{
|
||||
var completion = await client.CompleteChatAsync(messages, null, cancellation);
|
||||
var completion = await chatClient.CompleteChatAsync(messages, null, cancellation);
|
||||
|
||||
if (completion.Value.Content.Count > 0)
|
||||
rsp.Append(completion.Value.Content[0].Text);
|
||||
@@ -220,6 +230,7 @@ namespace SourceGit.Models
|
||||
private string _name;
|
||||
private string _server;
|
||||
private string _apiKey;
|
||||
private bool _readApiKeyFromEnv = false;
|
||||
private string _model;
|
||||
private bool _streaming = true;
|
||||
private string _analyzeDiffPrompt;
|
||||
|
||||
@@ -158,6 +158,12 @@ namespace SourceGit.Models
|
||||
set;
|
||||
} = false;
|
||||
|
||||
public bool NoVerifyOnCommit
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = false;
|
||||
|
||||
public bool IncludeUntrackedWhenStash
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
<StreamGeometry x:Key="Icons.CheckCircled">M512 32C246 32 32 250 32 512s218 480 480 480 480-218 480-480S774 32 512 32zm269 381L496 698c-26 26-61 26-83 0L243 528c-26-26-26-61 0-83s61-26 83 0l128 128 240-240c26-26 61-26 83 0 26 19 26 54 3 80z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Changes">M747 467c29 0 56 4 82 12v-363c0-47-38-84-84-84H125c-47 0-84 38-84 84v707c0 47 38 84 84 84h375a287 287 0 01-43-152c0-160 129-289 289-289zm-531-250h438c19 0 34 15 34 34s-15 34-34 34H216c-19 0-34-15-34-34s15-34 34-34zm0 179h263c19 0 34 15 34 34s-15 34-34 34H216c-19 0-34-15-34-34s15-34 34-34zm131 247h-131c-19 0-34-15-34-34s15-34 34-34h131c19 0 34 15 34 34s-15 34-34 34zM747 521c-130 0-236 106-236 236S617 992 747 992s236-106 236-236S877 521 747 521zm11 386v-65h-130c-12 0-22-10-22-22s10-22 22-22h260l-130 108zm108-192H606l130-108v65h130c12 0 22 10 22 22s-10 22-22 22z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.CherryPick">M529 511c115 0 212 79 239 185h224a62 62 0 017 123l-7 0-224 0a247 247 0 01-479 0H65a62 62 0 01-7-123l7-0h224a247 247 0 01239-185zm0 124a124 124 0 100 247 124 124 0 000-247zm0-618c32 0 58 24 61 55l0 7V206c89 11 165 45 225 103a74 74 0 0122 45l0 9v87a62 62 0 01-123 7l-0-7v-65l-6-4c-43-33-97-51-163-53l-17-0c-74 0-133 18-180 54l-6 4v65a62 62 0 01-55 61l-7 0a62 62 0 01-61-55l-0-7V362c0-20 8-39 23-53 60-58 135-92 224-103V79c0-34 28-62 62-62z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.CircleDown">M512 926c-229 0-414-186-414-414S283 98 512 98s414 186 414 414-186 414-414 414zm0-73c189 0 341-153 341-341S701 171 512 171 171 323 171 512s153 341 341 341zm-6-192L284 439l52-52 171 171 171-171L728 439l-222 222z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Clear">M512 57c251 0 455 204 455 455S763 967 512 967 57 763 57 512 261 57 512 57zm181 274c-11-11-29-11-40 0L512 472 371 331c-11-11-29-11-40 0-11 11-11 29 0 40L471 512 331 653c-11 11-11 29 0 40 11 11 29 11 40 0l141-141 141 141c11 11 29 11 40 0 11-11 11-29 0-40L552 512l141-141c11-11 11-29 0-40z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.ClearNotifications">M591 907A85 85 0 01427 875h114a299 299 0 0050 32zM725 405c130 0 235 105 235 235s-105 235-235 235-235-105-235-235 105-235 235-235zM512 64a43 43 0 0143 43v24c126 17 229 107 264 225A298 298 0 00725 341l-4 0A235 235 0 00512 213l-5 0c-125 4-224 104-228 229l-0 6v167a211 211 0 01-26 101l-4 7-14 23h211a298 298 0 0050 85l-276-0a77 77 0 01-66-39c-13-22-14-50-2-73l2-4 22-36c10-17 16-37 17-57l0-7v-167C193 287 313 153 469 131V107a43 43 0 0139-43zm345 505L654 771a149 149 0 00202-202zM725 491a149 149 0 00-131 220l202-202A149 149 0 00725 491z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Clean">M797 829a49 49 0 1049 49 49 49 0 00-49-49zm147-114A49 49 0 10992 764a49 49 0 00-49-49zM928 861a49 49 0 1049 49A49 49 0 00928 861zm-5-586L992 205 851 64l-71 71a67 67 0 00-94 0l235 235a67 67 0 000-94zm-853 128a32 32 0 00-32 50 1291 1291 0 0075 112L288 552c20 0 25 21 8 37l-93 86a1282 1282 0 00120 114l100-32c19-6 28 15 14 34l-40 55c26 19 53 36 82 53a89 89 0 00115-20 1391 1391 0 00256-485l-188-188s-306 224-595 198z</StreamGeometry>
|
||||
@@ -125,6 +124,7 @@
|
||||
<StreamGeometry x:Key="Icons.Submodules">M416 587c21 0 37 17 37 37v299A37 37 0 01416 960h-299a37 37 0 01-37-37v-299c0-21 17-37 37-37h299zm448 0c21 0 37 17 37 37v299A37 37 0 01864 960h-299a37 37 0 01-37-37v-299c0-21 17-37 37-37h299zM758 91l183 189a37 37 0 010 52l-182 188a37 37 0 01-53 1l-183-189a37 37 0 010-52l182-188a37 37 0 0153-1zM416 139c21 0 37 17 37 37v299A37 37 0 01416 512h-299a37 37 0 01-37-37v-299c0-21 17-37 37-37h299z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Subject">M512 0C230 0 0 230 0 512c0 145 60 282 166 375L90 1024H512c282 0 512-230 512-512S794 0 512 0z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.SyntaxHighlight">M875 128h-725A107 107 0 0043 235v555A107 107 0 00149 896h725a107 107 0 00107-107v-555A107 107 0 00875 128zm-115 640h-183v-58l25-3c15 0 19-8 14-24l-22-61H419l-28 82 39 2V768h-166v-58l18-3c18-2 22-11 26-24l125-363-40-4V256h168l160 448 39 3zM506 340l-72 218h145l-71-218h-2z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Tabs">M1097 372h-460l-146-299H146a73 73 0 00-73 73v731a73 73 0 0073 73h878a73 73 0 0073-73V372zM146 0h390l146 299h488V878a146 146 0 01-146 146H146a146 146 0 01-146-146V146a146 146 0 01146-146zm439 0h195l146 246h-195l-146-246zm244 0h195a146 146 0 01146 146v100h-195l-146-246z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Tag">M177 156c-22 5-33 17-36 37c-10 57-33 258-13 278l445 445c23 23 61 23 84 0l246-246c23-23 23-61 0-84l-445-445C437 120 231 145 177 156zM331 344c-26 26-69 26-95 0c-26-26-26-69 0-95s69-26 95 0C357 276 357 318 331 344z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Tag.Add">M683 537h-144v-142h-142V283H239a44 44 0 00-41 41v171a56 56 0 0014 34l321 321a41 41 0 0058 0l174-174a41 41 0 000-58zm-341-109a41 41 0 110-58a41 41 0 010 58zM649 284V142h-69v142h-142v68h142v142h69v-142h142v-68h-142z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Tags">M996 452 572 28A96 96 0 00504 0H96C43 0 0 43 0 96v408a96 96 0 0028 68l424 424c37 37 98 37 136 0l408-408c37-37 37-98 0-136zM224 320c-53 0-96-43-96-96s43-96 96-96 96 43 96 96-43 96-96 96zm1028 268L844 996c-37 37-98 37-136 0l-1-1L1055 647c34-34 53-79 53-127s-19-93-53-127L663 0h97a96 96 0 0168 28l424 424c37 37 37 98 0 136z</StreamGeometry>
|
||||
@@ -147,7 +147,7 @@
|
||||
<StreamGeometry x:Key="Icons.Window.Maximize">M153 154h768v768h-768v-768zm64 64v640h640v-640h-640z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Window.Restore">M796 231v727H64V231h732zm-82 78H146V880h567V309zM229 66H960v732H796v-82h82V148h-567v82h-82V66z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.WordWrap">M248 221a77 77 0 00-30-21c-18-7-40-10-68-5a224 224 0 00-45 13c-5 2-10 5-15 8l-3 2v68l11-9c10-8 21-14 34-19 13-5 26-7 39-7 12 0 21 3 28 10 6 6 9 16 9 29l-62 9c-14 2-26 6-36 11a80 80 0 00-25 20c-7 8-12 17-15 27-6 21-6 44 1 65a70 70 0 0041 43c10 4 21 6 34 6a80 80 0 0063-28v22h64V298c0-16-2-31-6-44a91 91 0 00-18-33zm-41 121v15c0 8-1 15-4 22a48 48 0 01-24 29 44 44 0 01-33 2 29 29 0 01-10-6 25 25 0 01-6-9 30 30 0 01-2-12c0-5 1-9 2-14a21 21 0 015-9 28 28 0 0110-7 83 83 0 0120-5l42-6zm323-68a144 144 0 00-16-42 87 87 0 00-28-29 75 75 0 00-41-11 73 73 0 00-44 14c-6 5-12 11-17 17V64H326v398h59v-18c8 10 18 17 30 21 6 2 13 3 21 3 16 0 31-4 43-11 12-7 23-18 31-31a147 147 0 0019-46 248 248 0 006-57c0-17-2-33-5-49zm-55 49c0 15-1 28-4 39-2 11-6 20-10 27a41 41 0 01-15 15 37 37 0 01-36 1 44 44 0 01-13-12 59 59 0 01-9-18A76 76 0 01384 352v-33c0-10 1-20 4-29 2-8 6-15 10-22a43 43 0 0115-13 37 37 0 0119-5 35 35 0 0132 18c4 6 7 14 9 23 2 9 3 20 3 31zM154 634a58 58 0 0120-15c14-6 35-7 49-1 7 3 13 6 20 12l21 17V572l-6-4a124 124 0 00-58-14c-20 0-38 4-54 11-16 7-30 17-41 30-12 13-20 29-26 46-6 17-9 36-9 57 0 18 3 36 8 52 6 16 14 30 24 42 10 12 23 21 38 28 15 7 32 10 50 10 15 0 28-2 39-5 11-3 21-8 30-14l5-4v-57l-13 6a26 26 0 01-5 2c-3 1-6 2-8 3-2 1-15 6-15 6-4 2-9 3-14 4a63 63 0 01-38-4 53 53 0 01-20-14 70 70 0 01-13-24 111 111 0 01-5-34c0-13 2-26 5-36 3-10 8-19 14-26zM896 384h-256V320h288c21 1 32 12 32 32v384c0 18-12 32-32 32H504l132 133-45 45-185-185c-16-21-16-25 0-45l185-185L637 576l-128 128H896V384z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Workspace">M128 691H6V38h838v160h-64V102H70v525H128zM973 806H154V250h819v557zm-755-64h691V314H218v429zM365 877h448v64h-448z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Workspace">M0 512M1024 512M512 0M512 1024M128 691H6V38h838v160h-64V102H70v525H128zM973 806H154V250h819v557zm-755-64h691V314H218v429zM365 877h448v64h-448z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Worktree">M853 267H514c-4 0-6-2-9-4l-38-66c-13-21-38-36-64-36H171c-41 0-75 34-75 75v555c0 41 34 75 75 75h683c41 0 75-34 75-75V341c0-41-34-75-75-75zm-683-43h233c4 0 6 2 9 4l38 66c13 21 38 36 64 36H853c6 0 11 4 11 11v75h-704V235c0-6 4-11 11-11zm683 576H171c-6 0-11-4-11-11V480h704V789c0 6-4 11-11 11z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Worktree.Add">M896 96 614 96c-58 0-128-19-179-51C422 38 390 19 358 19L262 19 128 19c-70 0-128 58-128 128l0 736c0 70 58 128 128 128l768 0c70 0 128-58 128-128L1024 224C1024 154 966 96 896 96zM704 685 544 685l0 160c0 19-13 32-32 32s-32-13-32-32l0-160L320 685c-19 0-32-13-32-32 0-19 13-32 32-32l160 0L480 461c0-19 13-32 32-32s32 13 32 32l0 160L704 621c19 0 32 13 32 32C736 666 723 685 704 685zM890 326 102 326 102 250c0-32 32-64 64-64l659 0c38 0 64 32 64 64L890 326z</StreamGeometry>
|
||||
<StreamGeometry x:Key="Icons.Worktrees">M1182 527a91 91 0 00-88-117H92a91 91 0 00-88 117l137 441A80 80 0 00217 1024h752a80 80 0 0076-56zM133 295a31 31 0 0031 31h858a31 31 0 0031-31A93 93 0 00959 203H226a93 93 0 00-94 92zM359 123h467a31 31 0 0031-31A92 92 0 00765 0H421a92 92 0 00-92 92 31 31 0 0031 31z</StreamGeometry>
|
||||
|
||||
@@ -268,7 +268,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stashen & wieder anwenden</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Neuer Branch-Name:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Branch-Name</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Leerzeichen werden durch Bindestriche ersetzt.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Lokalen Branch erstellen</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Überschreibe existierenden Branch</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Tag erstellen...</x:String>
|
||||
@@ -488,8 +487,8 @@
|
||||
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">In Browser öffnen</x:String>
|
||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">FEHLER</x:String>
|
||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">INFO</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Arbeitsplätze</x:String>
|
||||
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Tabs</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Arbeitsplätze</x:String>
|
||||
<x:String x:Key="Text.Merge" xml:space="preserve">Branch mergen</x:String>
|
||||
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">Merge-Nachricht anpassen</x:String>
|
||||
<x:String x:Key="Text.Merge.Into" xml:space="preserve">Ziel-Branch:</x:String>
|
||||
|
||||
@@ -70,12 +70,18 @@
|
||||
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ on ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Reset ${0}$ to ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.SwitchToWorktree" xml:space="preserve">Switch to ${0}$ (worktree)</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Set Tracking Branch...</x:String>
|
||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Compare</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Ahead" xml:space="preserve">{0} commit(s) ahead</x:String>
|
||||
<x:String x:Key="Text.BranchTree.AheadBehind" xml:space="preserve">{0} commit(s) ahead, {1} commit(s) behind</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Behind" xml:space="preserve">{0} commit(s) behind</x:String>
|
||||
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">Invalid</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Remote" xml:space="preserve">REMOTE</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Status" xml:space="preserve">STATUS</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Tracking" xml:space="preserve">TRACKING</x:String>
|
||||
<x:String x:Key="Text.BranchTree.URL" xml:space="preserve">URL</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Worktree" xml:space="preserve">WORKTREE</x:String>
|
||||
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCEL</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Reset to Parent Revision</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Reset to This Revision</x:String>
|
||||
@@ -166,6 +172,7 @@
|
||||
<x:String x:Key="Text.CommitDetail.Info.Signer" xml:space="preserve">Signer:</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Open in Browser</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Description</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.PasteAndReplaceAll" xml:space="preserve">Paste (Replace all)</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectCount" xml:space="preserve">SUBJECT</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Enter commit subject</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Configure</x:String>
|
||||
@@ -263,7 +270,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash & Reapply</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">New Branch Name:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Enter branch name.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Spaces will be replaced with dashes.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Create Local Branch</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Overwrite existing branch</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Create Tag...</x:String>
|
||||
@@ -334,6 +340,9 @@
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Increase Number of Visible Lines</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECT FILE TO VIEW CHANGES</x:String>
|
||||
<x:String x:Key="Text.DirHistories" xml:space="preserve">Dir History</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasLocalChanges" xml:space="preserve">Has Local Changes</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasPendingPullOrPush" xml:space="preserve">Mismatched with Upstream</x:String>
|
||||
<x:String x:Key="Text.DirtyState.UpToDate" xml:space="preserve">Already Up-To-Date</x:String>
|
||||
<x:String x:Key="Text.Discard" xml:space="preserve">Discard Changes</x:String>
|
||||
<x:String x:Key="Text.Discard.All" xml:space="preserve">All local changes in working copy.</x:String>
|
||||
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Changes:</x:String>
|
||||
@@ -483,8 +492,8 @@
|
||||
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Open in Browser</x:String>
|
||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERROR</x:String>
|
||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">NOTICE</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">Tabs</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Workspaces</x:String>
|
||||
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Branch</x:String>
|
||||
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">Customize merge message</x:String>
|
||||
<x:String x:Key="Text.Merge.Into" xml:space="preserve">Into:</x:String>
|
||||
@@ -530,6 +539,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Model</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Entered value is the name to load API key from ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Enable Streaming</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APPEARANCE</x:String>
|
||||
@@ -542,6 +552,7 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">Use monospace font only in text editor</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.Theme" xml:space="preserve">Theme</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.ThemeOverrides" xml:space="preserve">Theme Overrides</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseAutoHideScrollBars" xml:space="preserve">Use auto-hide scrollbars</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseFixedTabWidth" xml:space="preserve">Use fixed tab width in titlebar</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseNativeWindowFrame" xml:space="preserve">Use native window frame</x:String>
|
||||
<x:String x:Key="Text.Preferences.DiffMerge" xml:space="preserve">DIFF/MERGE TOOL</x:String>
|
||||
@@ -726,6 +737,7 @@
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">Patch has been saved successfully!</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">Scan Repositories</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.RootDir" xml:space="preserve">Root Dir:</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.UseCustomDir" xml:space="preserve">Scan another custom directory</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">Check for Updates...</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">New version of this software is available: </x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">Check for updates failed!</x:String>
|
||||
@@ -858,6 +870,7 @@
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUDE UNTRACKED FILES</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">NO RECENT INPUT MESSAGES</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">NO COMMIT TEMPLATES</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoVerify" xml:space="preserve">No-Verify</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">Reset Author</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">STAGED</x:String>
|
||||
@@ -873,6 +886,7 @@
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">WORKTREE</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Copy Path</x:String>
|
||||
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">Lock</x:String>
|
||||
<x:String x:Key="Text.Worktree.Open" xml:space="preserve">Open</x:String>
|
||||
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">Remove</x:String>
|
||||
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">Unlock</x:String>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -74,12 +74,18 @@
|
||||
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ en ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Renombrar ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Resetear ${0}$ a ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.SwitchToWorktree" xml:space="preserve">Cambiar a ${0}$ (worktree)</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Establecer Rama de Seguimiento...</x:String>
|
||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Comparar Ramas</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Ahead" xml:space="preserve">{0} commit(s) adelante</x:String>
|
||||
<x:String x:Key="Text.BranchTree.AheadBehind" xml:space="preserve">{0} commit(s) adelante, {1} commit(s) detrás</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Behind" xml:space="preserve">{0} commit(s) detrás</x:String>
|
||||
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">Inválido</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Remote" xml:space="preserve">REMOTO</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Status" xml:space="preserve">ESTADO</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Tracking" xml:space="preserve">SEGUIMIENTO</x:String>
|
||||
<x:String x:Key="Text.BranchTree.URL" xml:space="preserve">URL</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Worktree" xml:space="preserve">WORKTREE</x:String>
|
||||
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCELAR</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Resetear a Revisión Padre</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Resetear a Esta Revisión</x:String>
|
||||
@@ -170,6 +176,7 @@
|
||||
<x:String x:Key="Text.CommitDetail.Info.Signer" xml:space="preserve">Firmante:</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Abrir en Navegador</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Descripción</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.PasteAndReplaceAll" xml:space="preserve">Pegar (Reemplazar todo)</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectCount" xml:space="preserve">ASUNTO</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Introducir asunto del commit</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">Configurar Repositorio</x:String>
|
||||
@@ -267,7 +274,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash & Reaplicar</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nombre de la Nueva Rama:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Introduzca el nombre de la rama.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Los espacios serán reemplazados con guiones.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Crear Rama Local</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Sobrescribir la rama existente</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Crear Etiqueta...</x:String>
|
||||
@@ -338,6 +344,9 @@
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Aumentar Número de Líneas Visibles</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECCIONA ARCHIVO PARA VER CAMBIOS</x:String>
|
||||
<x:String x:Key="Text.DirHistories" xml:space="preserve">Historial del directorio</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasLocalChanges" xml:space="preserve">Tiene Cambios Locales</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasPendingPullOrPush" xml:space="preserve">No coincide con Upstream</x:String>
|
||||
<x:String x:Key="Text.DirtyState.UpToDate" xml:space="preserve">Ya se encuentra actualizado</x:String>
|
||||
<x:String x:Key="Text.Discard" xml:space="preserve">Descartar Cambios</x:String>
|
||||
<x:String x:Key="Text.Discard.All" xml:space="preserve">Todos los cambios locales en la copia de trabajo.</x:String>
|
||||
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Cambios:</x:String>
|
||||
@@ -487,8 +496,8 @@
|
||||
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Abrir en el Navegador</x:String>
|
||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERROR</x:String>
|
||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">AVISO</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Espacios de trabajo</x:String>
|
||||
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Páginas</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Espacios de trabajo</x:String>
|
||||
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Rama</x:String>
|
||||
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">Personalizar mensaje de merge</x:String>
|
||||
<x:String x:Key="Text.Merge.Into" xml:space="preserve">En:</x:String>
|
||||
@@ -534,6 +543,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI.GenerateSubjectPrompt" xml:space="preserve">Generar Subject Prompt</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modelo</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nombre</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">El valor ingresado es el nombre de la clave API a cargar desde ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Servidor</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Habilitar Transmisión</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APARIENCIA</x:String>
|
||||
@@ -546,6 +556,7 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">Usar solo fuente monospace en el editor de texto</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.Theme" xml:space="preserve">Tema</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.ThemeOverrides" xml:space="preserve">Sobreescritura de temas</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseAutoHideScrollBars" xml:space="preserve">Usar barras de desplazamiento que se oculten automáticamente</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseFixedTabWidth" xml:space="preserve">Usar ancho de pestaña fijo en la barra de título</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseNativeWindowFrame" xml:space="preserve">Usar marco de ventana nativo</x:String>
|
||||
<x:String x:Key="Text.Preferences.DiffMerge" xml:space="preserve">HERRAMIENTA DIFF/MERGE</x:String>
|
||||
@@ -559,6 +570,7 @@
|
||||
<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>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChangesPageByDefault" xml:space="preserve">Mostrar la página `CAMBIOS LOCALES` por defecto</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Mostrar hijos en los detalles de commit</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Mostrar etiquetas en el gráfico de commit</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Longitud de la guía del asunto</x:String>
|
||||
@@ -729,6 +741,7 @@
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">¡El parche se ha guardado exitosamente!</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">Escanear Repositorios</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.RootDir" xml:space="preserve">Directorio Raíz:</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.UseCustomDir" xml:space="preserve">Escanear otro directorio personalizado</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">Buscar Actualizaciones...</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">Nueva versión de este software disponible: </x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">¡Error al buscar actualizaciones!</x:String>
|
||||
@@ -842,6 +855,8 @@
|
||||
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignorar solo este archivo</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Enmendar</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Puedes hacer stage a este archivo ahora.</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories" xml:space="preserve">Limpiar Historial</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ClearCommitHistories.Confirm" xml:space="preserve">¿Estás seguro de querer limpiar todo el historial de los mensajes de commit? Esta acción no se puede deshacer.</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">Plantilla/Historias</x:String>
|
||||
@@ -859,6 +874,7 @@
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUIR ARCHIVOS NO RASTREADOS</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">NO HAY MENSAJES DE ENTRADA RECIENTES</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">NO HAY PLANTILLAS DE COMMIT</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoVerify" xml:space="preserve">Sin verificar</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">Restablecer Autor</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">Firmar</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">STAGED</x:String>
|
||||
@@ -874,6 +890,7 @@
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">WORKTREE</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Copiar Ruta</x:String>
|
||||
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">Bloquear</x:String>
|
||||
<x:String x:Key="Text.Worktree.Open" xml:space="preserve">Abrir</x:String>
|
||||
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">Eliminar</x:String>
|
||||
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">Desbloquear</x:String>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -190,7 +190,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash & Réappliquer</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nom de la nouvelle branche :</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Entrez le nom de la branche.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Les espaces seront remplacés par des tirets.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Créer une branche locale</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Créer un tag...</x:String>
|
||||
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Nouveau tag à :</x:String>
|
||||
|
||||
@@ -267,7 +267,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stasha e Ripristina</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nome Nuovo Branch:</x:String>
|
||||
<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>
|
||||
@@ -487,8 +486,8 @@
|
||||
<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.Launcher.Workspaces" xml:space="preserve">Workspaces</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>
|
||||
|
||||
@@ -189,7 +189,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">スタッシュして再適用</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">新しいブランチの名前:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">ブランチの名前を入力</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">スペースはダッシュに置き換えられます。</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">ローカルブランチを作成</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">タグを作成...</x:String>
|
||||
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">付与されるコミット:</x:String>
|
||||
|
||||
@@ -74,12 +74,18 @@
|
||||
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Переместить ${0}$ на ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Переименовать ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Сбросить ${0}$ к ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.SwitchToWorktree" xml:space="preserve">Переключить на ${0}$ (рабочий каталог)</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Отслеживать ветку...</x:String>
|
||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Сравнение веток</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Ahead" xml:space="preserve">{0} ревизий вперёд</x:String>
|
||||
<x:String x:Key="Text.BranchTree.AheadBehind" xml:space="preserve">{0} ревизий вперёд, {1} ревизий назад</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Behind" xml:space="preserve">{0} ревизий назад</x:String>
|
||||
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">Неверно</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Remote" xml:space="preserve">УДАЛЁННЫЙ</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Status" xml:space="preserve">СОСТОЯНИЕ</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Tracking" xml:space="preserve">ОТСЛЕЖИВАНИЕ</x:String>
|
||||
<x:String x:Key="Text.BranchTree.URL" xml:space="preserve">URL-АДРЕС</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Worktree" xml:space="preserve">РАБОЧИЙ КАТАЛОГ</x:String>
|
||||
<x:String x:Key="Text.Cancel" xml:space="preserve">ОТМЕНА</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Сбросить родительскую ревизию</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Сбросить эту ревизию</x:String>
|
||||
@@ -170,6 +176,7 @@
|
||||
<x:String x:Key="Text.CommitDetail.Info.Signer" xml:space="preserve">Подписант:</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Открыть в браузере</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Описание</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.PasteAndReplaceAll" xml:space="preserve">Вставить (заменить всё)</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectCount" xml:space="preserve">СУБЪЕКТ</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Введите тему ревизии</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">Настройка репозитория</x:String>
|
||||
@@ -267,7 +274,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Отложить и применить повторно</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Имя новой ветки:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Введите имя ветки.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Пробелы будут заменены на тире.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Создать локальную ветку</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">Перезаписать существующую ветку</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Создать метку...</x:String>
|
||||
@@ -338,6 +344,9 @@
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Больше видимых строк</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">ВЫБЕРИТЕ ФАЙЛ ДЛЯ ПРОСМОТРА ИЗМЕНЕНИЙ</x:String>
|
||||
<x:String x:Key="Text.DirHistories" xml:space="preserve">Каталог историй</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasLocalChanges" xml:space="preserve">Есть локальные изменения</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasPendingPullOrPush" xml:space="preserve">Не соответствует с исходящим потоком</x:String>
|
||||
<x:String x:Key="Text.DirtyState.UpToDate" xml:space="preserve">В актуальном состоянии</x:String>
|
||||
<x:String x:Key="Text.Discard" xml:space="preserve">Отклонить изменения</x:String>
|
||||
<x:String x:Key="Text.Discard.All" xml:space="preserve">Все локальные изменения в рабочей копии.</x:String>
|
||||
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Изменения:</x:String>
|
||||
@@ -487,8 +496,8 @@
|
||||
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">Открыть в браузере</x:String>
|
||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ОШИБКА</x:String>
|
||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">УВЕДОМЛЕНИЕ</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Рабочие места</x:String>
|
||||
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">Вкладки</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">Рабочие места</x:String>
|
||||
<x:String x:Key="Text.Merge" xml:space="preserve">Влить ветку</x:String>
|
||||
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">Изменить сообщение слияния</x:String>
|
||||
<x:String x:Key="Text.Merge.Into" xml:space="preserve">В:</x:String>
|
||||
@@ -534,6 +543,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI.GenerateSubjectPrompt" xml:space="preserve">Создать запрос на тему</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Модель</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Имя:</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Введённое значение — это имя для загрузки API-ключа из ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Сервер</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Разрешить потоковую передачу</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">ВИД</x:String>
|
||||
@@ -546,6 +556,7 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">В текстовом редакторе используется только моноширный шрифт</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.Theme" xml:space="preserve">Тема</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.ThemeOverrides" xml:space="preserve">Переопределение темы</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseAutoHideScrollBars" xml:space="preserve">Автоматически скрывать прокрутку</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseFixedTabWidth" xml:space="preserve">Использовать фиксированную ширину табуляции в строке заголовка.</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseNativeWindowFrame" xml:space="preserve">Использовать системное окно</x:String>
|
||||
<x:String x:Key="Text.Preferences.DiffMerge" xml:space="preserve">ИНСТРУМЕНТ СРАВНЕНИЙ/СЛИЯНИЯ</x:String>
|
||||
@@ -730,6 +741,7 @@
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">Заплатка успешно сохранена!</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">Обнаружение репозиториев</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.RootDir" xml:space="preserve">Корневой каталог:</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.UseCustomDir" xml:space="preserve">Сканировать другой пользовательский каталог</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">Проверить обновления...</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">Доступна новая версия программного обеспечения: </x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">Не удалось проверить наличие обновлений!</x:String>
|
||||
@@ -862,6 +874,7 @@
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">НЕТ ПОСЛЕДНИХ ВХОДНЫХ СООБЩЕНИЙ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">НЕТ ШАБЛОНОВ РЕВИЗИИ</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoVerify" xml:space="preserve">Не проверять</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">Сбросить автора</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">Завершение работы</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">СФОРМИРОВАННЫЕ</x:String>
|
||||
@@ -877,6 +890,7 @@
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">РАБОЧИЙ КАТАЛОГ</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Копировать путь</x:String>
|
||||
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">Заблокировать</x:String>
|
||||
<x:String x:Key="Text.Worktree.Open" xml:space="preserve">Открыть</x:String>
|
||||
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">Удалить</x:String>
|
||||
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">Разблокировать</x:String>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -189,7 +189,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">பதுக்கிவை & மீண்டும் இடு</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">புதிய கிளை பெயர்:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">கிளை பெயரை உள்ளிடவும்.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">இடைவெளிகள் கோடுகளால் மாற்றப்படும்.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">உள்ளக கிளையை உருவாக்கு</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">குறிச்சொல்லை உருவாக்கு...</x:String>
|
||||
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">இங்கு புதிய குறிச்சொல்:</x:String>
|
||||
|
||||
@@ -194,7 +194,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Сховати та Застосувати</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Назва нової гілки:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Введіть назву гілки.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">Пробіли будуть замінені на тире.</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Створити локальну гілку</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">Створити тег...</x:String>
|
||||
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Новий тег для:</x:String>
|
||||
|
||||
@@ -74,12 +74,18 @@
|
||||
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 至 ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名 ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">重置 ${0}$ 到 ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.SwitchToWorktree" xml:space="preserve">切换到 ${0}$ (工作树)</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支 ...</x:String>
|
||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比较</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Ahead" xml:space="preserve">领先 {0} 个提交</x:String>
|
||||
<x:String x:Key="Text.BranchTree.AheadBehind" xml:space="preserve">领先 {0} 个提交,落后 {1} 个提交</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Behind" xml:space="preserve">落后 {0} 个提交</x:String>
|
||||
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">不存在</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Remote" xml:space="preserve">远程</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Status" xml:space="preserve">状态</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Tracking" xml:space="preserve">上游分支</x:String>
|
||||
<x:String x:Key="Text.BranchTree.URL" xml:space="preserve">远程地址</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Worktree" xml:space="preserve">工作树</x:String>
|
||||
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">重置文件到上一版本</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重置文件到该版本</x:String>
|
||||
@@ -170,6 +176,7 @@
|
||||
<x:String x:Key="Text.CommitDetail.Info.Signer" xml:space="preserve">签名者 :</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">浏览器中查看</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">详细描述</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.PasteAndReplaceAll" xml:space="preserve">粘贴(替换全部)</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectCount" xml:space="preserve">主题</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">填写提交信息主题</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">仓库配置</x:String>
|
||||
@@ -267,7 +274,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">新分支名 :</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">填写分支名称。</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">空格将被替换为'-'符号</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">创建本地分支</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">允许重置已存在的分支</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">新建标签 ...</x:String>
|
||||
@@ -338,6 +344,9 @@
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可见的行数</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">请选择需要对比的文件</x:String>
|
||||
<x:String x:Key="Text.DirHistories" xml:space="preserve">目录内容变更历史</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasLocalChanges" xml:space="preserve">未提交的本地变更</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasPendingPullOrPush" xml:space="preserve">当前分支HEAD与远端不一致</x:String>
|
||||
<x:String x:Key="Text.DirtyState.UpToDate" xml:space="preserve">已是最新</x:String>
|
||||
<x:String x:Key="Text.Discard" xml:space="preserve">放弃更改确认</x:String>
|
||||
<x:String x:Key="Text.Discard.All" xml:space="preserve">所有本仓库未提交的修改。</x:String>
|
||||
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">变更 :</x:String>
|
||||
@@ -487,8 +496,8 @@
|
||||
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">在浏览器中访问</x:String>
|
||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">出错了</x:String>
|
||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系统提示</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作区列表</x:String>
|
||||
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">页面列表</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作区列表</x:String>
|
||||
<x:String x:Key="Text.Merge" xml:space="preserve">合并分支</x:String>
|
||||
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">编辑合并信息</x:String>
|
||||
<x:String x:Key="Text.Merge.Into" xml:space="preserve">目标分支 :</x:String>
|
||||
@@ -534,6 +543,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI.GenerateSubjectPrompt" xml:space="preserve">Generate Subject Prompt</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">模型</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">配置名称</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">从环境变量(填写环境变量名)中读取API密钥</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">服务地址</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">启用流式输出</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外观配置</x:String>
|
||||
@@ -546,6 +556,7 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">仅在文本编辑器中使用等宽字体</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.Theme" xml:space="preserve">主题</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.ThemeOverrides" xml:space="preserve">主题自定义</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseAutoHideScrollBars" xml:space="preserve">允许滚动条自动隐藏</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseFixedTabWidth" xml:space="preserve">主标签使用固定宽度</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseNativeWindowFrame" xml:space="preserve">使用系统默认窗体样式</x:String>
|
||||
<x:String x:Key="Text.Preferences.DiffMerge" xml:space="preserve">对比/合并工具</x:String>
|
||||
@@ -730,6 +741,7 @@
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">补丁已成功保存!</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">扫描仓库</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.RootDir" xml:space="preserve">根路径 :</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.UseCustomDir" xml:space="preserve">扫描其他自定义路径</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">检测更新...</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">检测到软件有版本更新: </x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">获取最新版本信息失败!</x:String>
|
||||
@@ -862,6 +874,7 @@
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">显示未跟踪文件</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">没有提交信息记录</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">没有可应用的提交信息模板</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoVerify" xml:space="preserve">跳过GIT钩子</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">重置提交者</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">署名</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">已暂存</x:String>
|
||||
@@ -877,6 +890,7 @@
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">本地工作树</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">复制工作树路径</x:String>
|
||||
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">锁定工作树</x:String>
|
||||
<x:String x:Key="Text.Worktree.Open" xml:space="preserve">打开工作树</x:String>
|
||||
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">移除工作树</x:String>
|
||||
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">解除工作树锁定</x:String>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -74,12 +74,18 @@
|
||||
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 分支至 ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名 ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">重設 ${0}$ 至 ${1}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.SwitchToWorktree" xml:space="preserve">切換到 ${0}$ (工作區)</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支...</x:String>
|
||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比較</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Ahead" xml:space="preserve">領先 {0} 次提交</x:String>
|
||||
<x:String x:Key="Text.BranchTree.AheadBehind" xml:space="preserve">領先 {0} 次提交, 落後 {0} 次提交</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Behind" xml:space="preserve">落後 {0} 次提交</x:String>
|
||||
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">無效</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Remote" xml:space="preserve">遠端</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Status" xml:space="preserve">狀態</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Tracking" xml:space="preserve">上游分支</x:String>
|
||||
<x:String x:Key="Text.BranchTree.URL" xml:space="preserve">遠端網址</x:String>
|
||||
<x:String x:Key="Text.BranchTree.Worktree" xml:space="preserve">工作區</x:String>
|
||||
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">重設檔案到上一版本</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">重設檔案為此版本</x:String>
|
||||
@@ -170,6 +176,7 @@
|
||||
<x:String x:Key="Text.CommitDetail.Info.Signer" xml:space="preserve">簽署人:</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">在瀏覽器中檢視</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">詳細描述</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.PasteAndReplaceAll" xml:space="preserve">粘貼(替換所有內容)</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectCount" xml:space="preserve">標題</x:String>
|
||||
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">填寫提交訊息標題</x:String>
|
||||
<x:String x:Key="Text.Configure" xml:space="preserve">存放庫設定</x:String>
|
||||
@@ -267,7 +274,6 @@
|
||||
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">擱置變更並自動復原</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">新分支名稱:</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">輸入分支名稱。</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Name.WarnSpace" xml:space="preserve">空格將以英文破折號取代</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">建立本機分支</x:String>
|
||||
<x:String x:Key="Text.CreateBranch.OverwriteExisting" xml:space="preserve">允許覆寫現有分支</x:String>
|
||||
<x:String x:Key="Text.CreateTag" xml:space="preserve">新增標籤...</x:String>
|
||||
@@ -338,6 +344,9 @@
|
||||
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">增加可見的行數</x:String>
|
||||
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">請選擇需要對比的檔案</x:String>
|
||||
<x:String x:Key="Text.DirHistories" xml:space="preserve">目錄内容變更歷史</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasLocalChanges" xml:space="preserve">未提交的本地變更</x:String>
|
||||
<x:String x:Key="Text.DirtyState.HasPendingPullOrPush" xml:space="preserve">當前分支的 HEAD 與上游不匹配</x:String>
|
||||
<x:String x:Key="Text.DirtyState.UpToDate" xml:space="preserve">已更新至最新</x:String>
|
||||
<x:String x:Key="Text.Discard" xml:space="preserve">捨棄變更</x:String>
|
||||
<x:String x:Key="Text.Discard.All" xml:space="preserve">所有本機未提交的變更。</x:String>
|
||||
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">變更:</x:String>
|
||||
@@ -487,8 +496,8 @@
|
||||
<x:String x:Key="Text.IssueLinkCM.OpenInBrowser" xml:space="preserve">在瀏覽器中開啟連結</x:String>
|
||||
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">發生錯誤</x:String>
|
||||
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">系統提示</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作區列表</x:String>
|
||||
<x:String x:Key="Text.Launcher.Pages" xml:space="preserve">頁面列表</x:String>
|
||||
<x:String x:Key="Text.Launcher.Workspaces" xml:space="preserve">工作區列表</x:String>
|
||||
<x:String x:Key="Text.Merge" xml:space="preserve">合併分支</x:String>
|
||||
<x:String x:Key="Text.Merge.Edit" xml:space="preserve">編輯合併訊息</x:String>
|
||||
<x:String x:Key="Text.Merge.Into" xml:space="preserve">目標分支:</x:String>
|
||||
@@ -534,6 +543,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI.GenerateSubjectPrompt" xml:space="preserve">產生提交訊息提示詞</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">模型</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">名稱</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">從環境變數中(輸入為環境變數名稱)載入金鑰</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">伺服器</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">啟用串流輸出</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外觀設定</x:String>
|
||||
@@ -546,6 +556,7 @@
|
||||
<x:String x:Key="Text.Preferences.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">僅在文字編輯器中使用等寬字型</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.Theme" xml:space="preserve">佈景主題</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.ThemeOverrides" xml:space="preserve">自訂主題</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseAutoHideScrollBars" xml:space="preserve">允許滾動條自動隱藏</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseFixedTabWidth" xml:space="preserve">使用固定寬度的分頁標籤</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.UseNativeWindowFrame" xml:space="preserve">使用系統原生預設視窗樣式</x:String>
|
||||
<x:String x:Key="Text.Preferences.DiffMerge" xml:space="preserve">對比/合併工具</x:String>
|
||||
@@ -730,6 +741,7 @@
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">修補檔已成功儲存!</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">掃描存放庫</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.RootDir" xml:space="preserve">頂層目錄:</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.UseCustomDir" xml:space="preserve">掃描其他自訂目錄</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">檢查更新...</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">軟體有版本更新:</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">取得最新版本資訊失敗!</x:String>
|
||||
@@ -862,6 +874,7 @@
|
||||
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">顯示未追蹤檔案</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">沒有提交訊息記錄</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">沒有可套用的提交訊息範本</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.NoVerify" xml:space="preserve">繞過 HOOKS 檢查</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.ResetAuthor" xml:space="preserve">重設作者</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.SignOff" xml:space="preserve">署名</x:String>
|
||||
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">已暫存</x:String>
|
||||
@@ -877,6 +890,7 @@
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">本機工作區</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">複製工作區路徑</x:String>
|
||||
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">鎖定工作區</x:String>
|
||||
<x:String x:Key="Text.Worktree.Open" xml:space="preserve">開啟工作區</x:String>
|
||||
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">移除工作區</x:String>
|
||||
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">解除鎖定工作區</x:String>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<x:Double x:Key="ScrollBarSize">12</x:Double>
|
||||
</Style.Resources>
|
||||
|
||||
<Setter Property="AllowAutoHide" Value="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseAutoHideScrollBars, Mode=OneWay}"/>
|
||||
<Setter Property="ShowDelay" Value="0:0:0.1"/>
|
||||
<Setter Property="HideDelay" Value="0:0:0.2"/>
|
||||
</Style>
|
||||
@@ -306,7 +307,6 @@
|
||||
<Style Selector="TextBlock.group_header_label">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG2}"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Margin" Value="10,0,0,0"/>
|
||||
</Style>
|
||||
<Style Selector="TextBlock.table_header">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch);
|
||||
if (b != null && _repo.HistoriesFilterMode == Models.FilterMode.Included)
|
||||
_repo.SetBranchFilterMode(b, Models.FilterMode.Included, true, false);
|
||||
_repo.SetBranchFilterMode(b, Models.FilterMode.Included, false, false);
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace SourceGit.ViewModels
|
||||
log.Complete();
|
||||
|
||||
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
|
||||
_repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, true, false);
|
||||
_repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, false, false);
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
|
||||
@@ -291,7 +291,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
_changes = null;
|
||||
_changes = [];
|
||||
_requestingRevisionFiles = false;
|
||||
_revisionFiles = null;
|
||||
|
||||
@@ -426,9 +426,6 @@ namespace SourceGit.ViewModels
|
||||
|
||||
private void RefreshVisibleChanges()
|
||||
{
|
||||
if (_changes == null)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrEmpty(_searchChangeFilter))
|
||||
{
|
||||
VisibleChanges = _changes;
|
||||
@@ -578,8 +575,8 @@ namespace SourceGit.ViewModels
|
||||
private Models.CommitFullMessage _fullMessage = null;
|
||||
private Models.CommitSignInfo _signInfo = null;
|
||||
private List<string> _children = null;
|
||||
private List<Models.Change> _changes = null;
|
||||
private List<Models.Change> _visibleChanges = null;
|
||||
private List<Models.Change> _changes = [];
|
||||
private List<Models.Change> _visibleChanges = [];
|
||||
private List<Models.Change> _selectedChanges = null;
|
||||
private string _searchChangeFilter = string.Empty;
|
||||
private DiffContext _diffContext = null;
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class ConfirmEmptyCommit
|
||||
{
|
||||
public bool HasLocalChanges
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Message
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public ConfirmEmptyCommit(WorkingCopy wc, bool autoPush, int unstagedCount)
|
||||
{
|
||||
_wc = wc;
|
||||
_autoPush = autoPush;
|
||||
HasLocalChanges = unstagedCount > 0;
|
||||
Message = App.Text(HasLocalChanges ? "ConfirmEmptyCommit.WithLocalChanges" : "ConfirmEmptyCommit.NoLocalChanges");
|
||||
}
|
||||
|
||||
public async Task StageAllThenCommitAsync()
|
||||
{
|
||||
await _wc.CommitAsync(true, _autoPush, Models.CommitCheckPassed.FileCount);
|
||||
}
|
||||
|
||||
public async Task ContinueAsync()
|
||||
{
|
||||
await _wc.CommitAsync(false, _autoPush, Models.CommitCheckPassed.FileCount);
|
||||
}
|
||||
|
||||
private readonly WorkingCopy _wc;
|
||||
private readonly bool _autoPush;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace SourceGit.ViewModels
|
||||
public class CreateBranch : Popup
|
||||
{
|
||||
[Required(ErrorMessage = "Branch name is required!")]
|
||||
[RegularExpression(@"^[\w \-/\.#\+]+$", ErrorMessage = "Bad branch name format!")]
|
||||
[RegularExpression(@"^[\w\-/\.#\+]+$", ErrorMessage = "Bad branch name format!")]
|
||||
[CustomValidation(typeof(CreateBranch), nameof(ValidateBranchName))]
|
||||
public string Name
|
||||
{
|
||||
@@ -101,10 +101,9 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (!creator._allowOverwrite)
|
||||
{
|
||||
var fixedName = Models.Branch.FixName(name);
|
||||
foreach (var b in creator._repo.Branches)
|
||||
{
|
||||
if (b.FriendlyName.Equals(fixedName, StringComparison.Ordinal))
|
||||
if (b.FriendlyName.Equals(name, StringComparison.Ordinal))
|
||||
return new ValidationResult("A branch with same name already exists!");
|
||||
}
|
||||
}
|
||||
@@ -119,8 +118,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
||||
var fixedName = Models.Branch.FixName(_name);
|
||||
var log = _repo.CreateLog($"Create Branch '{fixedName}'");
|
||||
var log = _repo.CreateLog($"Create Branch '{_name}'");
|
||||
Use(log);
|
||||
|
||||
if (CheckoutAfterCreated)
|
||||
@@ -166,7 +164,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
succ = await new Commands.Checkout(_repo.FullPath)
|
||||
.Use(log)
|
||||
.BranchAsync(fixedName, _baseOnRevision, DiscardLocalChanges, _allowOverwrite);
|
||||
.BranchAsync(_name, _baseOnRevision, DiscardLocalChanges, _allowOverwrite);
|
||||
|
||||
if (succ)
|
||||
{
|
||||
@@ -187,7 +185,7 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
succ = await new Commands.Branch(_repo.FullPath, fixedName)
|
||||
succ = await new Commands.Branch(_repo.FullPath, _name)
|
||||
.Use(log)
|
||||
.CreateAsync(_baseOnRevision, _allowOverwrite);
|
||||
}
|
||||
@@ -205,7 +203,7 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
|
||||
if (autoSetUpstream)
|
||||
await new Commands.Branch(_repo.FullPath, fixedName)
|
||||
await new Commands.Branch(_repo.FullPath, _name)
|
||||
.Use(log)
|
||||
.SetUpstreamAsync(basedOn);
|
||||
}
|
||||
@@ -214,7 +212,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (succ && CheckoutAfterCreated)
|
||||
{
|
||||
var fake = new Models.Branch() { IsLocal = true, FullName = $"refs/heads/{fixedName}" };
|
||||
var fake = new Models.Branch() { IsLocal = true, FullName = $"refs/heads/{_name}" };
|
||||
if (BasedOn is Models.Branch { IsLocal: false } based)
|
||||
fake.Upstream = based.FullName;
|
||||
|
||||
@@ -223,8 +221,7 @@ namespace SourceGit.ViewModels
|
||||
_repo.Settings.ExpandedBranchNodesInSideBar.Add(fake.FullName.Substring(0, folderEndIdx));
|
||||
|
||||
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
|
||||
_repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false);
|
||||
|
||||
_repo.SetBranchFilterMode(fake, Models.FilterMode.Included, false, false);
|
||||
}
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _viewContent, value);
|
||||
}
|
||||
|
||||
public FileHistoriesSingleRevision(Repository repo, string file, Models.Commit revision, bool prevIsDiffMode)
|
||||
public FileHistoriesSingleRevision(string repo, string file, Models.Commit revision, bool prevIsDiffMode)
|
||||
{
|
||||
_repo = repo;
|
||||
_file = file;
|
||||
@@ -49,7 +49,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public async Task<bool> ResetToSelectedRevisionAsync()
|
||||
{
|
||||
return await new Commands.Checkout(_repo.FullPath)
|
||||
return await new Commands.Checkout(_repo)
|
||||
.FileWithRevisionAsync(_file, $"{_revision.SHA}")
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
@@ -59,13 +59,13 @@ namespace SourceGit.ViewModels
|
||||
if (_viewContent is not FileHistoriesRevisionFile { CanOpenWithDefaultEditor: true })
|
||||
return;
|
||||
|
||||
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, _file);
|
||||
var fullPath = Native.OS.GetAbsPath(_repo, _file);
|
||||
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
|
||||
var fileExt = Path.GetExtension(fullPath) ?? "";
|
||||
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_revision.SHA.AsSpan(0, 10)}{fileExt}");
|
||||
|
||||
await Commands.SaveRevisionFile
|
||||
.RunAsync(_repo.FullPath, _revision.SHA, _file, tmpFile)
|
||||
.RunAsync(_repo, _revision.SHA, _file, tmpFile)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Native.OS.OpenWithDefaultEditor(tmpFile);
|
||||
@@ -81,7 +81,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var objs = await new Commands.QueryRevisionObjects(_repo.FullPath, _revision.SHA, _file)
|
||||
var objs = await new Commands.QueryRevisionObjects(_repo, _revision.SHA, _file)
|
||||
.GetResultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@@ -100,23 +100,23 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (obj.Type == Models.ObjectType.Blob)
|
||||
{
|
||||
var isBinary = await new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).GetResultAsync().ConfigureAwait(false);
|
||||
var isBinary = await new Commands.IsBinary(_repo, _revision.SHA, _file).GetResultAsync().ConfigureAwait(false);
|
||||
if (isBinary)
|
||||
{
|
||||
var imgDecoder = ImageSource.GetDecoder(_file);
|
||||
if (imgDecoder != Models.ImageDecoder.None)
|
||||
{
|
||||
var source = await ImageSource.FromRevisionAsync(_repo.FullPath, _revision.SHA, _file, imgDecoder).ConfigureAwait(false);
|
||||
var source = await ImageSource.FromRevisionAsync(_repo, _revision.SHA, _file, imgDecoder).ConfigureAwait(false);
|
||||
var image = new Models.RevisionImageFile(_file, source.Bitmap, source.Size);
|
||||
return new FileHistoriesRevisionFile(_file, image, true);
|
||||
}
|
||||
|
||||
var size = await new Commands.QueryFileSize(_repo.FullPath, _file, _revision.SHA).GetResultAsync().ConfigureAwait(false);
|
||||
var size = await new Commands.QueryFileSize(_repo, _file, _revision.SHA).GetResultAsync().ConfigureAwait(false);
|
||||
var binaryFile = new Models.RevisionBinaryFile() { Size = size };
|
||||
return new FileHistoriesRevisionFile(_file, binaryFile, true);
|
||||
}
|
||||
|
||||
var contentStream = await Commands.QueryFileContent.RunAsync(_repo.FullPath, _revision.SHA, _file).ConfigureAwait(false);
|
||||
var contentStream = await Commands.QueryFileContent.RunAsync(_repo, _revision.SHA, _file).ConfigureAwait(false);
|
||||
var content = await new StreamReader(contentStream).ReadToEndAsync();
|
||||
var lfs = Models.LFSObject.Parse(content);
|
||||
if (lfs != null)
|
||||
@@ -124,7 +124,7 @@ namespace SourceGit.ViewModels
|
||||
var imgDecoder = ImageSource.GetDecoder(_file);
|
||||
if (imgDecoder != Models.ImageDecoder.None)
|
||||
{
|
||||
var combined = new RevisionLFSImage(_repo.FullPath, _file, lfs, imgDecoder);
|
||||
var combined = new RevisionLFSImage(_repo, _file, lfs, imgDecoder);
|
||||
return new FileHistoriesRevisionFile(_file, combined, true);
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (obj.Type == Models.ObjectType.Commit)
|
||||
{
|
||||
var submoduleRoot = Path.Combine(_repo.FullPath, _file);
|
||||
var submoduleRoot = Path.Combine(_repo, _file);
|
||||
var commit = await new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).GetResultAsync().ConfigureAwait(false);
|
||||
var message = commit != null ? await new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).GetResultAsync().ConfigureAwait(false) : null;
|
||||
var module = new Models.RevisionSubmodule()
|
||||
@@ -156,10 +156,10 @@ namespace SourceGit.ViewModels
|
||||
private void SetViewContentAsDiff()
|
||||
{
|
||||
var option = new Models.DiffOption(_revision, _file);
|
||||
ViewContent = new DiffContext(_repo.FullPath, option, _viewContent as DiffContext);
|
||||
ViewContent = new DiffContext(_repo, option, _viewContent as DiffContext);
|
||||
}
|
||||
|
||||
private Repository _repo = null;
|
||||
private string _repo = null;
|
||||
private string _file = null;
|
||||
private Models.Commit _revision = null;
|
||||
private bool _isDiffMode = false;
|
||||
@@ -186,7 +186,7 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _viewContent, value);
|
||||
}
|
||||
|
||||
public FileHistoriesCompareRevisions(Repository repo, string file, Models.Commit start, Models.Commit end)
|
||||
public FileHistoriesCompareRevisions(string repo, string file, Models.Commit start, Models.Commit end)
|
||||
{
|
||||
_repo = repo;
|
||||
_file = file;
|
||||
@@ -204,7 +204,7 @@ namespace SourceGit.ViewModels
|
||||
public async Task<bool> SaveAsPatch(string saveTo)
|
||||
{
|
||||
return await Commands.SaveChangesAsPatch
|
||||
.ProcessRevisionCompareChangesAsync(_repo.FullPath, _changes, _startPoint.SHA, _endPoint.SHA, saveTo)
|
||||
.ProcessRevisionCompareChangesAsync(_repo, _changes, _startPoint.SHA, _endPoint.SHA, saveTo)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
_changes = await new Commands.CompareRevisions(_repo.FullPath, _startPoint.SHA, _endPoint.SHA, _file).ReadAsync().ConfigureAwait(false);
|
||||
_changes = await new Commands.CompareRevisions(_repo, _startPoint.SHA, _endPoint.SHA, _file).ReadAsync().ConfigureAwait(false);
|
||||
if (_changes.Count == 0)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => ViewContent = null);
|
||||
@@ -220,12 +220,12 @@ namespace SourceGit.ViewModels
|
||||
else
|
||||
{
|
||||
var option = new Models.DiffOption(_startPoint.SHA, _endPoint.SHA, _changes[0]);
|
||||
Dispatcher.UIThread.Post(() => ViewContent = new DiffContext(_repo.FullPath, option, _viewContent));
|
||||
Dispatcher.UIThread.Post(() => ViewContent = new DiffContext(_repo, option, _viewContent));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Repository _repo = null;
|
||||
private string _repo = null;
|
||||
private string _file = null;
|
||||
private Models.Commit _startPoint = null;
|
||||
private Models.Commit _endPoint = null;
|
||||
@@ -264,7 +264,7 @@ namespace SourceGit.ViewModels
|
||||
private set => SetProperty(ref _viewContent, value);
|
||||
}
|
||||
|
||||
public FileHistories(Repository repo, string file, string commit = null)
|
||||
public FileHistories(string repo, string file, string commit = null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(commit))
|
||||
Title = $"{file} @ {commit}";
|
||||
@@ -282,7 +282,7 @@ namespace SourceGit.ViewModels
|
||||
.Append(" -- ")
|
||||
.Append(file.Quoted());
|
||||
|
||||
var commits = await new Commands.QueryCommits(_repo.FullPath, argsBuilder.ToString(), false)
|
||||
var commits = await new Commands.QueryCommits(_repo, argsBuilder.ToString(), false)
|
||||
.GetResultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@@ -311,7 +311,18 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void NavigateToCommit(Models.Commit commit)
|
||||
{
|
||||
_repo.NavigateToCommit(commit.SHA);
|
||||
var launcher = App.GetLauncher();
|
||||
if (launcher != null)
|
||||
{
|
||||
foreach (var page in launcher.Pages)
|
||||
{
|
||||
if (page.Data is Repository repo && repo.FullPath.Equals(_repo, StringComparison.Ordinal))
|
||||
{
|
||||
repo.NavigateToCommit(commit.SHA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetCommitFullMessage(Models.Commit commit)
|
||||
@@ -320,12 +331,12 @@ namespace SourceGit.ViewModels
|
||||
if (_fullCommitMessages.TryGetValue(sha, out var msg))
|
||||
return msg;
|
||||
|
||||
msg = new Commands.QueryCommitFullMessage(_repo.FullPath, sha).GetResult();
|
||||
msg = new Commands.QueryCommitFullMessage(_repo, sha).GetResult();
|
||||
_fullCommitMessages[sha] = msg;
|
||||
return msg;
|
||||
}
|
||||
|
||||
private readonly Repository _repo = null;
|
||||
private readonly string _repo = null;
|
||||
private bool _isLoading = true;
|
||||
private bool _prevIsDiffMode = true;
|
||||
private List<Models.Commit> _commits = null;
|
||||
|
||||
@@ -219,12 +219,12 @@ namespace SourceGit.ViewModels
|
||||
return false;
|
||||
|
||||
var lb = _repo.Branches.Find(x => x.IsLocal && x.Upstream == rb.FullName);
|
||||
if (lb == null || lb.TrackStatus.Ahead.Count > 0)
|
||||
if (lb == null || lb.Ahead.Count > 0)
|
||||
{
|
||||
if (_repo.CanCreatePopup())
|
||||
_repo.ShowPopup(new CreateBranch(_repo, rb));
|
||||
}
|
||||
else if (lb.TrackStatus.Behind.Count > 0)
|
||||
else if (lb.Behind.Count > 0)
|
||||
{
|
||||
if (_repo.CanCreatePopup())
|
||||
_repo.ShowPopup(new CheckoutAndFastForward(_repo, lb, rb));
|
||||
@@ -265,7 +265,7 @@ namespace SourceGit.ViewModels
|
||||
continue;
|
||||
|
||||
var lb = _repo.Branches.Find(x => x.IsLocal && x.Upstream == rb.FullName);
|
||||
if (lb is { TrackStatus.Ahead.Count: 0 })
|
||||
if (lb.Ahead.Count == 0)
|
||||
{
|
||||
if (_repo.CanCreatePopup())
|
||||
_repo.ShowPopup(new CheckoutAndFastForward(_repo, lb, rb));
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform;
|
||||
@@ -52,7 +53,12 @@ namespace SourceGit.ViewModels
|
||||
if (string.IsNullOrEmpty(lfs.Oid) || lfs.Size == 0)
|
||||
return new ImageSource(null, 0);
|
||||
|
||||
var stream = await Commands.QueryFileContent.FromLFSAsync(repo, lfs.Oid, lfs.Size).ConfigureAwait(false);
|
||||
var commonDir = await new Commands.QueryGitCommonDir(repo).GetResultAsync().ConfigureAwait(false);
|
||||
var localFile = Path.Combine(commonDir, "lfs", "objects", lfs.Oid.Substring(0, 2), lfs.Oid.Substring(2, 2), lfs.Oid);
|
||||
if (File.Exists(localFile))
|
||||
return await FromFileAsync(localFile, decoder).ConfigureAwait(false);
|
||||
|
||||
await using var stream = await Commands.QueryFileContent.FromLFSAsync(repo, lfs.Oid, lfs.Size).ConfigureAwait(false);
|
||||
return await Task.Run(() => LoadFromStream(stream, decoder)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,28 +107,25 @@ namespace SourceGit.ViewModels
|
||||
get;
|
||||
} = [];
|
||||
|
||||
public InteractiveRebaseItem SelectedItem
|
||||
public InteractiveRebaseItem PreSelected
|
||||
{
|
||||
get => _selectedItem;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedItem, value))
|
||||
DetailContext.Commit = value?.Commit;
|
||||
}
|
||||
get => _preSelected;
|
||||
private set => SetProperty(ref _preSelected, value);
|
||||
}
|
||||
|
||||
public CommitDetail DetailContext
|
||||
public object Detail
|
||||
{
|
||||
get;
|
||||
get => _detail;
|
||||
private set => SetProperty(ref _detail, value);
|
||||
}
|
||||
|
||||
public InteractiveRebase(Repository repo, Models.Commit on, InteractiveRebasePrefill prefill = null)
|
||||
{
|
||||
_repo = repo;
|
||||
_commitDetail = new CommitDetail(repo, false);
|
||||
Current = repo.CurrentBranch;
|
||||
On = on;
|
||||
IsLoading = true;
|
||||
DetailContext = new CommitDetail(repo, false);
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
@@ -157,12 +154,29 @@ namespace SourceGit.ViewModels
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Items.AddRange(list);
|
||||
SelectedItem = selected;
|
||||
PreSelected = selected;
|
||||
IsLoading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void SelectCommits(List<InteractiveRebaseItem> items)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
{
|
||||
Detail = null;
|
||||
}
|
||||
else if (items.Count == 1)
|
||||
{
|
||||
_commitDetail.Commit = items[0].Commit;
|
||||
Detail = _commitDetail;
|
||||
}
|
||||
else
|
||||
{
|
||||
Detail = new Models.Count(items.Count);
|
||||
}
|
||||
}
|
||||
|
||||
public void MoveItemUp(InteractiveRebaseItem item)
|
||||
{
|
||||
var idx = Items.IndexOf(item);
|
||||
@@ -171,7 +185,6 @@ namespace SourceGit.ViewModels
|
||||
var prev = Items[idx - 1];
|
||||
Items.RemoveAt(idx - 1);
|
||||
Items.Insert(idx, prev);
|
||||
SelectedItem = item;
|
||||
UpdateItems();
|
||||
}
|
||||
}
|
||||
@@ -184,20 +197,26 @@ namespace SourceGit.ViewModels
|
||||
var next = Items[idx + 1];
|
||||
Items.RemoveAt(idx + 1);
|
||||
Items.Insert(idx, next);
|
||||
SelectedItem = item;
|
||||
UpdateItems();
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeAction(InteractiveRebaseItem item, Models.InteractiveRebaseAction action)
|
||||
public void ChangeAction(List<InteractiveRebaseItem> selected, Models.InteractiveRebaseAction action)
|
||||
{
|
||||
if (!item.CanSquashOrFixup)
|
||||
if (action == Models.InteractiveRebaseAction.Squash || action == Models.InteractiveRebaseAction.Fixup)
|
||||
{
|
||||
if (action == Models.InteractiveRebaseAction.Squash || action == Models.InteractiveRebaseAction.Fixup)
|
||||
return;
|
||||
foreach (var item in selected)
|
||||
{
|
||||
if (item.CanSquashOrFixup)
|
||||
item.Action = action;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in selected)
|
||||
item.Action = action;
|
||||
}
|
||||
|
||||
item.Action = action;
|
||||
UpdateItems();
|
||||
}
|
||||
|
||||
@@ -257,6 +276,8 @@ namespace SourceGit.ViewModels
|
||||
|
||||
private Repository _repo = null;
|
||||
private bool _isLoading = false;
|
||||
private InteractiveRebaseItem _selectedItem = null;
|
||||
private InteractiveRebaseItem _preSelected = null;
|
||||
private object _detail = null;
|
||||
private CommitDetail _commitDetail = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Media;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
@@ -20,10 +21,10 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _data, value);
|
||||
}
|
||||
|
||||
public IBrush DirtyBrush
|
||||
public Models.DirtyState DirtyState
|
||||
{
|
||||
get => _dirtyBrush;
|
||||
private set => SetProperty(ref _dirtyBrush, value);
|
||||
get => _dirtyState;
|
||||
private set => SetProperty(ref _dirtyState, value);
|
||||
}
|
||||
|
||||
public Popup Popup
|
||||
@@ -66,22 +67,18 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void ChangeDirtyState(Models.DirtyState flag, bool remove)
|
||||
{
|
||||
var state = _dirtyState;
|
||||
if (remove)
|
||||
{
|
||||
if (_dirtyState.HasFlag(flag))
|
||||
_dirtyState -= flag;
|
||||
if (state.HasFlag(flag))
|
||||
state -= flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dirtyState |= flag;
|
||||
state |= flag;
|
||||
}
|
||||
|
||||
if (_dirtyState.HasFlag(Models.DirtyState.HasLocalChanges))
|
||||
DirtyBrush = Brushes.Gray;
|
||||
else if (_dirtyState.HasFlag(Models.DirtyState.HasPendingPullOrPush))
|
||||
DirtyBrush = Brushes.RoyalBlue;
|
||||
else
|
||||
DirtyBrush = null;
|
||||
DirtyState = state;
|
||||
}
|
||||
|
||||
public bool CanCreatePopup()
|
||||
@@ -127,7 +124,6 @@ namespace SourceGit.ViewModels
|
||||
|
||||
private RepositoryNode _node = null;
|
||||
private object _data = null;
|
||||
private IBrush _dirtyBrush = null;
|
||||
private Models.DirtyState _dirtyState = Models.DirtyState.None;
|
||||
private Popup _popup = null;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
_launcher = launcher;
|
||||
UpdateVisiblePages();
|
||||
SelectedPage = launcher.ActivePage;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
|
||||
@@ -158,6 +158,12 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _useFixedTabWidth, value);
|
||||
}
|
||||
|
||||
public bool UseAutoHideScrollBars
|
||||
{
|
||||
get => _useAutoHideScrollBars;
|
||||
set => SetProperty(ref _useAutoHideScrollBars, value);
|
||||
}
|
||||
|
||||
public bool Check4UpdatesOnStartup
|
||||
{
|
||||
get => _check4UpdatesOnStartup;
|
||||
@@ -706,6 +712,7 @@ namespace SourceGit.ViewModels
|
||||
private int _maxHistoryCommits = 20000;
|
||||
private int _subjectGuideLength = 50;
|
||||
private bool _useFixedTabWidth = true;
|
||||
private bool _useAutoHideScrollBars = true;
|
||||
private bool _showAuthorTimeInGraph = false;
|
||||
private bool _showChildren = false;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
|
||||
[Required(ErrorMessage = "Branch name is required!!!")]
|
||||
[RegularExpression(@"^[\w \-/\.#\+]+$", ErrorMessage = "Bad branch name format!")]
|
||||
[RegularExpression(@"^[\w\-/\.#\+]+$", ErrorMessage = "Bad branch name format!")]
|
||||
[CustomValidation(typeof(RenameBranch), nameof(ValidateBranchName))]
|
||||
public string Name
|
||||
{
|
||||
@@ -31,10 +31,9 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (ctx.ObjectInstance is RenameBranch rename)
|
||||
{
|
||||
var fixedName = Models.Branch.FixName(name);
|
||||
foreach (var b in rename._repo.Branches)
|
||||
{
|
||||
if (b.IsLocal && b != rename.Target && b.Name.Equals(fixedName, StringComparison.Ordinal))
|
||||
if (b.IsLocal && b != rename.Target && b.Name.Equals(name, StringComparison.Ordinal))
|
||||
return new ValidationResult("A branch with same name already exists!!!");
|
||||
}
|
||||
}
|
||||
@@ -44,8 +43,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public override async Task<bool> Sure()
|
||||
{
|
||||
var fixedName = Models.Branch.FixName(_name);
|
||||
if (fixedName.Equals(Target.Name, StringComparison.Ordinal))
|
||||
if (Target.Name.Equals(_name, StringComparison.Ordinal))
|
||||
return true;
|
||||
|
||||
_repo.SetWatcherEnabled(false);
|
||||
@@ -59,7 +57,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
var succ = await new Commands.Branch(_repo.FullPath, Target.Name)
|
||||
.Use(log)
|
||||
.RenameAsync(fixedName);
|
||||
.RenameAsync(_name);
|
||||
|
||||
if (succ)
|
||||
{
|
||||
@@ -68,7 +66,7 @@ namespace SourceGit.ViewModels
|
||||
if (filter.Type == Models.FilterType.LocalBranch &&
|
||||
filter.Pattern.Equals(oldName, StringComparison.Ordinal))
|
||||
{
|
||||
filter.Pattern = $"refs/heads/{fixedName}";
|
||||
filter.Pattern = $"refs/heads/{_name}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,39 +740,6 @@ namespace SourceGit.ViewModels
|
||||
return log;
|
||||
}
|
||||
|
||||
public async Task<Models.IssueTracker> AddIssueTrackerAsync(string name, string regex, string url)
|
||||
{
|
||||
var rule = new Models.IssueTracker()
|
||||
{
|
||||
IsShared = false,
|
||||
Name = name,
|
||||
RegexString = regex,
|
||||
URLTemplate = url,
|
||||
};
|
||||
|
||||
var succ = await CreateIssueTrackerCommand(false).AddAsync(rule);
|
||||
if (succ)
|
||||
{
|
||||
IssueTrackers.Add(rule);
|
||||
return rule;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task RemoveIssueTrackerAsync(Models.IssueTracker rule)
|
||||
{
|
||||
var succ = await CreateIssueTrackerCommand(rule.IsShared).RemoveAsync(rule);
|
||||
if (succ)
|
||||
IssueTrackers.Remove(rule);
|
||||
}
|
||||
|
||||
public async Task ChangeIssueTrackerShareModeAsync(Models.IssueTracker rule)
|
||||
{
|
||||
await CreateIssueTrackerCommand(!rule.IsShared).RemoveAsync(rule);
|
||||
await CreateIssueTrackerCommand(rule.IsShared).AddAsync(rule);
|
||||
}
|
||||
|
||||
public void RefreshAll()
|
||||
{
|
||||
RefreshCommits();
|
||||
@@ -786,8 +753,8 @@ namespace SourceGit.ViewModels
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var issuetrackers = new List<Models.IssueTracker>();
|
||||
await CreateIssueTrackerCommand(true).ReadAllAsync(issuetrackers, true).ConfigureAwait(false);
|
||||
await CreateIssueTrackerCommand(false).ReadAllAsync(issuetrackers, false).ConfigureAwait(false);
|
||||
await new Commands.IssueTracker(FullPath, true).ReadAllAsync(issuetrackers, true).ConfigureAwait(false);
|
||||
await new Commands.IssueTracker(FullPath, false).ReadAllAsync(issuetrackers, false).ConfigureAwait(false);
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IssueTrackers.Clear();
|
||||
@@ -1215,7 +1182,7 @@ namespace SourceGit.ViewModels
|
||||
if (_workingCopy != null)
|
||||
_workingCopy.HasRemotes = remotes.Count > 0;
|
||||
|
||||
var hasPendingPullOrPush = CurrentBranch?.TrackStatus.IsVisible ?? false;
|
||||
var hasPendingPullOrPush = CurrentBranch?.IsTrackStatusVisible ?? false;
|
||||
GetOwnerPage()?.ChangeDirtyState(Models.DirtyState.HasPendingPullOrPush, !hasPendingPullOrPush);
|
||||
});
|
||||
}, token);
|
||||
@@ -1498,9 +1465,9 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (b.IsLocal &&
|
||||
b.Upstream.Equals(branch.FullName, StringComparison.Ordinal) &&
|
||||
b.TrackStatus.Ahead.Count == 0)
|
||||
b.Ahead.Count == 0)
|
||||
{
|
||||
if (b.TrackStatus.Behind.Count > 0)
|
||||
if (b.Behind.Count > 0)
|
||||
ShowPopup(new CheckoutAndFastForward(this, b, branch));
|
||||
else if (!b.IsCurrent)
|
||||
await CheckoutBranchAsync(b);
|
||||
@@ -1743,11 +1710,6 @@ namespace SourceGit.ViewModels
|
||||
return null;
|
||||
}
|
||||
|
||||
private Commands.IssueTracker CreateIssueTrackerCommand(bool shared)
|
||||
{
|
||||
return new Commands.IssueTracker(FullPath, shared ? $"{FullPath}/.issuetracker" : null);
|
||||
}
|
||||
|
||||
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
|
||||
{
|
||||
var builder = new BranchTreeNode.Builder(_settings.LocalBranchSortMode, _settings.RemoteBranchSortMode);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Collections;
|
||||
@@ -114,8 +115,8 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public AvaloniaList<Models.IssueTracker> IssueTrackers
|
||||
{
|
||||
get => _repo.IssueTrackers;
|
||||
}
|
||||
get;
|
||||
} = [];
|
||||
|
||||
public Models.IssueTracker SelectedIssueTracker
|
||||
{
|
||||
@@ -176,6 +177,17 @@ namespace SourceGit.ViewModels
|
||||
HttpProxy = proxy;
|
||||
if (_cached.TryGetValue("fetch.prune", out var prune))
|
||||
EnablePruneOnFetch = (prune == "true");
|
||||
|
||||
foreach (var rule in _repo.IssueTrackers)
|
||||
{
|
||||
IssueTrackers.Add(new()
|
||||
{
|
||||
IsShared = rule.IsShared,
|
||||
Name = rule.Name,
|
||||
RegexString = rule.RegexString,
|
||||
URLTemplate = rule.URLTemplate,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearHttpProxy()
|
||||
@@ -208,25 +220,28 @@ namespace SourceGit.ViewModels
|
||||
return outs;
|
||||
}
|
||||
|
||||
public async Task AddIssueTrackerAsync(string name, string regex, string url)
|
||||
public void AddIssueTracker(string name, string regex, string url)
|
||||
{
|
||||
SelectedIssueTracker = await _repo.AddIssueTrackerAsync(name, regex, url);
|
||||
var rule = new Models.IssueTracker()
|
||||
{
|
||||
IsShared = false,
|
||||
Name = name,
|
||||
RegexString = regex,
|
||||
URLTemplate = url,
|
||||
};
|
||||
|
||||
IssueTrackers.Add(rule);
|
||||
SelectedIssueTracker = rule;
|
||||
}
|
||||
|
||||
public async Task RemoveIssueTrackerAsync()
|
||||
public void RemoveIssueTracker()
|
||||
{
|
||||
if (_selectedIssueTracker is { } rule)
|
||||
await _repo.RemoveIssueTrackerAsync(rule);
|
||||
IssueTrackers.Remove(rule);
|
||||
|
||||
SelectedIssueTracker = null;
|
||||
}
|
||||
|
||||
public async Task ChangeIssueTrackerShareModeAsync()
|
||||
{
|
||||
if (_selectedIssueTracker is { } rule)
|
||||
await _repo.ChangeIssueTrackerShareModeAsync(rule);
|
||||
}
|
||||
|
||||
public void AddNewCustomAction()
|
||||
{
|
||||
SelectedCustomAction = _repo.Settings.AddNewCustomAction();
|
||||
@@ -259,6 +274,8 @@ namespace SourceGit.ViewModels
|
||||
await SetIfChangedAsync("user.signingkey", GPGUserSigningKey, "");
|
||||
await SetIfChangedAsync("http.proxy", HttpProxy, "");
|
||||
await SetIfChangedAsync("fetch.prune", EnablePruneOnFetch ? "true" : "false", "false");
|
||||
|
||||
await ApplyIssueTrackerChangesAsync();
|
||||
}
|
||||
|
||||
private async Task SetIfChangedAsync(string key, string value, string defValue)
|
||||
@@ -267,6 +284,62 @@ namespace SourceGit.ViewModels
|
||||
await new Commands.Config(_repo.FullPath).SetAsync(key, value);
|
||||
}
|
||||
|
||||
private async Task ApplyIssueTrackerChangesAsync()
|
||||
{
|
||||
var changed = false;
|
||||
var oldRules = new Dictionary<string, Models.IssueTracker>();
|
||||
foreach (var rule in _repo.IssueTrackers)
|
||||
oldRules.Add(rule.Name, rule);
|
||||
|
||||
foreach (var rule in IssueTrackers)
|
||||
{
|
||||
if (oldRules.TryGetValue(rule.Name, out var old))
|
||||
{
|
||||
if (old.IsShared != rule.IsShared)
|
||||
{
|
||||
changed = true;
|
||||
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).RemoveAsync(old.Name);
|
||||
await new Commands.IssueTracker(_repo.FullPath, rule.IsShared).AddAsync(rule);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!old.RegexString.Equals(rule.RegexString, StringComparison.Ordinal))
|
||||
{
|
||||
changed = true;
|
||||
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).UpdateRegexAsync(rule);
|
||||
}
|
||||
|
||||
if (!old.URLTemplate.Equals(rule.URLTemplate, StringComparison.Ordinal))
|
||||
{
|
||||
changed = true;
|
||||
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).UpdateURLTemplateAsync(rule);
|
||||
}
|
||||
}
|
||||
|
||||
oldRules.Remove(rule.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
changed = true;
|
||||
await new Commands.IssueTracker(_repo.FullPath, rule.IsShared).AddAsync(rule);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldRules.Count > 0)
|
||||
{
|
||||
changed = true;
|
||||
|
||||
foreach (var kv in oldRules)
|
||||
await new Commands.IssueTracker(_repo.FullPath, kv.Value.IsShared).RemoveAsync(kv.Key);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
_repo.IssueTrackers.Clear();
|
||||
_repo.IssueTrackers.AddRange(IssueTrackers);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Repository _repo = null;
|
||||
private readonly Dictionary<string, string> _cached = null;
|
||||
private string _httpProxy;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
var source = await ImageSource.FromLFSObjectAsync(repo, lfs, decoder).ConfigureAwait(false);
|
||||
var img = new Models.RevisionImageFile(file, source.Bitmap, source.Size);
|
||||
Dispatcher.UIThread.Invoke(() => Image = img);
|
||||
Dispatcher.UIThread.Post(() => Image = img);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
var changes = await new Commands.QueryLocalChanges(_repo.FullPath, false).GetResultAsync();
|
||||
var signOff = _repo.Settings.EnableSignOffForCommit;
|
||||
var noVerify = _repo.Settings.NoVerifyOnCommit;
|
||||
var needAutoStash = false;
|
||||
var succ = false;
|
||||
|
||||
@@ -64,7 +65,7 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
succ = await new Commands.Commit(_repo.FullPath, _message, signOff, true, false)
|
||||
succ = await new Commands.Commit(_repo.FullPath, _message, signOff, noVerify, true, false)
|
||||
.Use(log)
|
||||
.RunAsync();
|
||||
|
||||
|
||||
@@ -8,6 +8,18 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
public class ScanRepositories : Popup
|
||||
{
|
||||
public bool UseCustomDir
|
||||
{
|
||||
get => _useCustomDir;
|
||||
set => SetProperty(ref _useCustomDir, value);
|
||||
}
|
||||
|
||||
public string CustomDir
|
||||
{
|
||||
get => _customDir;
|
||||
set => SetProperty(ref _customDir, value);
|
||||
}
|
||||
|
||||
public List<Models.ScanDir> ScanDirs
|
||||
{
|
||||
get;
|
||||
@@ -33,16 +45,28 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (ScanDirs.Count > 0)
|
||||
_selected = ScanDirs[0];
|
||||
else
|
||||
_useCustomDir = true;
|
||||
|
||||
GetManagedRepositories(Preferences.Instance.RepositoryNodes, _managed);
|
||||
}
|
||||
|
||||
public override async Task<bool> Sure()
|
||||
{
|
||||
ProgressDescription = $"Scan repositories under '{_selected.Path}' ...";
|
||||
var selectedDir = _useCustomDir ? _customDir : _selected?.Path;
|
||||
if (string.IsNullOrEmpty(selectedDir))
|
||||
{
|
||||
App.RaiseException(null, "Missing root directory to scan!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(selectedDir))
|
||||
return true;
|
||||
|
||||
ProgressDescription = $"Scan repositories under '{selectedDir}' ...";
|
||||
|
||||
var minDelay = Task.Delay(500);
|
||||
var rootDir = new DirectoryInfo(_selected.Path);
|
||||
var rootDir = new DirectoryInfo(selectedDir);
|
||||
var found = new List<string>();
|
||||
|
||||
await GetUnmanagedRepositoriesAsync(rootDir, found, new EnumerationOptions()
|
||||
@@ -162,6 +186,8 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
|
||||
private HashSet<string> _managed = new();
|
||||
private bool _useCustomDir = false;
|
||||
private string _customDir = string.Empty;
|
||||
private Models.ScanDir _selected = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
var changes = await new Commands.QueryLocalChanges(_repo.FullPath, false).GetResultAsync();
|
||||
var signOff = _repo.Settings.EnableSignOffForCommit;
|
||||
var noVerify = _repo.Settings.NoVerifyOnCommit;
|
||||
var needAutoStash = false;
|
||||
var succ = false;
|
||||
|
||||
@@ -64,7 +65,7 @@ namespace SourceGit.ViewModels
|
||||
.ExecAsync();
|
||||
|
||||
if (succ)
|
||||
succ = await new Commands.Commit(_repo.FullPath, _message, signOff, true, false)
|
||||
succ = await new Commands.Commit(_repo.FullPath, _message, signOff, noVerify, true, false)
|
||||
.Use(log)
|
||||
.RunAsync();
|
||||
|
||||
|
||||
@@ -198,24 +198,16 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public async Task CheckoutSingleFileAsync(Models.Change change)
|
||||
{
|
||||
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, change.Path);
|
||||
var log = _repo.CreateLog($"Reset File to '{_selectedStash.SHA}'");
|
||||
var revision = _selectedStash.SHA;
|
||||
if (_untracked.Contains(change) && _selectedStash.Parents.Count == 3)
|
||||
revision = _selectedStash.Parents[2];
|
||||
else if (change.Index == Models.ChangeState.Added && _selectedStash.Parents.Count > 1)
|
||||
revision = _selectedStash.Parents[1];
|
||||
|
||||
if (_untracked.Contains(change))
|
||||
{
|
||||
await Commands.SaveRevisionFile.RunAsync(_repo.FullPath, _selectedStash.Parents[2], change.Path, fullPath);
|
||||
}
|
||||
else if (change.Index == Models.ChangeState.Added)
|
||||
{
|
||||
await Commands.SaveRevisionFile.RunAsync(_repo.FullPath, _selectedStash.SHA, change.Path, fullPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
await new Commands.Checkout(_repo.FullPath)
|
||||
var log = _repo.CreateLog($"Reset File to '{_selectedStash.Name}'");
|
||||
await new Commands.Checkout(_repo.FullPath)
|
||||
.Use(log)
|
||||
.FileWithRevisionAsync(change.Path, $"{_selectedStash.SHA}");
|
||||
}
|
||||
|
||||
.FileWithRevisionAsync(change.Path, revision);
|
||||
log.Complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,12 @@ namespace SourceGit.ViewModels
|
||||
set => _repo.Settings.EnableSignOffForCommit = value;
|
||||
}
|
||||
|
||||
public bool NoVerifyOnCommit
|
||||
{
|
||||
get => _repo.Settings.NoVerifyOnCommit;
|
||||
set => _repo.Settings.NoVerifyOnCommit = value;
|
||||
}
|
||||
|
||||
public bool UseAmend
|
||||
{
|
||||
get => _useAmend;
|
||||
@@ -619,7 +625,7 @@ namespace SourceGit.ViewModels
|
||||
_repo.Settings.CommitMessages.Clear();
|
||||
}
|
||||
|
||||
public async Task CommitAsync(bool autoStage, bool autoPush, Models.CommitCheckPassed checkPassed = Models.CommitCheckPassed.None)
|
||||
public async Task CommitAsync(bool autoStage, bool autoPush)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_commitMessage))
|
||||
return;
|
||||
@@ -636,30 +642,32 @@ namespace SourceGit.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
if (_repo.CurrentBranch is { IsDetachedHead: true } && checkPassed < Models.CommitCheckPassed.DetachedHead)
|
||||
if (_repo.CurrentBranch is { IsDetachedHead: true })
|
||||
{
|
||||
var msg = App.Text("WorkingCopy.ConfirmCommitWithDetachedHead");
|
||||
var sure = await App.AskConfirmAsync(msg);
|
||||
if (sure)
|
||||
await CommitAsync(autoStage, autoPush, Models.CommitCheckPassed.DetachedHead);
|
||||
return;
|
||||
if (!sure)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_filter) && _staged.Count > _visibleStaged.Count && checkPassed < Models.CommitCheckPassed.Filter)
|
||||
if (!string.IsNullOrEmpty(_filter) && _staged.Count > _visibleStaged.Count)
|
||||
{
|
||||
var msg = App.Text("WorkingCopy.ConfirmCommitWithFilter", _staged.Count, _visibleStaged.Count, _staged.Count - _visibleStaged.Count);
|
||||
var sure = await App.AskConfirmAsync(msg);
|
||||
if (sure)
|
||||
await CommitAsync(autoStage, autoPush, Models.CommitCheckPassed.Filter);
|
||||
return;
|
||||
if (!sure)
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkPassed < Models.CommitCheckPassed.FileCount && !_useAmend)
|
||||
if (!_useAmend)
|
||||
{
|
||||
if ((!autoStage && _staged.Count == 0) || (autoStage && _cached.Count == 0))
|
||||
{
|
||||
await App.ShowDialog(new ConfirmEmptyCommit(this, autoPush, _cached.Count));
|
||||
return;
|
||||
var rs = await App.AskConfirmEmptyCommitAsync(_cached.Count > 0);
|
||||
if (rs == Models.ConfirmEmptyCommitResult.Cancel)
|
||||
return;
|
||||
|
||||
if (rs == Models.ConfirmEmptyCommitResult.StageAllAndCommit)
|
||||
autoStage = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,14 +675,19 @@ namespace SourceGit.ViewModels
|
||||
_repo.Settings.PushCommitMessage(_commitMessage);
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
||||
var signOff = _repo.Settings.EnableSignOffForCommit;
|
||||
var log = _repo.CreateLog("Commit");
|
||||
var succ = true;
|
||||
if (autoStage && _unstaged.Count > 0)
|
||||
succ = await new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).ExecAsync().ConfigureAwait(false);
|
||||
succ = await new Commands.Add(_repo.FullPath, _repo.IncludeUntracked)
|
||||
.Use(log)
|
||||
.ExecAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (succ)
|
||||
succ = await new Commands.Commit(_repo.FullPath, _commitMessage, signOff, _useAmend, _resetAuthor).Use(log).RunAsync().ConfigureAwait(false);
|
||||
succ = await new Commands.Commit(_repo.FullPath, _commitMessage, EnableSignOff, NoVerifyOnCommit, _useAmend, _resetAuthor)
|
||||
.Use(log)
|
||||
.RunAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
log.Complete();
|
||||
|
||||
|
||||
63
src/Views/BranchOrTagNameTextBox.cs
Normal file
63
src/Views/BranchOrTagNameTextBox.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class BranchOrTagNameTextBox : TextBox
|
||||
{
|
||||
protected override Type StyleKeyOverride => typeof(TextBox);
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
PastingFromClipboard += OnPastingFromClipboard;
|
||||
}
|
||||
|
||||
protected override void OnUnloaded(RoutedEventArgs e)
|
||||
{
|
||||
PastingFromClipboard -= OnPastingFromClipboard;
|
||||
base.OnUnloaded(e);
|
||||
}
|
||||
|
||||
protected override void OnTextInput(TextInputEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Text))
|
||||
return;
|
||||
|
||||
var builder = new StringBuilder(e.Text.Length);
|
||||
var chars = e.Text.ToCharArray();
|
||||
foreach (var ch in chars)
|
||||
{
|
||||
if (char.IsWhiteSpace(ch))
|
||||
builder.Append('-');
|
||||
else
|
||||
builder.Append(ch);
|
||||
}
|
||||
|
||||
e.Text = builder.ToString();
|
||||
base.OnTextInput(e);
|
||||
}
|
||||
|
||||
private async void OnPastingFromClipboard(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var clipboard = TopLevel.GetTopLevel(this)?.Clipboard;
|
||||
if (clipboard != null)
|
||||
{
|
||||
var text = await clipboard.GetTextAsync();
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
OnTextInput(new TextInputEventArgs() { Text = text });
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,26 +43,52 @@
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Branch}"/>
|
||||
<TextBlock FontWeight="Bold" VerticalAlignment="Center" Margin="8,0,0,0" Text="{Binding FriendlyName}"/>
|
||||
<TextBlock FontWeight="Bold" VerticalAlignment="Center" Margin="4,0,0,0" Text="{Binding FriendlyName}"/>
|
||||
<Border Background="Green" Margin="4,0,0,0" CornerRadius="4" VerticalAlignment="Center" IsVisible="{Binding !IsLocal}">
|
||||
<TextBlock Text="{DynamicResource Text.BranchTree.Remote}" FontSize="12" Classes="primary" Margin="4,1" Foreground="White" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{DynamicResource Text.BranchTree.Remote}" FontSize="12" Classes="primary" Margin="4,0" Foreground="White" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="0,8,0,0"
|
||||
IsVisible="{Binding Upstream, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||
<TextBlock Classes="info_label"
|
||||
<Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="Auto,Auto" Margin="0,8,0,0" IsVisible="{Binding IsLocal, Mode=OneWay}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Classes="info_label"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{DynamicResource Text.BranchTree.Tracking}"/>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1"
|
||||
Margin="8,0,0,0"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Upstream, Mode=OneWay, Converter={x:Static c:StringConverters.ToFriendlyUpstream}}"
|
||||
IsVisible="{Binding Upstream, Mode=OneWay, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<TextBlock IsVisible="{Binding Upstream, Mode=OneWay, Converter={x:Static StringConverters.IsNullOrEmpty}}">
|
||||
<Run Text="---"/>
|
||||
<Run Text="(none)" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock Margin="6,0,0,0"
|
||||
Text="{Binding Upstream, Mode=OneWay, Converter={x:Static c:StringConverters.ToFriendlyUpstream}}"/>
|
||||
<Border Background="OrangeRed" Margin="4,0,0,0" CornerRadius="4" VerticalAlignment="Center" IsVisible="{Binding IsUpstreamGone}">
|
||||
<TextBlock Text="{DynamicResource Text.BranchTree.InvalidUpstream}" FontSize="12" Classes="primary" Margin="4,1" Foreground="White" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<Border Background="OrangeRed" Margin="4,0,0,0" CornerRadius="4" VerticalAlignment="Center" IsVisible="{Binding IsUpstreamGone}">
|
||||
<TextBlock Text="{DynamicResource Text.BranchTree.InvalidUpstream}" FontSize="12" Classes="primary" Margin="4,1" Foreground="White" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
Classes="info_label"
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{DynamicResource Text.BranchTree.Status}"
|
||||
IsVisible="{Binding IsTrackStatusVisible, Mode=OneWay}"/>
|
||||
<v:BranchTreeNodeTrackStatusTooltip Grid.Row="1" Grid.Column="1"
|
||||
Margin="8,4,0,0"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
Classes="info_label"
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Text="{DynamicResource Text.BranchTree.Worktree}"
|
||||
IsVisible="{Binding HasWorktree}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1"
|
||||
Margin="8,4,0,0"
|
||||
Text="{Binding WorktreePath, Mode=OneWay}"
|
||||
IsVisible="{Binding HasWorktree}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
|
||||
@@ -50,25 +50,27 @@ namespace SourceGit.Views
|
||||
|
||||
if (node.Backend is Models.Remote)
|
||||
{
|
||||
CreateContent(new Thickness(0, 0, 0, 0), "Icons.Remote", false);
|
||||
CreateContent(new Thickness(0, 0, 0, 0), "Icons.Remote");
|
||||
}
|
||||
else if (node.Backend is Models.Branch branch)
|
||||
{
|
||||
if (branch.IsCurrent)
|
||||
CreateContent(new Thickness(0, 0, 0, 0), "Icons.CheckCircled", true);
|
||||
CreateContent(new Thickness(0, 0, 0, 0), "Icons.CheckCircled", Brushes.Green);
|
||||
else if (branch.IsLocal && !string.IsNullOrEmpty(branch.WorktreePath))
|
||||
CreateContent(new Thickness(2, 0, 0, 0), "Icons.Branch", Brushes.DarkCyan);
|
||||
else
|
||||
CreateContent(new Thickness(2, 0, 0, 0), "Icons.Branch", false);
|
||||
CreateContent(new Thickness(2, 0, 0, 0), "Icons.Branch");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node.IsExpanded)
|
||||
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder.Open", false);
|
||||
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder.Open");
|
||||
else
|
||||
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder", false);
|
||||
CreateContent(new Thickness(0, 2, 0, 0), "Icons.Folder");
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateContent(Thickness margin, string iconKey, bool highlight)
|
||||
private void CreateContent(Thickness margin, string iconKey, IBrush fill = null)
|
||||
{
|
||||
if (this.FindResource(iconKey) is not StreamGeometry geo)
|
||||
return;
|
||||
@@ -83,8 +85,8 @@ namespace SourceGit.Views
|
||||
Data = geo,
|
||||
};
|
||||
|
||||
if (highlight)
|
||||
path.Fill = Brushes.Green;
|
||||
if (fill != null)
|
||||
path.Fill = fill;
|
||||
|
||||
Content = path;
|
||||
}
|
||||
@@ -181,11 +183,11 @@ namespace SourceGit.Views
|
||||
|
||||
if (DataContext is ViewModels.BranchTreeNode { Backend: Models.Branch branch })
|
||||
{
|
||||
var status = branch.TrackStatus.ToString();
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
var desc = branch.TrackStatusDescription;
|
||||
if (!string.IsNullOrEmpty(desc))
|
||||
{
|
||||
_label = new FormattedText(
|
||||
status,
|
||||
desc,
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
new Typeface(FontFamily),
|
||||
@@ -200,6 +202,33 @@ namespace SourceGit.Views
|
||||
private FormattedText _label = null;
|
||||
}
|
||||
|
||||
public class BranchTreeNodeTrackStatusTooltip : TextBlock
|
||||
{
|
||||
protected override Type StyleKeyOverride => typeof(TextBlock);
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
|
||||
Text = string.Empty;
|
||||
|
||||
if (DataContext is not Models.Branch { IsTrackStatusVisible: true } branch)
|
||||
{
|
||||
SetCurrentValue(IsVisibleProperty, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var ahead = branch.Ahead.Count;
|
||||
var behind = branch.Behind.Count;
|
||||
if (ahead > 0)
|
||||
Text = behind > 0 ? App.Text("BranchTree.AheadBehind", ahead, behind) : App.Text("BranchTree.Ahead", ahead);
|
||||
else
|
||||
Text = App.Text("BranchTree.Behind", behind);
|
||||
|
||||
SetCurrentValue(IsVisibleProperty, true);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class BranchTree : UserControl
|
||||
{
|
||||
public static readonly StyledProperty<List<ViewModels.BranchTreeNode>> NodesProperty =
|
||||
@@ -605,7 +634,7 @@ namespace SourceGit.Views
|
||||
var fastForward = new MenuItem();
|
||||
fastForward.Header = App.Text("BranchCM.FastForward", upstream.FriendlyName);
|
||||
fastForward.Icon = App.CreateMenuIcon("Icons.FastForward");
|
||||
fastForward.IsEnabled = branch.TrackStatus.Ahead.Count == 0 && branch.TrackStatus.Behind.Count > 0;
|
||||
fastForward.IsEnabled = branch.Ahead.Count == 0 && branch.Behind.Count > 0;
|
||||
fastForward.Click += async (_, e) =>
|
||||
{
|
||||
if (repo.CanCreatePopup())
|
||||
@@ -633,27 +662,26 @@ namespace SourceGit.Views
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!repo.IsBare)
|
||||
{
|
||||
var checkout = new MenuItem();
|
||||
checkout.Header = App.Text("BranchCM.Checkout", branch.Name);
|
||||
checkout.Icon = App.CreateMenuIcon("Icons.Check");
|
||||
checkout.Click += async (_, e) =>
|
||||
{
|
||||
await repo.CheckoutBranchAsync(branch);
|
||||
e.Handled = true;
|
||||
};
|
||||
menu.Items.Add(checkout);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
}
|
||||
var hasNoWorktree = string.IsNullOrEmpty(branch.WorktreePath);
|
||||
|
||||
var worktree = repo.Worktrees.Find(x => x.Branch == branch.FullName);
|
||||
if (upstream != null && worktree == null)
|
||||
var checkout = new MenuItem();
|
||||
checkout.Header = App.Text(hasNoWorktree ? "BranchCM.Checkout" : "BranchCM.SwitchToWorktree", branch.Name);
|
||||
checkout.Icon = App.CreateMenuIcon("Icons.Check");
|
||||
checkout.IsEnabled = !repo.IsBare || !hasNoWorktree;
|
||||
checkout.Click += async (_, e) =>
|
||||
{
|
||||
await repo.CheckoutBranchAsync(branch);
|
||||
e.Handled = true;
|
||||
};
|
||||
menu.Items.Add(checkout);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
|
||||
if (upstream != null && hasNoWorktree)
|
||||
{
|
||||
var fastForward = new MenuItem();
|
||||
fastForward.Header = App.Text("BranchCM.FastForward", upstream.FriendlyName);
|
||||
fastForward.Icon = App.CreateMenuIcon("Icons.FastForward");
|
||||
fastForward.IsEnabled = branch.TrackStatus.Ahead.Count == 0 && branch.TrackStatus.Behind.Count > 0;
|
||||
fastForward.IsEnabled = branch.Ahead.Count == 0 && branch.Behind.Count > 0;
|
||||
fastForward.Click += async (_, e) =>
|
||||
{
|
||||
if (repo.CanCreatePopup())
|
||||
@@ -665,7 +693,7 @@ namespace SourceGit.Views
|
||||
var fetchInto = new MenuItem();
|
||||
fetchInto.Header = App.Text("BranchCM.FetchInto", upstream.FriendlyName, branch.Name);
|
||||
fetchInto.Icon = App.CreateMenuIcon("Icons.Fetch");
|
||||
fetchInto.IsEnabled = branch.TrackStatus.Ahead.Count == 0;
|
||||
fetchInto.IsEnabled = branch.Ahead.Count == 0;
|
||||
fetchInto.Click += async (_, e) =>
|
||||
{
|
||||
if (repo.CanCreatePopup())
|
||||
@@ -705,7 +733,7 @@ namespace SourceGit.Views
|
||||
menu.Items.Add(rebase);
|
||||
}
|
||||
|
||||
if (worktree == null)
|
||||
if (hasNoWorktree)
|
||||
{
|
||||
var selectedCommit = repo.GetSelectedCommitInHistory();
|
||||
if (selectedCommit != null && !selectedCommit.SHA.Equals(branch.Head, StringComparison.Ordinal))
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="9"
|
||||
Background="{DynamicResource Brush.Badge}"
|
||||
IsVisible="{Binding LocalBranch.TrackStatus.IsVisible}">
|
||||
IsVisible="{Binding LocalBranch.IsTrackStatusVisible, Mode=OneWay}">
|
||||
<TextBlock Foreground="{DynamicResource Brush.BadgeFG}"
|
||||
FontFamily="{DynamicResource Fonts.Monospace}"
|
||||
FontSize="10"
|
||||
Text="{Binding LocalBranch.TrackStatus}"/>
|
||||
Text="{Binding LocalBranch.TrackStatusDescription, Mode=OneWay}"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<Grid ColumnDefinitions="96,*">
|
||||
<v:Avatar Grid.Column="0" Width="64" Height="64" HorizontalAlignment="Right" User="{Binding Author}"/>
|
||||
<StackPanel Grid.Column="1" Margin="16,0,8,0" Orientation="Vertical">
|
||||
<TextBlock Classes="group_header_label" Margin="0" Text="{DynamicResource Text.CommitDetail.Info.Author}"/>
|
||||
<TextBlock Classes="group_header_label" Text="{DynamicResource Text.CommitDetail.Info.Author}"/>
|
||||
<Grid Margin="0,10,0,8" ColumnDefinitions="Auto,*" ClipToBounds="True">
|
||||
<v:EnhancedSelectableTextBlock Grid.Column="0" Text="{Binding Author.Name}" Margin="2,0,8,0"/>
|
||||
<v:EnhancedSelectableTextBlock Grid.Column="1" Text="{Binding Author.Email}" ToolTip.Tip="{Binding Author.Email}" Foreground="{DynamicResource Brush.FG2}" TextTrimming="CharacterEllipsis"/>
|
||||
@@ -34,7 +34,7 @@
|
||||
<Grid ColumnDefinitions="96,*" IsVisible="{Binding IsCommitterVisible}">
|
||||
<v:Avatar Grid.Column="0" Width="64" Height="64" HorizontalAlignment="Right" User="{Binding Committer}"/>
|
||||
<StackPanel Grid.Column="1" Margin="16,0,8,0" Orientation="Vertical">
|
||||
<TextBlock Classes="group_header_label" Margin="0" Text="{DynamicResource Text.CommitDetail.Info.Committer}"/>
|
||||
<TextBlock Classes="group_header_label" Text="{DynamicResource Text.CommitDetail.Info.Committer}"/>
|
||||
<Grid Margin="0,10,0,8" ColumnDefinitions="Auto,*" ClipToBounds="True">
|
||||
<v:EnhancedSelectableTextBlock Grid.Column="0" Text="{Binding Committer.Name}" Margin="2,0,8,0"/>
|
||||
<v:EnhancedSelectableTextBlock Grid.Column="1" Text="{Binding Committer.Email}" ToolTip.Tip="{Binding Committer.Email}" Foreground="{DynamicResource Brush.FG2}" TextTrimming="CharacterEllipsis"/>
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace SourceGit.Views
|
||||
history.Icon = App.CreateMenuIcon("Icons.Histories");
|
||||
history.Click += (_, ev) =>
|
||||
{
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo, change.Path, commit.SHA));
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo.FullPath, change.Path, commit.SHA));
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
Background="{DynamicResource Brush.Window}"
|
||||
BorderThickness="1,0,0,0"
|
||||
CornerRadius="0,0,4,4">
|
||||
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,*" Margin="0,4">
|
||||
<Grid ColumnDefinitions="Auto,Auto,Auto,Auto,Auto,*" Margin="0,4">
|
||||
<Button Grid.Column="0"
|
||||
Classes="icon_button"
|
||||
Width="24"
|
||||
@@ -105,7 +105,16 @@
|
||||
<Path Width="13" Height="13" Data="{StaticResource Icons.Copy}"/>
|
||||
</Button>
|
||||
|
||||
<StackPanel Grid.Column="4"
|
||||
<Button Grid.Column="4"
|
||||
Classes="icon_button"
|
||||
Width="24"
|
||||
Margin="0,0,4,0" Padding="0"
|
||||
Click="PasteAndReplaceAllText"
|
||||
ToolTip.Tip="{DynamicResource Text.CommitMessageTextBox.PasteAndReplaceAll}">
|
||||
<Path Width="13" Height="13" Data="{StaticResource Icons.Paste}"/>
|
||||
</Button>
|
||||
|
||||
<StackPanel Grid.Column="5"
|
||||
Margin="0,0,6,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
|
||||
@@ -356,6 +356,26 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void PasteAndReplaceAllText(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var text = await App.GetClipboardTextAsync();
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
var parts = text.ReplaceLineEndings("\n").Split("\n", 2);
|
||||
var subject = parts[0];
|
||||
Text = parts.Length > 1 ? $"{subject}\n\n{parts[1].Trim()}" : subject;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exceptions.
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private TextChangeWay _changingWay = TextChangeWay.None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,14 +52,13 @@ namespace SourceGit.Views
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
if (DataContext is Models.Commit commit && CurrentBranch is not null)
|
||||
if (DataContext is Models.Commit commit && CurrentBranch is { } b)
|
||||
{
|
||||
var sha = commit.SHA;
|
||||
var track = CurrentBranch.TrackStatus;
|
||||
|
||||
if (track.Ahead.Contains(sha))
|
||||
if (b.Ahead.Contains(sha))
|
||||
_status = Status.Ahead;
|
||||
else if (track.Behind.Contains(sha))
|
||||
else if (b.Behind.Contains(sha))
|
||||
_status = Status.Behind;
|
||||
else
|
||||
_status = Status.Normal;
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.ConfirmEmptyCommit"
|
||||
x:DataType="vm:ConfirmEmptyCommit"
|
||||
x:Name="ThisControl"
|
||||
Icon="/App.ico"
|
||||
Title="{DynamicResource Text.Warn}"
|
||||
@@ -39,15 +37,15 @@
|
||||
|
||||
<!-- Body -->
|
||||
<Border Grid.Row="1" Margin="16">
|
||||
<TextBlock Text="{Binding Message}" MaxWidth="520" TextWrapping="Wrap"/>
|
||||
<TextBlock x:Name="TxtMessage" MaxWidth="520" TextWrapping="Wrap"/>
|
||||
</Border>
|
||||
|
||||
<!-- Buttons -->
|
||||
<StackPanel Grid.Row="2" Margin="0,0,0,16" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Classes="flat"
|
||||
x:Name="BtnStageAllAndCommit"
|
||||
Height="30"
|
||||
Margin="4,0"
|
||||
IsVisible="{Binding HasLocalChanges}"
|
||||
Click="StageAllThenCommit"
|
||||
Content="{DynamicResource Text.ConfirmEmptyCommit.StageAllThenCommit}"
|
||||
HorizontalContentAlignment="Center"
|
||||
|
||||
@@ -9,25 +9,19 @@ namespace SourceGit.Views
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void StageAllThenCommit(object _1, RoutedEventArgs _2)
|
||||
private void StageAllThenCommit(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
if (DataContext is ViewModels.ConfirmEmptyCommit vm)
|
||||
await vm.StageAllThenCommitAsync();
|
||||
|
||||
Close();
|
||||
Close(Models.ConfirmEmptyCommitResult.StageAllAndCommit);
|
||||
}
|
||||
|
||||
private async void Continue(object _1, RoutedEventArgs _2)
|
||||
private void Continue(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
if (DataContext is ViewModels.ConfirmEmptyCommit vm)
|
||||
await vm.ContinueAsync();
|
||||
|
||||
Close();
|
||||
Close(Models.ConfirmEmptyCommitResult.CreateEmptyCommit);
|
||||
}
|
||||
|
||||
private void CloseWindow(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
Close();
|
||||
Close(Models.ConfirmEmptyCommitResult.Cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.CreateBranch.Title}"/>
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,32,Auto,Auto,Auto" ColumnDefinitions="140,*">
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,Auto,Auto" ColumnDefinitions="140,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
@@ -48,26 +48,20 @@
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.CreateBranch.Name}"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1"
|
||||
Height="26"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.CreateBranch.Name.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
<StackPanel Grid.Row="2" Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
IsVisible="{Binding Name, Converter={x:Static c:StringConverters.ContainsSpaces}}">
|
||||
<Path Width="10" Height="10" Data="{StaticResource Icons.Error}" Fill="DarkOrange"/>
|
||||
<TextBlock Classes="small" Text="{DynamicResource Text.CreateBranch.Name.WarnSpace}" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
<v:BranchOrTagNameTextBox Grid.Row="1" Grid.Column="1"
|
||||
Height="26"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.CreateBranch.Name.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0"
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.CreateBranch.LocalChanges}"
|
||||
IsVisible="{Binding !IsBareRepository}"/>
|
||||
<Border Grid.Row="3" Grid.Column="1" MinHeight="32" IsVisible="{Binding !IsBareRepository}">
|
||||
<Border Grid.Row="2" Grid.Column="1" MinHeight="32" IsVisible="{Binding !IsBareRepository}">
|
||||
<WrapPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<RadioButton GroupName="LocalChanges"
|
||||
Margin="0,0,8,0"
|
||||
@@ -78,17 +72,17 @@
|
||||
</WrapPanel>
|
||||
</Border>
|
||||
|
||||
<CheckBox Grid.Row="4" Grid.Column="1"
|
||||
<CheckBox Grid.Row="3" Grid.Column="1"
|
||||
Content="{DynamicResource Text.CreateBranch.OverwriteExisting}"
|
||||
IsChecked="{Binding AllowOverwrite, Mode=TwoWay}"
|
||||
ToolTip.Tip="checkout -B or branch -f"/>
|
||||
|
||||
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||
<CheckBox Grid.Row="4" Grid.Column="1"
|
||||
Content="{DynamicResource Text.CreateBranch.Checkout}"
|
||||
IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"
|
||||
IsVisible="{Binding !IsBareRepository}"/>
|
||||
|
||||
<CheckBox Grid.Row="6" Grid.Column="1"
|
||||
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
|
||||
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
|
||||
ToolTip.Tip="--recurse-submodules">
|
||||
|
||||
@@ -41,13 +41,13 @@
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.CreateTag.Name}"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1"
|
||||
Height="26"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding TagName, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.CreateTag.Name.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
<v:BranchOrTagNameTextBox Grid.Row="1" Grid.Column="1"
|
||||
Height="26"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding TagName, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.CreateTag.Name.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="9"
|
||||
Background="{DynamicResource Brush.Badge}"
|
||||
IsVisible="{Binding Target.TrackStatus.IsVisible}">
|
||||
IsVisible="{Binding Target.IsTrackStatusVisible}">
|
||||
<TextBlock Foreground="{DynamicResource Brush.BadgeFG}"
|
||||
FontFamily="{DynamicResource Fonts.Monospace}"
|
||||
FontSize="10"
|
||||
Text="{Binding Target.TrackStatus}"/>
|
||||
Text="{Binding Target.TrackStatusDescription}"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@@ -52,11 +52,11 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="9"
|
||||
Background="{DynamicResource Brush.Badge}"
|
||||
IsVisible="{Binding TrackStatus.IsVisible}">
|
||||
IsVisible="{Binding IsTrackStatusVisible}">
|
||||
<TextBlock Foreground="{DynamicResource Brush.BadgeFG}"
|
||||
FontFamily="{DynamicResource Fonts.Monospace}"
|
||||
FontSize="10"
|
||||
Text="{Binding TrackStatus}"/>
|
||||
Text="{Binding TrackStatusDescription, Mode=OneWay}"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -711,7 +711,7 @@ namespace SourceGit.Views
|
||||
|
||||
if (!isHead)
|
||||
{
|
||||
if (current.TrackStatus.Ahead.Contains(commit.SHA))
|
||||
if (current.Ahead.Contains(commit.SHA))
|
||||
{
|
||||
var upstream = repo.Branches.Find(x => x.FullName.Equals(current.Upstream, StringComparison.Ordinal));
|
||||
var pushRevision = new MenuItem();
|
||||
@@ -911,7 +911,7 @@ namespace SourceGit.Views
|
||||
var fastForward = new MenuItem();
|
||||
fastForward.Header = App.Text("BranchCM.FastForward", upstream);
|
||||
fastForward.Icon = App.CreateMenuIcon("Icons.FastForward");
|
||||
fastForward.IsEnabled = current.TrackStatus.Ahead.Count == 0 && current.TrackStatus.Behind.Count > 0;
|
||||
fastForward.IsEnabled = current.Ahead.Count == 0 && current.Behind.Count > 0;
|
||||
fastForward.Click += async (_, e) =>
|
||||
{
|
||||
var b = repo.Branches.Find(x => x.FriendlyName == upstream);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
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"
|
||||
@@ -52,11 +53,12 @@
|
||||
<Border Grid.Row="2" Margin="8,0,8,8" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
|
||||
<Grid RowDefinitions="*,3,*">
|
||||
<v:InteractiveRebaseListBox Grid.Row="0"
|
||||
x:Name="IRItemListBox"
|
||||
Focusable="True"
|
||||
Background="{DynamicResource Brush.Contents}"
|
||||
ItemsSource="{Binding Items}"
|
||||
SelectionMode="Single"
|
||||
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
|
||||
SelectionMode="Multiple"
|
||||
SelectedItem="{Binding PreSelected, Mode=OneWay}"
|
||||
SelectionChanged="OnRowsSelectionChanged"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
@@ -176,21 +178,38 @@
|
||||
BorderThickness="0,1,0,0"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"/>
|
||||
|
||||
<Grid Grid.Row="2">
|
||||
<Path Width="128" Height="128"
|
||||
Data="{StaticResource Icons.Detail}"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
IsVisible="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNull}}"/>
|
||||
<ContentControl Grid.Row="2">
|
||||
<ContentControl.Content>
|
||||
<Binding Path="Detail">
|
||||
<Binding.TargetNullValue>
|
||||
<Path Width="128" Height="128"
|
||||
Data="{StaticResource Icons.Detail}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Fill="{DynamicResource Brush.FG2}"/>
|
||||
</Binding.TargetNullValue>
|
||||
</Binding>
|
||||
</ContentControl.Content>
|
||||
|
||||
<ContentControl Content="{Binding DetailContext}" IsVisible="{Binding SelectedItem, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="vm:CommitDetail">
|
||||
<v:CommitDetail/>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="m:Count">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Path Width="128" Height="128"
|
||||
Data="{StaticResource Icons.Detail}"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Margin="0,16"
|
||||
FontSize="24" FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
Text="{Binding Value, Converter={x:Static c:StringConverters.FormatByResourceKey}, ConverterParameter='Histories.Selected'}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="vm:CommitDetail">
|
||||
<v:CommitDetail/>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
@@ -14,17 +15,19 @@ namespace SourceGit.Views
|
||||
{
|
||||
protected override Type StyleKeyOverride => typeof(ListBox);
|
||||
|
||||
/// <summary>
|
||||
/// Prevent ListBox handle the arrow keys.
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.InteractiveRebase vm)
|
||||
if (DataContext is not ViewModels.InteractiveRebase vm || SelectedItems == null)
|
||||
return;
|
||||
|
||||
var item = vm.SelectedItem;
|
||||
if (item == null)
|
||||
var items = new List<ViewModels.InteractiveRebaseItem>();
|
||||
foreach (var item in SelectedItems)
|
||||
{
|
||||
if (item is ViewModels.InteractiveRebaseItem rebaseItem)
|
||||
items.Add(rebaseItem);
|
||||
}
|
||||
|
||||
if (items.Count == 0)
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
return;
|
||||
@@ -32,44 +35,54 @@ namespace SourceGit.Views
|
||||
|
||||
if (e.Key == Key.P)
|
||||
{
|
||||
vm.ChangeAction(item, Models.InteractiveRebaseAction.Pick);
|
||||
vm.ChangeAction(items, Models.InteractiveRebaseAction.Pick);
|
||||
MoveSelection(NavigationDirection.Next);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.E)
|
||||
{
|
||||
vm.ChangeAction(item, Models.InteractiveRebaseAction.Edit);
|
||||
vm.ChangeAction(items, Models.InteractiveRebaseAction.Edit);
|
||||
MoveSelection(NavigationDirection.Next);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.R)
|
||||
{
|
||||
vm.ChangeAction(item, Models.InteractiveRebaseAction.Reword);
|
||||
vm.ChangeAction(items, Models.InteractiveRebaseAction.Reword);
|
||||
if (items.Count == 1)
|
||||
this.FindAncestorOfType<InteractiveRebase>()?.OpenCommitMessageEditor(items[0]);
|
||||
else
|
||||
MoveSelection(NavigationDirection.Next);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.S)
|
||||
{
|
||||
vm.ChangeAction(item, Models.InteractiveRebaseAction.Squash);
|
||||
vm.ChangeAction(items, Models.InteractiveRebaseAction.Squash);
|
||||
MoveSelection(NavigationDirection.Next);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.F)
|
||||
{
|
||||
vm.ChangeAction(item, Models.InteractiveRebaseAction.Fixup);
|
||||
vm.ChangeAction(items, Models.InteractiveRebaseAction.Fixup);
|
||||
MoveSelection(NavigationDirection.Next);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.D)
|
||||
{
|
||||
vm.ChangeAction(item, Models.InteractiveRebaseAction.Drop);
|
||||
vm.ChangeAction(items, Models.InteractiveRebaseAction.Drop);
|
||||
MoveSelection(NavigationDirection.Next);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
|
||||
else if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control) && items.Count == 1)
|
||||
{
|
||||
if (e.Key == Key.Up)
|
||||
{
|
||||
vm.MoveItemUp(item);
|
||||
vm.MoveItemUp(items[0]);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Down)
|
||||
{
|
||||
vm.MoveItemDown(item);
|
||||
vm.MoveItemDown(items[0]);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
@@ -85,14 +98,14 @@ namespace SourceGit.Views
|
||||
{
|
||||
CloseOnESC = true;
|
||||
InitializeComponent();
|
||||
IRItemListBox?.Focus();
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
public void OpenCommitMessageEditor(ViewModels.InteractiveRebaseItem item)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
var list = this.FindDescendantOfType<InteractiveRebaseListBox>();
|
||||
list?.Focus();
|
||||
var dialog = new CommitMessageEditor();
|
||||
dialog.AsBuiltin(item.FullMessage, msg => item.FullMessage = msg);
|
||||
dialog.ShowDialog(this);
|
||||
}
|
||||
|
||||
private void CloseWindow(object _1, RoutedEventArgs _2)
|
||||
@@ -100,21 +113,27 @@ namespace SourceGit.Views
|
||||
Close();
|
||||
}
|
||||
|
||||
private void OnRowsSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
private void OnRowsSelectionChanged(object _, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (!_firstSelectionChangedHandled &&
|
||||
sender is InteractiveRebaseListBox list &&
|
||||
list.SelectedItem is ViewModels.InteractiveRebaseItem item)
|
||||
{
|
||||
if (DataContext is not ViewModels.InteractiveRebase vm)
|
||||
return;
|
||||
|
||||
var isFirstTimeHere = !_firstSelectionChangedHandled;
|
||||
if (isFirstTimeHere)
|
||||
_firstSelectionChangedHandled = true;
|
||||
|
||||
if (item.Action == Models.InteractiveRebaseAction.Reword)
|
||||
{
|
||||
var dialog = new CommitMessageEditor();
|
||||
dialog.AsBuiltin(item.FullMessage, msg => item.FullMessage = msg);
|
||||
dialog.ShowDialog(this);
|
||||
}
|
||||
var selected = IRItemListBox.SelectedItems ?? new List<object>();
|
||||
var items = new List<ViewModels.InteractiveRebaseItem>();
|
||||
foreach (var item in selected)
|
||||
{
|
||||
if (item is ViewModels.InteractiveRebaseItem rebaseItem)
|
||||
items.Add(rebaseItem);
|
||||
}
|
||||
|
||||
vm.SelectCommits(items);
|
||||
|
||||
if (items.Count == 1 && isFirstTimeHere && items[0].Action == Models.InteractiveRebaseAction.Reword)
|
||||
OpenCommitMessageEditor(items[0]);
|
||||
}
|
||||
|
||||
private void OnSetupRowHeaderDragDrop(object sender, RoutedEventArgs e)
|
||||
@@ -195,11 +214,7 @@ namespace SourceGit.Views
|
||||
private void OnOpenCommitMessageEditor(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button { DataContext: ViewModels.InteractiveRebaseItem item })
|
||||
{
|
||||
var dialog = new CommitMessageEditor();
|
||||
dialog.AsBuiltin(item.FullMessage, msg => item.FullMessage = msg);
|
||||
dialog.ShowDialog(this);
|
||||
}
|
||||
OpenCommitMessageEditor(item);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
@@ -247,17 +262,36 @@ namespace SourceGit.Views
|
||||
menuItem.Icon = new Ellipse() { Width = 14, Height = 14, Fill = iconBrush };
|
||||
menuItem.Header = header;
|
||||
menuItem.Tag = hotkey;
|
||||
menuItem.Click += (_, e) =>
|
||||
{
|
||||
if (DataContext is ViewModels.InteractiveRebase vm)
|
||||
vm.ChangeAction(item, action);
|
||||
|
||||
e.Handled = true;
|
||||
};
|
||||
menuItem.Click += (_, __) => ChangeItemsAction(item, action);
|
||||
|
||||
flyout.Items.Add(menuItem);
|
||||
}
|
||||
|
||||
private void ChangeItemsAction(ViewModels.InteractiveRebaseItem target, Models.InteractiveRebaseAction action)
|
||||
{
|
||||
if (DataContext is not ViewModels.InteractiveRebase vm)
|
||||
return;
|
||||
|
||||
var selected = IRItemListBox.SelectedItems ?? new List<object>();
|
||||
var items = new List<ViewModels.InteractiveRebaseItem>();
|
||||
foreach (var item in selected)
|
||||
{
|
||||
if (item is ViewModels.InteractiveRebaseItem rebaseItem)
|
||||
items.Add(rebaseItem);
|
||||
}
|
||||
|
||||
if (!items.Contains(target))
|
||||
{
|
||||
items.Clear();
|
||||
items.Add(target);
|
||||
}
|
||||
|
||||
vm.ChangeAction(items, action);
|
||||
|
||||
if (items.Count == 1 && action == Models.InteractiveRebaseAction.Reword)
|
||||
OpenCommitMessageEditor(items[0]);
|
||||
}
|
||||
|
||||
private bool _firstSelectionChangedHandled = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Custom TitleBar -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,32,32,*,Auto">
|
||||
<!-- Bottom border -->
|
||||
<Border Grid.Column="0" Grid.ColumnSpan="4"
|
||||
<Border Grid.Column="0" Grid.ColumnSpan="5"
|
||||
Background="{DynamicResource Brush.TitleBar}"
|
||||
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
|
||||
DoubleTapped="MaximizeOrRestoreWindow"
|
||||
@@ -31,9 +31,9 @@
|
||||
<Border Grid.Column="0" Width="72" IsVisible="{Binding #ThisControl.HasLeftCaptionButton}"/>
|
||||
|
||||
<!-- Menu (Windows/Linux) -->
|
||||
<Button Grid.Column="0" Classes="icon_button" VerticalAlignment="Bottom" Margin="6,0,2,3" IsVisible="{OnPlatform True, macOS=False}">
|
||||
<Button Grid.Column="0" Classes="icon_button" VerticalAlignment="Bottom" Margin="6,0,0,3" IsVisible="{OnPlatform True, macOS=False}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout Placement="BottomEdgeAlignedLeft" VerticalOffset="-8">
|
||||
<MenuFlyout Placement="BottomEdgeAlignedLeft" VerticalOffset="-6">
|
||||
<MenuItem Header="{DynamicResource Text.Preferences}" Command="{x:Static s:App.OpenPreferencesCommand}" InputGesture="Ctrl+,">
|
||||
<MenuItem.Icon>
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.Settings}"/>
|
||||
@@ -84,11 +84,27 @@
|
||||
Fill="{Binding ActiveWorkspace.Brush}"/>
|
||||
</Button>
|
||||
|
||||
<!-- Pages Switcher Toggle Button -->
|
||||
<Button Grid.Column="2" Classes="icon_button" VerticalAlignment="Bottom" Margin="0,0,0,1" Command="{Binding OpenTabSwitcher}">
|
||||
<ToolTip.Tip>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{DynamicResource Text.Launcher.Pages}"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBlock Margin="8,0,0,0"
|
||||
Text="{OnPlatform Ctrl+P, macOS=⌘+P}"
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForeground}"
|
||||
VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</ToolTip.Tip>
|
||||
<Path Width="13" Height="13" Margin="0,2,0,0" Data="{StaticResource Icons.Tabs}"/>
|
||||
</Button>
|
||||
|
||||
<!-- Pages Tabs -->
|
||||
<v:LauncherTabBar Grid.Column="2" Height="30" Margin="0,0,16,0" VerticalAlignment="Bottom"/>
|
||||
<v:LauncherTabBar Grid.Column="3" Height="30" Margin="0,0,16,0" VerticalAlignment="Bottom"/>
|
||||
|
||||
<!-- Caption Buttons (Windows/Linux) -->
|
||||
<Border Grid.Column="3" Margin="16,0,0,0" IsVisible="{Binding #ThisControl.HasRightCaptionButton}">
|
||||
<Border Grid.Column="4" Margin="16,0,0,0" IsVisible="{Binding #ThisControl.HasRightCaptionButton}">
|
||||
<v:CaptionButtons Height="30" VerticalAlignment="Top"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
@@ -4,6 +4,7 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
@@ -317,6 +318,20 @@ namespace SourceGit.Views
|
||||
{
|
||||
var pref = ViewModels.Preferences.Instance;
|
||||
var menu = new ContextMenu();
|
||||
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
||||
menu.VerticalOffset = -6;
|
||||
|
||||
var groupHeader = new TextBlock()
|
||||
{
|
||||
Text = App.Text("Launcher.Workspaces"),
|
||||
FontWeight = FontWeight.Bold,
|
||||
};
|
||||
|
||||
var workspaces = new MenuItem();
|
||||
workspaces.Header = groupHeader;
|
||||
workspaces.Tag = OperatingSystem.IsMacOS() ? "⌘+⇧+P" : "Ctrl+Shift+P";
|
||||
workspaces.IsEnabled = false;
|
||||
menu.Items.Add(workspaces);
|
||||
|
||||
for (var i = 0; i < pref.Workspaces.Count; i++)
|
||||
{
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:LauncherPage">
|
||||
<Grid ColumnDefinitions="Auto,6,*" Background="Transparent" DoubleTapped="OnItemDoubleTapped">
|
||||
<Grid ColumnDefinitions="Auto,6,*" Background="Transparent" Tapped="OnItemTapped">
|
||||
<Path Grid.Column="0"
|
||||
Width="12" Height="12"
|
||||
Fill="{Binding Node.Bookmark, Converter={x:Static c:IntConverters.ToBookmarkBrush}}"
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void OnItemDoubleTapped(object sender, TappedEventArgs e)
|
||||
private void OnItemTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.LauncherPageSwitcher switcher)
|
||||
{
|
||||
@@ -32,14 +32,28 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnSearchBoxKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Down && PagesListBox.ItemCount > 0)
|
||||
if (PagesListBox.ItemCount == 0)
|
||||
return;
|
||||
|
||||
if (e.Key == Key.Down)
|
||||
{
|
||||
PagesListBox.Focus(NavigationMethod.Directional);
|
||||
|
||||
if (PagesListBox.SelectedIndex < 0)
|
||||
PagesListBox.SelectedIndex = 0;
|
||||
else if (PagesListBox.SelectedIndex < PagesListBox.ItemCount)
|
||||
if (PagesListBox.SelectedIndex < PagesListBox.ItemCount - 1)
|
||||
PagesListBox.SelectedIndex++;
|
||||
else
|
||||
PagesListBox.SelectedIndex = 0;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Up)
|
||||
{
|
||||
PagesListBox.Focus(NavigationMethod.Directional);
|
||||
|
||||
if (PagesListBox.SelectedIndex > 0)
|
||||
PagesListBox.SelectedIndex--;
|
||||
else
|
||||
PagesListBox.SelectedIndex = PagesListBox.ItemCount - 1;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
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"
|
||||
@@ -51,7 +52,11 @@
|
||||
<ToolTip.Tip>
|
||||
<Grid>
|
||||
<TextBlock Text="{DynamicResource Text.Welcome}" IsVisible="{Binding !Node.IsRepository}"/>
|
||||
<TextBlock Text="{Binding Node.Id}" IsVisible="{Binding Node.IsRepository}"/>
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding Node.IsRepository}">
|
||||
<TextBlock Text="{Binding Node.Id}"/>
|
||||
<TextBlock Text="{Binding DirtyState, Converter={x:Static c:DirtyStateConverters.ToDesc}}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ToolTip.Tip>
|
||||
|
||||
@@ -78,8 +83,8 @@
|
||||
Width="8" Height="8"
|
||||
Margin="0,0,6,0"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding DirtyBrush, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
Fill="{Binding DirtyBrush}"/>
|
||||
IsVisible="{Binding DirtyState, Converter={x:Static ObjectConverters.IsNotNull}, ConverterParameter={x:Static m:DirtyState.None}}"
|
||||
Fill="{Binding DirtyState, Converter={x:Static c:DirtyStateConverters.ToBrush}}"/>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="primary"
|
||||
@@ -147,114 +152,7 @@
|
||||
<Path Width="8" Height="14" Stretch="Fill" Data="{StaticResource Icons.TriangleRight}"/>
|
||||
</RepeatButton>
|
||||
|
||||
<Button x:Name="PageSelector" Classes="icon_button" Width="16" Height="16" Margin="8,0">
|
||||
<Button.Flyout>
|
||||
<Flyout Opened="OnTabsDropdownOpened" Closed="OnTabsDropdownClosed">
|
||||
<Grid RowDefinitions="28,Auto" KeyDown="OnTabsDropdownKeyDown" LostFocus="OnTabsDropdownLostFocus">
|
||||
<TextBox Grid.Row="0"
|
||||
Height="24"
|
||||
Margin="4,0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="12"
|
||||
Text="{Binding #ThisControl.SearchFilter, Mode=TwoWay}"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
VerticalContentAlignment="Center"
|
||||
KeyDown="OnTabsDropdownSearchBoxKeyDown"
|
||||
v:AutoFocusBehaviour.IsEnabled="True">
|
||||
<TextBox.InnerLeftContent>
|
||||
<Path Width="14" Height="14"
|
||||
Margin="6,0,0,0"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
Data="{StaticResource Icons.Search}"/>
|
||||
</TextBox.InnerLeftContent>
|
||||
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button"
|
||||
Width="16"
|
||||
Margin="0,0,6,0"
|
||||
Click="OnClearSearchFilter"
|
||||
IsVisible="{Binding #ThisControl.SearchFilter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||
HorizontalAlignment="Right">
|
||||
<Path Width="14" Height="14"
|
||||
Margin="0,1,0,0"
|
||||
Fill="{DynamicResource Brush.FG1}"
|
||||
Data="{StaticResource Icons.Clear}"/>
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
|
||||
<ListBox Grid.Row="1"
|
||||
x:Name="TabsDropdownList"
|
||||
Focusable="True"
|
||||
Width="200"
|
||||
MaxHeight="400"
|
||||
Margin="0,4,0,0"
|
||||
Background="Transparent"
|
||||
SelectionMode="Single"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
ItemsSource="{Binding #ThisControl.SelectablePages}"
|
||||
SelectedItem="{Binding ActivePage, Mode=OneWay}">
|
||||
<ListBox.Styles>
|
||||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="MinHeight" Value="26"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ListBox">
|
||||
<Setter Property="FocusAdorner">
|
||||
<FocusAdornerTemplate>
|
||||
<Grid/>
|
||||
</FocusAdornerTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:LauncherPage">
|
||||
<Grid ColumnDefinitions="Auto,*" Background="Transparent" Tapped="OnTabsDropdownItemTapped">
|
||||
<Path Grid.Column="0"
|
||||
Width="12" Height="12" Margin="12,0"
|
||||
Fill="{Binding Node.Bookmark, Converter={x:Static c:IntConverters.ToBookmarkBrush}}"
|
||||
Data="{StaticResource Icons.Bookmark}"
|
||||
IsVisible="{Binding Node.IsRepository}"
|
||||
IsHitTestVisible="False"/>
|
||||
<Path Grid.Column="0"
|
||||
Width="12" Height="12" Margin="12,0"
|
||||
Fill="{DynamicResource Brush.FG1}"
|
||||
Data="{StaticResource Icons.Repositories}"
|
||||
IsVisible="{Binding !Node.IsRepository}"
|
||||
IsHitTestVisible="False"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="primary"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Node.Name}"
|
||||
IsVisible="{Binding Node.IsRepository}"
|
||||
IsHitTestVisible="False"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="primary"
|
||||
VerticalAlignment="Center"
|
||||
Text="{DynamicResource Text.PageTabBar.Welcome.Title}"
|
||||
IsVisible="{Binding !Node.IsRepository}"
|
||||
IsHitTestVisible="False"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
<Path Width="14" Height="14" Data="{StaticResource Icons.CircleDown}"/>
|
||||
</Button>
|
||||
|
||||
<Button Classes="icon_button" Width="16" Height="16" Command="{Binding AddNewTab}">
|
||||
<Button Classes="icon_button" Width="16" Height="16" Margin="4,0,0,0" Command="{Binding AddNewTab}">
|
||||
<ToolTip.Tip>
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<TextBlock Text="{DynamicResource Text.PageTabBar.New}" VerticalAlignment="Center"/>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
@@ -20,20 +19,6 @@ namespace SourceGit.Views
|
||||
set => SetValue(IsScrollerVisibleProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string> SearchFilterProperty =
|
||||
AvaloniaProperty.Register<LauncherTabBar, string>(nameof(SearchFilter));
|
||||
|
||||
public string SearchFilter
|
||||
{
|
||||
get => GetValue(SearchFilterProperty);
|
||||
set => SetValue(SearchFilterProperty, value);
|
||||
}
|
||||
|
||||
public AvaloniaList<ViewModels.LauncherPage> SelectablePages
|
||||
{
|
||||
get;
|
||||
} = [];
|
||||
|
||||
public LauncherTabBar()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -141,14 +126,6 @@ namespace SourceGit.Views
|
||||
context.DrawGeometry(fill, stroke, geo);
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == SearchFilterProperty)
|
||||
UpdateSelectablePages();
|
||||
}
|
||||
|
||||
private void ScrollTabs(object _, PointerWheelEventArgs e)
|
||||
{
|
||||
if (!e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
@@ -337,97 +314,6 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTabsDropdownOpened(object sender, EventArgs e)
|
||||
{
|
||||
UpdateSelectablePages();
|
||||
}
|
||||
|
||||
private void OnTabsDropdownClosed(object sender, EventArgs e)
|
||||
{
|
||||
SelectablePages.Clear();
|
||||
SearchFilter = string.Empty;
|
||||
}
|
||||
|
||||
private void OnTabsDropdownKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Escape)
|
||||
{
|
||||
PageSelector.Flyout?.Hide();
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Enter)
|
||||
{
|
||||
if (TabsDropdownList.SelectedItem is ViewModels.LauncherPage page &&
|
||||
DataContext is ViewModels.Launcher vm)
|
||||
{
|
||||
vm.ActivePage = page;
|
||||
PageSelector.Flyout?.Hide();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTabsDropdownSearchBoxKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Down && TabsDropdownList.ItemCount > 0)
|
||||
{
|
||||
TabsDropdownList.Focus(NavigationMethod.Directional);
|
||||
|
||||
if (TabsDropdownList.SelectedIndex < 0)
|
||||
TabsDropdownList.SelectedIndex = 0;
|
||||
else if (TabsDropdownList.SelectedIndex < TabsDropdownList.ItemCount)
|
||||
TabsDropdownList.SelectedIndex++;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTabsDropdownLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Control { IsFocused: false, IsKeyboardFocusWithin: false })
|
||||
PageSelector.Flyout?.Hide();
|
||||
}
|
||||
|
||||
private void OnClearSearchFilter(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SearchFilter = string.Empty;
|
||||
}
|
||||
|
||||
private void OnTabsDropdownItemTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (sender is Control { DataContext: ViewModels.LauncherPage page } &&
|
||||
DataContext is ViewModels.Launcher vm)
|
||||
{
|
||||
vm.ActivePage = page;
|
||||
PageSelector.Flyout?.Hide();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSelectablePages()
|
||||
{
|
||||
if (DataContext is not ViewModels.Launcher vm)
|
||||
return;
|
||||
|
||||
SelectablePages.Clear();
|
||||
|
||||
var pages = vm.Pages;
|
||||
var filter = SearchFilter?.Trim() ?? "";
|
||||
if (string.IsNullOrEmpty(filter))
|
||||
{
|
||||
SelectablePages.AddRange(pages);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var page in pages)
|
||||
{
|
||||
var node = page.Node;
|
||||
if (node.Name.Contains(filter, StringComparison.OrdinalIgnoreCase) ||
|
||||
(node.IsRepository && node.Id.Contains(filter, StringComparison.OrdinalIgnoreCase)))
|
||||
SelectablePages.Add(page);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _pressedTab = false;
|
||||
private Point _pressedTabPosition = new();
|
||||
private bool _startDragTab = false;
|
||||
|
||||
@@ -169,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,Auto" ColumnDefinitions="Auto,*">
|
||||
<Grid Margin="8" RowDefinitions="32,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"
|
||||
@@ -276,6 +276,11 @@
|
||||
IsChecked="{Binding UseFixedTabWidth, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="8" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.Appearance.UseAutoHideScrollBars}"
|
||||
IsChecked="{Binding UseAutoHideScrollBars, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="9" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.Appearance.UseNativeWindowFrame}"
|
||||
IsChecked="{Binding UseSystemWindowFrame, Mode=OneTime}"
|
||||
@@ -788,7 +793,10 @@
|
||||
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Model, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preferences.AI.ApiKey}"/>
|
||||
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding ApiKey, Mode=TwoWay}" PasswordChar="*"/>
|
||||
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding ApiKey, Mode=TwoWay}" PasswordChar="*" RevealPassword="{Binding ReadApiKeyFromEnv, Mode=OneWay}"/>
|
||||
<CheckBox Margin="0,4,0,0"
|
||||
Content="{DynamicResource Text.Preferences.AI.ReadApiKeyFromEnv}"
|
||||
IsChecked="{Binding ReadApiKeyFromEnv, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preferences.AI.AnalyzeDiffPrompt}"/>
|
||||
<TextBox Height="120"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.RenameBranch}"/>
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto" ColumnDefinitions="120,*">
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="120,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
@@ -26,20 +26,13 @@
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.RenameBranch.Name}"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1"
|
||||
Height="26"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.RenameBranch.Name.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
|
||||
<StackPanel Grid.Row="2" Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
IsVisible="{Binding Name, Converter={x:Static c:StringConverters.ContainsSpaces}}">
|
||||
<Path Width="10" Height="10" Data="{StaticResource Icons.Error}" Fill="DarkOrange"/>
|
||||
<TextBlock Classes="small" Text="{DynamicResource Text.CreateBranch.Name.WarnSpace}" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
<v:BranchOrTagNameTextBox Grid.Row="1" Grid.Column="1"
|
||||
Height="26"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.RenameBranch.Name.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -218,10 +218,10 @@
|
||||
<ToggleButton Grid.Row="0" Classes="group_expander" IsChecked="{Binding IsLocalBranchGroupExpanded, Mode=TwoWay}">
|
||||
<Grid ColumnDefinitions="16,*,Auto,Auto">
|
||||
<Path Grid.Column="0" Width="11" Height="11" HorizontalAlignment="Left" Data="{StaticResource Icons.Local}" Fill="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0">
|
||||
<Run Text="{DynamicResource Text.Repository.LocalBranches}"/>
|
||||
<Run Text="{Binding LocalBranchesCount, StringFormat='({0})', Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<TextBlock Classes="group_header_label" Text="{DynamicResource Text.Repository.LocalBranches}"/>
|
||||
<TextBlock Classes="group_header_label" Text="{Binding LocalBranchesCount, StringFormat='({0})'}" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
<Button Grid.Column="2"
|
||||
Classes="icon_button"
|
||||
Width="14"
|
||||
@@ -251,10 +251,10 @@
|
||||
<ToggleButton Grid.Row="2" Classes="group_expander" IsChecked="{Binding IsRemoteGroupExpanded, Mode=TwoWay}">
|
||||
<Grid ColumnDefinitions="16,*,Auto,Auto">
|
||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Data="{StaticResource Icons.Remotes}" Fill="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0">
|
||||
<Run Text="{DynamicResource Text.Repository.Remotes}"/>
|
||||
<Run Text="{Binding Remotes, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<TextBlock Classes="group_header_label" Text="{DynamicResource Text.Repository.Remotes}"/>
|
||||
<TextBlock Classes="group_header_label" Text="{Binding Remotes, Converter={x:Static c:ListConverters.ToCount}}" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
<Button Grid.Column="2"
|
||||
Classes="icon_button"
|
||||
Width="14"
|
||||
@@ -284,10 +284,10 @@
|
||||
<ToggleButton Grid.Row="4" Classes="group_expander" IsChecked="{Binding IsTagGroupExpanded, Mode=TwoWay}">
|
||||
<Grid ColumnDefinitions="16,*,Auto,Auto,Auto">
|
||||
<Path Grid.Column="0" Width="11" Height="11" Margin="2,1,0,0" HorizontalAlignment="Left" Data="{StaticResource Icons.Tags}" Fill="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0">
|
||||
<Run Text="{DynamicResource Text.Repository.Tags}"/>
|
||||
<Run Text="{Binding Tags, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<TextBlock Classes="group_header_label" Text="{DynamicResource Text.Repository.Tags}"/>
|
||||
<TextBlock Classes="group_header_label" Text="{Binding Tags, Converter={x:Static c:ListConverters.ToCount}}" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
<ToggleButton Grid.Column="2"
|
||||
Classes="show_as_tree"
|
||||
Width="14"
|
||||
@@ -329,10 +329,10 @@
|
||||
<ToggleButton Grid.Row="6" Classes="group_expander" IsChecked="{Binding IsSubmoduleGroupExpanded, Mode=TwoWay}">
|
||||
<Grid ColumnDefinitions="16,*,Auto,Auto,Auto">
|
||||
<Path Grid.Column="0" Width="10" Height="10" Margin="2,0,0,0" HorizontalAlignment="Left" Data="{StaticResource Icons.Submodules}" Fill="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0">
|
||||
<Run Text="{DynamicResource Text.Repository.Submodules}"/>
|
||||
<Run Text="{Binding Submodules, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<TextBlock Classes="group_header_label" Text="{DynamicResource Text.Repository.Submodules}"/>
|
||||
<TextBlock Classes="group_header_label" Text="{Binding Submodules, Converter={x:Static c:ListConverters.ToCount}}" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
<ToggleButton Grid.Column="2"
|
||||
Classes="show_as_tree"
|
||||
Width="14"
|
||||
@@ -371,10 +371,10 @@
|
||||
<ToggleButton Grid.Row="8" Classes="group_expander" IsChecked="{Binding IsWorktreeGroupExpanded, Mode=TwoWay}">
|
||||
<Grid ColumnDefinitions="16,*,Auto,Auto">
|
||||
<Path Grid.Column="0" Width="11" Height="11" Margin="1,0,0,0" HorizontalAlignment="Left" Data="{StaticResource Icons.Worktrees}" Fill="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0">
|
||||
<Run Text="{DynamicResource Text.Repository.Worktrees}"/>
|
||||
<Run Text="{Binding Worktrees, Converter={x:Static c:ListConverters.ToCount}, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<TextBlock Classes="group_header_label" Text="{DynamicResource Text.Repository.Worktrees}"/>
|
||||
<TextBlock Classes="group_header_label" Text="{Binding Worktrees, Converter={x:Static c:ListConverters.ToCount}}" Margin="4,0,0,0"/>
|
||||
</StackPanel>
|
||||
<Button Grid.Column="2"
|
||||
Classes="icon_button"
|
||||
Width="14"
|
||||
@@ -777,7 +777,7 @@
|
||||
</MultiBinding>
|
||||
</Border.IsVisible>
|
||||
|
||||
<Grid Height="28" ColumnDefinitions="Auto,*,Auto">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<Path Grid.Column="0"
|
||||
Margin="8,0,0,0"
|
||||
Width="12" Height="12"
|
||||
@@ -791,10 +791,10 @@
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
IsVisible="{Binding HistoriesFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Excluded}}"/>
|
||||
|
||||
<ItemsControl Grid.Column="1" Margin="8,0,0,0" ItemsSource="{Binding Settings.HistoriesFilters}">
|
||||
<ItemsControl Grid.Column="1" Margin="8,4" ItemsSource="{Binding Settings.HistoriesFilters}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel Orientation="Horizontal" VerticalAlignment="Center"/>
|
||||
<WrapPanel Orientation="Horizontal" ItemHeight="22"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
@@ -804,7 +804,8 @@
|
||||
Margin="0,0,6,0"
|
||||
CornerRadius="12"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{Binding Mode, Converter={x:Static c:FilterModeConverters.ToBorderBrush}}">
|
||||
BorderBrush="{Binding Mode, Converter={x:Static c:FilterModeConverters.ToBorderBrush}}"
|
||||
VerticalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal" Margin="8,0">
|
||||
<Path Width="10" Height="10" Data="{StaticResource Icons.Branch}" IsVisible="{Binding IsBranch}"/>
|
||||
<Path Width="10" Height="10" Data="{StaticResource Icons.Tag}" IsVisible="{Binding !IsBranch}"/>
|
||||
|
||||
@@ -190,6 +190,17 @@ namespace SourceGit.Views
|
||||
{
|
||||
var menu = new ContextMenu();
|
||||
|
||||
var switchTo = new MenuItem();
|
||||
switchTo.Header = App.Text("Worktree.Open");
|
||||
switchTo.Icon = App.CreateMenuIcon("Icons.Folder.Open");
|
||||
switchTo.Click += (_, ev) =>
|
||||
{
|
||||
repo.OpenWorktree(worktree);
|
||||
ev.Handled = true;
|
||||
};
|
||||
menu.Items.Add(switchTo);
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
|
||||
if (worktree.IsLocked)
|
||||
{
|
||||
var unlock = new MenuItem();
|
||||
|
||||
@@ -374,8 +374,7 @@
|
||||
<CheckBox Grid.Row="7" Grid.Column="1"
|
||||
Margin="0,4,0,0"
|
||||
Content="{DynamicResource Text.Configure.IssueTracker.Share}"
|
||||
IsChecked="{Binding IsShared, Mode=TwoWay}"
|
||||
Click="OnIssueTrackerIsSharedChanged"/>
|
||||
IsChecked="{Binding IsShared, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
|
||||
@@ -50,15 +50,15 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnNewCustomIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnNewCustomIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
await vm.AddIssueTrackerAsync("New Issue Tracker", @"#(\d+)", "https://xxx/$1");
|
||||
vm.AddIssueTracker("New Issue Tracker", @"#(\d+)", "https://xxx/$1");
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGitHubIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGitHubIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -73,17 +73,17 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("GitHub Issue", @"#(\d+)", link);
|
||||
vm.AddIssueTracker("GitHub Issue", @"#(\d+)", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddJiraIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddJiraIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
await vm.AddIssueTrackerAsync(
|
||||
vm.AddIssueTracker(
|
||||
"Jira Tracker",
|
||||
@"PROJ-(\d+)",
|
||||
"https://jira.yourcompany.com/browse/PROJ-$1");
|
||||
@@ -92,11 +92,11 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddAzureWorkItemTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddAzureWorkItemTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
await vm.AddIssueTrackerAsync(
|
||||
vm.AddIssueTracker(
|
||||
"Azure DevOps Tracker",
|
||||
@"#(\d+)",
|
||||
"https://dev.azure.com/yourcompany/workspace/_workitems/edit/$1");
|
||||
@@ -105,7 +105,7 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGitLabIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGitLabIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -117,13 +117,13 @@ namespace SourceGit.Views
|
||||
break;
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("GitLab Issue", @"#(\d+)", link);
|
||||
vm.AddIssueTracker("GitLab Issue", @"#(\d+)", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGitLabMergeRequestTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGitLabMergeRequestTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -135,13 +135,13 @@ namespace SourceGit.Views
|
||||
break;
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("GitLab MR", @"!(\d+)", link);
|
||||
vm.AddIssueTracker("GitLab MR", @"!(\d+)", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGiteeIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGiteeIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -156,13 +156,13 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("Gitee Issue", @"#([0-9A-Z]{6,10})", link);
|
||||
vm.AddIssueTracker("Gitee Issue", @"#([0-9A-Z]{6,10})", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGiteePullRequestTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGiteePullRequestTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -177,17 +177,17 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("Gitee Pull Request", @"!(\d+)", link);
|
||||
vm.AddIssueTracker("Gitee Pull Request", @"!(\d+)", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGerritChangeIdTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGerritChangeIdTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
await vm.AddIssueTrackerAsync(
|
||||
vm.AddIssueTracker(
|
||||
"Gerrit Change-Id",
|
||||
@"(I[A-Za-z0-9]{40})",
|
||||
"https://gerrit.yourcompany.com/q/$1");
|
||||
@@ -196,18 +196,10 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnRemoveIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnRemoveIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
await vm.RemoveIssueTrackerAsync();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnIssueTrackerIsSharedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
await vm.ChangeIssueTrackerShareModeAsync();
|
||||
vm.RemoveIssueTracker();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
@@ -535,7 +535,7 @@ namespace SourceGit.Views
|
||||
history.Icon = App.CreateMenuIcon("Icons.Histories");
|
||||
history.Click += (_, ev) =>
|
||||
{
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo, file.Path, commit.SHA));
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo.FullPath, file.Path, commit.SHA));
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.ScanRepositories}"/>
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32" ColumnDefinitions="120,*">
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="120,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
@@ -20,7 +20,8 @@
|
||||
Height="28" Padding="4,0"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding ScanDirs, Mode=OneWay}"
|
||||
SelectedItem="{Binding Selected, Mode=TwoWay}">
|
||||
SelectedItem="{Binding Selected, Mode=TwoWay}"
|
||||
IsVisible="{Binding !UseCustomDir, Mode=OneWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="m:ScanDir">
|
||||
<Grid ColumnDefinitions="20,*,Auto">
|
||||
@@ -38,6 +39,21 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding CustomDir, Mode=TwoWay}"
|
||||
IsVisible="{Binding UseCustomDir, Mode=OneWay}">
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button" Width="30" Height="30" Click="OnSelectRootDir">
|
||||
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
|
||||
<CheckBox Grid.Row="1" Grid.Column="1"
|
||||
Content="{DynamicResource Text.ScanRepositories.UseCustomDir}"
|
||||
IsChecked="{Binding UseCustomDir, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
using System;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
@@ -8,5 +12,33 @@ namespace SourceGit.Views
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void OnSelectRootDir(object _, RoutedEventArgs e)
|
||||
{
|
||||
var provider = TopLevel.GetTopLevel(this)?.StorageProvider;
|
||||
if (provider == null)
|
||||
return;
|
||||
|
||||
if (DataContext is not ViewModels.ScanRepositories vm)
|
||||
return;
|
||||
|
||||
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
|
||||
try
|
||||
{
|
||||
var selected = await provider.OpenFolderPickerAsync(options);
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
var folder = selected[0];
|
||||
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
|
||||
vm.CustomDir = folderPath;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.RaiseException(string.Empty, $"Failed to select root scanning directory: {ex.Message}");
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace SourceGit.Views
|
||||
histories.Icon = App.CreateMenuIcon("Icons.Histories");
|
||||
histories.Click += (_, ev) =>
|
||||
{
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo, submodule.Path));
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo.FullPath, submodule.Path));
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<ContentControl Content="{Binding}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="vm:CombinedTextDiff">
|
||||
<Grid ColumnDefinitions="*,1,8">
|
||||
<Grid ColumnDefinitions="*,1,12">
|
||||
<v:CombinedTextDiffPresenter Grid.Column="0"
|
||||
FileName="{Binding File}"
|
||||
Foreground="{DynamicResource Brush.FG1}"
|
||||
|
||||
@@ -11,6 +11,7 @@ using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
using Avalonia.VisualTree;
|
||||
@@ -1334,6 +1335,8 @@ namespace SourceGit.Views
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
context.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, Bounds.Width, Bounds.Height));
|
||||
|
||||
var total = 0;
|
||||
if (DataContext is ViewModels.TwoSideTextDiff twoSideDiff)
|
||||
{
|
||||
@@ -1371,6 +1374,44 @@ namespace SourceGit.Views
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
|
||||
var range = DisplayRange;
|
||||
if (range == null || range.End == 0)
|
||||
return;
|
||||
|
||||
var total = 0;
|
||||
if (DataContext is ViewModels.TwoSideTextDiff twoSideDiff)
|
||||
{
|
||||
var halfWidth = Bounds.Width * 0.5;
|
||||
total = Math.Max(twoSideDiff.Old.Count, twoSideDiff.New.Count);
|
||||
}
|
||||
else if (DataContext is ViewModels.CombinedTextDiff combined)
|
||||
{
|
||||
var data = combined.Data;
|
||||
total = data.Lines.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var height = Bounds.Height;
|
||||
var startY = range.Start / (total * 1.0) * height;
|
||||
var endY = range.End / (total * 1.0) * height;
|
||||
var pressedY = e.GetPosition(this).Y;
|
||||
if (pressedY >= startY && pressedY <= endY)
|
||||
return;
|
||||
|
||||
var line = Math.Max(1, Math.Min(total, (int)Math.Ceiling(pressedY * total / height)));
|
||||
if (this.Parent is Control parent)
|
||||
parent.FindLogicalDescendantOfType<ThemedTextDiffPresenter>()?.ScrollToLine(line);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void RenderSingleSide(DrawingContext context, List<Models.TextDiffLine> lines, double x, double width)
|
||||
{
|
||||
var total = lines.Count;
|
||||
@@ -1414,6 +1455,7 @@ namespace SourceGit.Views
|
||||
get => GetValue(SelectedChunkProperty);
|
||||
set => SetValue(SelectedChunkProperty, value);
|
||||
}
|
||||
|
||||
public TextDiffView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
<v:CommitMessageTextBox Grid.Row="2" ShowAdvancedOptions="True" Text="{Binding CommitMessage, Mode=TwoWay}"/>
|
||||
|
||||
<!-- Commit Options -->
|
||||
<Grid Grid.Row="3" Margin="0,6,0,0" ColumnDefinitions="Auto,Auto,Auto,*,Auto,Auto,Auto">
|
||||
<Grid Grid.Row="3" Margin="0,6,0,0" ColumnDefinitions="Auto,Auto,Auto,Auto,*,Auto,Auto,Auto">
|
||||
<CheckBox Grid.Column="0"
|
||||
Height="24"
|
||||
Margin="1,0,0,0"
|
||||
@@ -256,6 +256,16 @@
|
||||
ToolTip.VerticalOffset="0"/>
|
||||
|
||||
<CheckBox Grid.Column="1"
|
||||
Height="24"
|
||||
Margin="12,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
IsChecked="{Binding NoVerifyOnCommit, Mode=TwoWay}"
|
||||
Content="{DynamicResource Text.WorkingCopy.NoVerify}"
|
||||
ToolTip.Tip="--no-verify"
|
||||
ToolTip.Placement="Top"
|
||||
ToolTip.VerticalOffset="0"/>
|
||||
|
||||
<CheckBox Grid.Column="2"
|
||||
Height="24"
|
||||
Margin="12,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
@@ -265,7 +275,7 @@
|
||||
ToolTip.Placement="Top"
|
||||
ToolTip.VerticalOffset="0"/>
|
||||
|
||||
<CheckBox Grid.Column="2"
|
||||
<CheckBox Grid.Column="3"
|
||||
Height="24"
|
||||
Margin="12,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
@@ -276,12 +286,12 @@
|
||||
ToolTip.Placement="Top"
|
||||
ToolTip.VerticalOffset="0"/>
|
||||
|
||||
<v:LoadingIcon Grid.Column="3"
|
||||
<v:LoadingIcon Grid.Column="4"
|
||||
Width="18" Height="18"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{Binding IsCommitting}"/>
|
||||
|
||||
<SplitButton Grid.Column="4"
|
||||
<SplitButton Grid.Column="5"
|
||||
Content="{DynamicResource Text.Repository.Continue}"
|
||||
Height="28"
|
||||
Margin="8,0,0,0"
|
||||
@@ -303,7 +313,7 @@
|
||||
</SplitButton.Flyout>
|
||||
</SplitButton>
|
||||
|
||||
<Button Grid.Column="4"
|
||||
<Button Grid.Column="5"
|
||||
Classes="flat primary"
|
||||
Content="{DynamicResource Text.WorkingCopy.Commit}"
|
||||
Height="28"
|
||||
@@ -336,7 +346,7 @@
|
||||
</Button>
|
||||
|
||||
<!-- Invisible button just to add another hotkey `Ctrl+Shift+Enter` to commit with auto-stage -->
|
||||
<Button Grid.Column="5"
|
||||
<Button Grid.Column="6"
|
||||
Width="0" Height="0"
|
||||
Background="Transparent"
|
||||
Click="OnCommitWithAutoStage"
|
||||
@@ -349,7 +359,7 @@
|
||||
</Button.IsEnabled>
|
||||
</Button>
|
||||
|
||||
<Button Grid.Column="6"
|
||||
<Button Grid.Column="7"
|
||||
Classes="flat"
|
||||
Content="{DynamicResource Text.WorkingCopy.CommitAndPush}"
|
||||
Height="28"
|
||||
|
||||
@@ -620,7 +620,7 @@ namespace SourceGit.Views
|
||||
history.Icon = App.CreateMenuIcon("Icons.Histories");
|
||||
history.Click += (_, e) =>
|
||||
{
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo, change.Path));
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo.FullPath, change.Path));
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
@@ -1086,7 +1086,7 @@ namespace SourceGit.Views
|
||||
history.Icon = App.CreateMenuIcon("Icons.Histories");
|
||||
history.Click += (_, e) =>
|
||||
{
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo, change.Path));
|
||||
App.ShowWindow(new ViewModels.FileHistories(repo.FullPath, change.Path));
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:Workspace">
|
||||
<Grid ColumnDefinitions="Auto,*" Background="Transparent" DoubleTapped="OnItemDoubleTapped">
|
||||
<Grid ColumnDefinitions="Auto,*" Background="Transparent" Tapped="OnItemTapped">
|
||||
<Path Grid.Column="0"
|
||||
Width="12" Height="12"
|
||||
Fill="{Binding Brush}"
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void OnItemDoubleTapped(object sender, TappedEventArgs e)
|
||||
private void OnItemTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.WorkspaceSwitcher switcher)
|
||||
{
|
||||
@@ -32,14 +32,28 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnSearchBoxKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Down && WorkspaceListBox.ItemCount > 0)
|
||||
if (WorkspaceListBox.ItemCount == 0)
|
||||
return;
|
||||
|
||||
if (e.Key == Key.Down)
|
||||
{
|
||||
WorkspaceListBox.Focus(NavigationMethod.Directional);
|
||||
|
||||
if (WorkspaceListBox.SelectedIndex < 0)
|
||||
WorkspaceListBox.SelectedIndex = 0;
|
||||
else if (WorkspaceListBox.SelectedIndex < WorkspaceListBox.ItemCount)
|
||||
if (WorkspaceListBox.SelectedIndex < WorkspaceListBox.ItemCount - 1)
|
||||
WorkspaceListBox.SelectedIndex++;
|
||||
else
|
||||
WorkspaceListBox.SelectedIndex = 0;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Up)
|
||||
{
|
||||
WorkspaceListBox.Focus(NavigationMethod.Directional);
|
||||
|
||||
if (WorkspaceListBox.SelectedIndex > 0)
|
||||
WorkspaceListBox.SelectedIndex--;
|
||||
else
|
||||
WorkspaceListBox.SelectedIndex = WorkspaceListBox.ItemCount - 1;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user